From 3be8563870963442b0455a353e02c459d51ebd19 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 23 Nov 2023 17:43:56 +0000 Subject: [PATCH 001/134] Refactor app container to modularity. --- bootstrap.php | 74 +- composer.json | 6 +- composer.lock | 70 +- .../Container/ContainerConfigurator.php | 153 ++++ .../Container/PackageProxyContainer.php | 102 +++ .../Container/ReadOnlyContainer.php | 138 ++++ .../Modularity/Module/ExecutableModule.php | 21 + .../Modularity/Module/ExtendingModule.php | 24 + .../Modularity/Module/FactoryModule.php | 18 + .../Inpsyde/Modularity/Module/Module.php | 20 + .../Module/ModuleClassNameIdTrait.php | 23 + .../Modularity/Module/ServiceModule.php | 21 + lib/packages/Inpsyde/Modularity/Package.php | 727 ++++++++++++++++++ .../Modularity/Properties/BaseProperties.php | 217 ++++++ .../Properties/LibraryProperties.php | 209 +++++ .../Properties/PluginProperties.php | 176 +++++ .../Modularity/Properties/Properties.php | 139 ++++ .../Modularity/Properties/ThemeProperties.php | 131 ++++ .../Container/ContainerExceptionInterface.php | 3 - .../Psr/Container/ContainerInterface.php | 9 +- .../Container/NotFoundExceptionInterface.php | 3 - src/DhiiToModularityModule.php | 128 +++ 22 files changed, 2367 insertions(+), 45 deletions(-) create mode 100644 lib/packages/Inpsyde/Modularity/Container/ContainerConfigurator.php create mode 100644 lib/packages/Inpsyde/Modularity/Container/PackageProxyContainer.php create mode 100644 lib/packages/Inpsyde/Modularity/Container/ReadOnlyContainer.php create mode 100644 lib/packages/Inpsyde/Modularity/Module/ExecutableModule.php create mode 100644 lib/packages/Inpsyde/Modularity/Module/ExtendingModule.php create mode 100644 lib/packages/Inpsyde/Modularity/Module/FactoryModule.php create mode 100644 lib/packages/Inpsyde/Modularity/Module/Module.php create mode 100644 lib/packages/Inpsyde/Modularity/Module/ModuleClassNameIdTrait.php create mode 100644 lib/packages/Inpsyde/Modularity/Module/ServiceModule.php create mode 100644 lib/packages/Inpsyde/Modularity/Package.php create mode 100644 lib/packages/Inpsyde/Modularity/Properties/BaseProperties.php create mode 100644 lib/packages/Inpsyde/Modularity/Properties/LibraryProperties.php create mode 100644 lib/packages/Inpsyde/Modularity/Properties/PluginProperties.php create mode 100644 lib/packages/Inpsyde/Modularity/Properties/Properties.php create mode 100644 lib/packages/Inpsyde/Modularity/Properties/ThemeProperties.php create mode 100644 src/DhiiToModularityModule.php diff --git a/bootstrap.php b/bootstrap.php index fe4552110..fe9a0799b 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -11,8 +11,11 @@ use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\CompositeContainer; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\DelegatingContainer; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ProxyContainer; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Package; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Properties\PluginProperties; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\DhiiToModularityModule; return function ( string $root_dir, @@ -34,38 +37,47 @@ return function ( */ $modules = apply_filters( 'woocommerce_paypal_payments_modules', $modules ); - $providers = array_map( - function ( ModuleInterface $module ): ServiceProviderInterface { - return $module->setup(); - }, - $modules - ); + // Initialize plugin. + $properties = PluginProperties::new(__FILE__); + $bootstrap = Package::new($properties); - $provider = new CompositeCachingServiceProvider( $providers ); - $proxy_container = new ProxyContainer(); - // TODO: caching does not work currently, - // may want to consider fixing it later (pass proxy as parent to DelegatingContainer) - // for now not fixed since we were using this behavior for long time and fixing it now may break things. - $container = new DelegatingContainer( $provider ); - /** - * Skip iterable vs array check. - * - * @psalm-suppress PossiblyInvalidArgument - */ - $app_container = new CachingContainer( - new CompositeContainer( - array_merge( - $additional_containers, - array( $container ) - ) - ) - ); - $proxy_container->setInnerContainer( $app_container ); + $bootstrap->addModule( new DhiiToModularityModule( $modules ) ); + $bootstrap->boot(); - foreach ( $modules as $module ) { - /* @var $module ModuleInterface module */ - $module->run( $app_container ); - } + return $bootstrap->container(); - return $app_container; +// $providers = array_map( +// function ( ModuleInterface $module ): ServiceProviderInterface { +// return $module->setup(); +// }, +// $modules +// ); + +// $provider = new CompositeCachingServiceProvider( $providers ); +// $proxy_container = new ProxyContainer(); +// // TODO: caching does not work currently, +// // may want to consider fixing it later (pass proxy as parent to DelegatingContainer) +// // for now not fixed since we were using this behavior for long time and fixing it now may break things. +// $container = new DelegatingContainer( $provider ); +// /** +// * Skip iterable vs array check. +// * +// * @psalm-suppress PossiblyInvalidArgument +// */ +// $app_container = new CachingContainer( +// new CompositeContainer( +// array_merge( +// $additional_containers, +// array( $container ) +// ) +// ) +// ); +// $proxy_container->setInnerContainer( $app_container ); +// +// foreach ( $modules as $module ) { +// /* @var $module ModuleInterface module */ +// $module->run( $app_container ); +// } +// +// return $app_container; }; diff --git a/composer.json b/composer.json index bb2ccbf7c..96c9459ef 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,8 @@ "wikimedia/composer-merge-plugin": "^2.0", "wp-oop/wordpress-interface": "^0.1.0-alpha1", "dhii/versions": "^0.1.0-alpha1", - "symfony/polyfill-php80": "^1.19" + "symfony/polyfill-php80": "^1.19", + "inpsyde/modularity": "^1.7" }, "require-dev": { "psr/container": "^1.0", @@ -77,7 +78,8 @@ "packages": [ "psr/container", "dhii/containers", - "dhii/module-interface" + "dhii/module-interface", + "inpsyde/modularity" ], "delete_vendor_directories": true } diff --git a/composer.lock b/composer.lock index 450c96e96..36ce94f4e 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": "97559eb2b9d8b6f1529d44abd2604f99", + "content-hash": "214504278540f7c3d05f10d1e67920b1", "packages": [ { "name": "container-interop/service-provider", @@ -294,6 +294,74 @@ }, "time": "2021-12-08T16:54:50+00:00" }, + { + "name": "inpsyde/modularity", + "version": "1.7.2", + "source": { + "type": "git", + "url": "https://github.com/inpsyde/modularity.git", + "reference": "43f4b3a7c8fbb585a44fb7a619e2546b338a8934" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/inpsyde/modularity/zipball/43f4b3a7c8fbb585a44fb7a619e2546b338a8934", + "reference": "43f4b3a7c8fbb585a44fb7a619e2546b338a8934", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2", + "psr/container": "^1.1.0 || ^2" + }, + "require-dev": { + "brain/monkey": "^2.6.1", + "inpsyde/php-coding-standards": "^1", + "johnpbloch/wordpress-core": ">=5.8", + "mikey179/vfsstream": "^v1.6.10", + "php-stubs/wordpress-stubs": ">=5.8@stable", + "phpunit/phpunit": "^8.5.21 || ^9.6.7", + "vimeo/psalm": "^4.13.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Inpsyde\\Modularity\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Inpsyde GmbH", + "email": "hello@inpsyde.com", + "homepage": "https://inpsyde.com/", + "role": "Company" + }, + { + "name": "Christian Leucht", + "email": "c.leucht@inpsyde.com", + "role": "Developer" + }, + { + "name": "Giuseppe Mazzapica", + "email": "g.mazzapica@inpsyde.com", + "role": "Developer" + } + ], + "description": "Modular PSR-11 implementation for WordPress plugins, themes or libraries.", + "support": { + "issues": "https://github.com/inpsyde/modularity/issues", + "source": "https://github.com/inpsyde/modularity/tree/1.7.2" + }, + "time": "2023-11-16T11:19:47+00:00" + }, { "name": "psr/container", "version": "1.1.1", diff --git a/lib/packages/Inpsyde/Modularity/Container/ContainerConfigurator.php b/lib/packages/Inpsyde/Modularity/Container/ContainerConfigurator.php new file mode 100644 index 000000000..429869912 --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Container/ContainerConfigurator.php @@ -0,0 +1,153 @@ + + */ + private $services = []; + + /** + * @var array + */ + private $factoryIds = []; + + /** + * @var array> + */ + private $extensions = []; + + /** + * @var ContainerInterface[] + */ + private $containers = []; + + /** + * @var null|ContainerInterface + */ + private $compiledContainer; + + /** + * ContainerConfigurator constructor. + * + * @param ContainerInterface[] $containers + */ + public function __construct(array $containers = []) + { + array_map([$this, 'addContainer'], $containers); + } + + /** + * Allowing to add child containers. + * + * @param ContainerInterface $container + */ + public function addContainer(ContainerInterface $container): void + { + $this->containers[] = $container; + } + + /** + * @param string $id + * @param callable(ContainerInterface $container):mixed $factory + */ + public function addFactory(string $id, callable $factory): void + { + $this->addService($id, $factory); + // We're using a hash table to detect later + // via isset() if a Service as a Factory. + $this->factoryIds[$id] = true; + } + + /** + * @param string $id + * @param callable(ContainerInterface $container):mixed $service + * + * @return void + */ + public function addService(string $id, callable $service): void + { + /* + * We are being intentionally permissive here, + * allowing a simple workflow for *intentional* overrides + * while accepting the (small?) risk of *accidental* overrides + * that could be hard to notice and debug. + * + * Clear a factory flag in case it was a factory. + * If needs be, it will get re-added after this function completes. + */ + unset($this->factoryIds[$id]); + + $this->services[$id] = $service; + } + + /** + * @param string $id + * + * @return bool + */ + public function hasService(string $id): bool + { + if (array_key_exists($id, $this->services)) { + return true; + } + + foreach ($this->containers as $container) { + if ($container->has($id)) { + return true; + } + } + + return false; + } + + /** + * @param string $id + * @param callable(mixed $service, ContainerInterface $container):mixed $extender + * + * @return void + */ + public function addExtension(string $id, callable $extender): void + { + if (!isset($this->extensions[$id])) { + $this->extensions[$id] = []; + } + + $this->extensions[$id][] = $extender; + } + + /** + * @param string $id + * + * @return bool + */ + public function hasExtension(string $id): bool + { + return isset($this->extensions[$id]); + } + + /** + * Returns a read only version of this Container. + * + * @return ContainerInterface + */ + public function createReadOnlyContainer(): ContainerInterface + { + if (!$this->compiledContainer) { + $this->compiledContainer = new ReadOnlyContainer( + $this->services, + $this->factoryIds, + $this->extensions, + $this->containers + ); + } + + return $this->compiledContainer; + } +} diff --git a/lib/packages/Inpsyde/Modularity/Container/PackageProxyContainer.php b/lib/packages/Inpsyde/Modularity/Container/PackageProxyContainer.php new file mode 100644 index 000000000..2c8d79d5d --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Container/PackageProxyContainer.php @@ -0,0 +1,102 @@ +package = $package; + } + + /** + * @param string $id + * @return mixed + * + * @throws \Exception + */ + public function get(string $id) + { + $this->assertPackageBooted($id); + + return $this->container->get($id); + } + + /** + * @param string $id + * @return bool + * + * @throws \Exception + */ + public function has(string $id): bool + { + return $this->tryContainer() && $this->container->has($id); + } + + /** + * @return bool + * + * @throws \Exception + * @psalm-assert-if-true ContainerInterface $this->container + */ + private function tryContainer(): bool + { + if ($this->container) { + return true; + } + + /** TODO: We need a better way to deal with status checking besides equality */ + if ( + $this->package->statusIs(Package::STATUS_READY) + || $this->package->statusIs(Package::STATUS_BOOTED) + ) { + $this->container = $this->package->container(); + } + + return (bool)$this->container; + } + + /** + * @param string $id + * @return void + * + * @throws \Exception + * + * @psalm-assert ContainerInterface $this->container + */ + private function assertPackageBooted(string $id): void + { + if ($this->tryContainer()) { + return; + } + + $name = $this->package->name(); + $status = $this->package->statusIs(Package::STATUS_FAILED) + ? 'is errored' + : 'is not ready yet'; + + throw new class ("Error retrieving service {$id} because package {$name} {$status}.") + extends \Exception + implements ContainerExceptionInterface { + }; + } +} diff --git a/lib/packages/Inpsyde/Modularity/Container/ReadOnlyContainer.php b/lib/packages/Inpsyde/Modularity/Container/ReadOnlyContainer.php new file mode 100644 index 000000000..763ae23ac --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Container/ReadOnlyContainer.php @@ -0,0 +1,138 @@ + + */ + private $services; + + /** + * @var array + */ + private $factoryIds; + + /** + * @var array> + */ + private $extensions; + + /** + * Resolved factories. + * + * @var array + */ + private $resolvedServices = []; + + /** + * @var ContainerInterface[] + */ + private $containers; + + /** + * ReadOnlyContainer constructor. + * + * @param array $services + * @param array $factoryIds + * @param array> $extensions + * @param ContainerInterface[] $containers + */ + public function __construct( + array $services, + array $factoryIds, + array $extensions, + array $containers + ) { + $this->services = $services; + $this->factoryIds = $factoryIds; + $this->extensions = $extensions; + $this->containers = $containers; + } + + /** + * @param string $id + * + * @return mixed + */ + public function get(string $id) + { + if (array_key_exists($id, $this->resolvedServices)) { + return $this->resolvedServices[$id]; + } + + if (array_key_exists($id, $this->services)) { + $service = $this->services[$id]($this); + $resolved = $this->resolveExtensions($id, $service); + + if (!isset($this->factoryIds[$id])) { + $this->resolvedServices[$id] = $resolved; + unset($this->services[$id]); + } + + return $resolved; + } + + foreach ($this->containers as $container) { + if ($container->has($id)) { + $service = $container->get($id); + + return $this->resolveExtensions($id, $service); + } + } + + throw new class ("Service with ID {$id} not found.") + extends \Exception + implements NotFoundExceptionInterface { + }; + } + + /** + * @param string $id + * + * @return bool + */ + public function has(string $id): bool + { + if (array_key_exists($id, $this->services)) { + return true; + } + + if (array_key_exists($id, $this->resolvedServices)) { + return true; + } + + foreach ($this->containers as $container) { + if ($container->has($id)) { + return true; + } + } + + return false; + } + + /** + * @param string $id + * @param mixed $service + * + * @return mixed + */ + private function resolveExtensions(string $id, $service) + { + if (!isset($this->extensions[$id])) { + return $service; + } + + foreach ($this->extensions[$id] as $extender) { + $service = $extender($service, $this); + } + + return $service; + } +} diff --git a/lib/packages/Inpsyde/Modularity/Module/ExecutableModule.php b/lib/packages/Inpsyde/Modularity/Module/ExecutableModule.php new file mode 100644 index 000000000..2f7771fb5 --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Module/ExecutableModule.php @@ -0,0 +1,21 @@ + + */ + public function extensions(): array; +} diff --git a/lib/packages/Inpsyde/Modularity/Module/FactoryModule.php b/lib/packages/Inpsyde/Modularity/Module/FactoryModule.php new file mode 100644 index 000000000..6e686c0c2 --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Module/FactoryModule.php @@ -0,0 +1,18 @@ + + */ + public function factories(): array; +} diff --git a/lib/packages/Inpsyde/Modularity/Module/Module.php b/lib/packages/Inpsyde/Modularity/Module/Module.php new file mode 100644 index 000000000..49dd0e5e3 --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Module/Module.php @@ -0,0 +1,20 @@ + + */ + public function services(): array; +} diff --git a/lib/packages/Inpsyde/Modularity/Package.php b/lib/packages/Inpsyde/Modularity/Package.php new file mode 100644 index 000000000..f55eaeccb --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Package.php @@ -0,0 +1,727 @@ + + * $package = Package::new(); + * $package->boot(); + * + * $container = $package->container(); + * $container->has(Package::PROPERTIES); + * $container->get(Package::PROPERTIES); + * + * + * @var string + */ + public const PROPERTIES = 'properties'; + + /** + * Custom action to be used to add Modules to the package. + * It might also be used to access package properties. + * + * @example + * + * $package = Package::new(); + * + * add_action( + * $package->hookName(Package::ACTION_INIT), + * $callback + * ); + * + */ + public const ACTION_INIT = 'init'; + + /** + * Custom action which is triggered after the application + * is booted to access container and properties. + * + * @example + * + * $package = Package::new(); + * + * add_action( + * $package->hookName(Package::ACTION_READY), + * $callback + * ); + * + */ + public const ACTION_READY = 'ready'; + + /** + * Custom action which is triggered when a failure happens during the building stage. + * + * @example + * + * $package = Package::new(); + * + * add_action( + * $package->hookName(Package::ACTION_FAILED_BUILD), + * $callback + * ); + * + */ + public const ACTION_FAILED_BUILD = 'failed-build'; + + /** + * Custom action which is triggered when a failure happens during the booting stage. + * + * @example + * + * $package = Package::new(); + * + * add_action( + * $package->hookName(Package::ACTION_FAILED_BOOT), + * $callback + * ); + * + */ + public const ACTION_FAILED_BOOT = 'failed-boot'; + + /** + * Custom action which is triggered when a package is connected. + */ + public const ACTION_PACKAGE_CONNECTED = 'package-connected'; + + /** + * Custom action which is triggered when a package cannot be connected. + */ + public const ACTION_FAILED_CONNECTION = 'failed-connection'; + + /** + * Module states can be used to get information about your module. + * + * @example + * + * $package = Package::new(); + * $package->moduleIs(SomeModule::class, Package::MODULE_ADDED); // false + * $package->boot(new SomeModule()); + * $package->moduleIs(SomeModule::class, Package::MODULE_ADDED); // true + * + */ + public const MODULE_ADDED = 'added'; + public const MODULE_NOT_ADDED = 'not-added'; + public const MODULE_REGISTERED = 'registered'; + public const MODULE_REGISTERED_FACTORIES = 'registered-factories'; + public const MODULE_EXTENDED = 'extended'; + public const MODULE_EXECUTED = 'executed'; + public const MODULE_EXECUTION_FAILED = 'executed-failed'; + public const MODULES_ALL = '*'; + + /** + * Custom states for the class. + * + * @example + * + * $package = Package::new(); + * $package->statusIs(Package::IDLE); // true + * $package->boot(); + * $package->statusIs(Package::BOOTED); // true + * + */ + public const STATUS_IDLE = 2; + public const STATUS_INITIALIZED = 4; + public const STATUS_MODULES_ADDED = 5; + public const STATUS_READY = 7; + public const STATUS_BOOTED = 8; + public const STATUS_FAILED = -8; + + /** + * Current state of the application. + * + * @see Package::STATUS_* + * + * @var int + */ + private $status = self::STATUS_IDLE; + + /** + * Contains the progress of all modules. + * + * @see Package::moduleProgress() + * + * @var array> + */ + private $moduleStatus = [self::MODULES_ALL => []]; + + /** + * Hashmap of where keys are names of connected packages, and values are boolean, true + * if connection was successful. + * + * @see Package::connect() + * + * @var array + */ + private $connectedPackages = []; + + /** + * @var list + */ + private $executables = []; + + /** + * @var Properties + */ + private $properties; + + /** + * @var ContainerConfigurator + */ + private $containerConfigurator; + + /** + * @var bool + */ + private $built = false; + + /** + * @var bool + */ + private $hasContainer = false; + + /** + * @var \Throwable|null + */ + private $lastError = null; + + /** + * @param Properties $properties + * @param ContainerInterface[] $containers + * + * @return Package + */ + public static function new(Properties $properties, ContainerInterface ...$containers): Package + { + return new self($properties, ...$containers); + } + + /** + * @param Properties $properties + * @param ContainerInterface[] $containers + */ + private function __construct(Properties $properties, ContainerInterface ...$containers) + { + $this->properties = $properties; + + $this->containerConfigurator = new ContainerConfigurator($containers); + $this->containerConfigurator->addService( + self::PROPERTIES, + static function () use ($properties) { + return $properties; + } + ); + } + + /** + * @param Module $module + * + * @return static + * @throws \Exception + */ + public function addModule(Module $module): Package + { + try { + $this->assertStatus(self::STATUS_IDLE, sprintf('add module %s', $module->id())); + + $registeredServices = $this->addModuleServices( + $module, + self::MODULE_REGISTERED + ); + $registeredFactories = $this->addModuleServices( + $module, + self::MODULE_REGISTERED_FACTORIES + ); + $extended = $this->addModuleServices( + $module, + self::MODULE_EXTENDED + ); + $isExecutable = $module instanceof ExecutableModule; + + // ExecutableModules are collected and executed on Package::boot() + // when the Container is being compiled. + if ($isExecutable) { + /** @var ExecutableModule $module */ + $this->executables[] = $module; + } + + $added = $registeredServices || $registeredFactories || $extended || $isExecutable; + $status = $added ? self::MODULE_ADDED : self::MODULE_NOT_ADDED; + $this->moduleProgress($module->id(), $status); + } catch (\Throwable $throwable) { + $this->handleFailure($throwable, self::ACTION_FAILED_BUILD); + } + + return $this; + } + + /** + * @param Package $package + * @return bool + * @throws \Exception + */ + public function connect(Package $package): bool + { + try { + if ($package === $this) { + return false; + } + + $packageName = $package->name(); + $errorData = ['package' => $packageName, 'status' => $this->status]; + $errorMessage = "Failed connecting package {$packageName}"; + + // Don't connect, if already connected + if (array_key_exists($packageName, $this->connectedPackages)) { + $error = "{$errorMessage} because it was already connected."; + do_action( + $this->hookName(self::ACTION_FAILED_CONNECTION), + $packageName, + new \WP_Error('already_connected', $error, $errorData) + ); + + throw new \Exception($error, 0, $this->lastError); + } + + // Don't connect, if already booted or boot failed + $failed = $this->statusIs(self::STATUS_FAILED); + if ($failed || $this->statusIs(self::STATUS_BOOTED)) { + $status = $failed ? 'errored' : 'booted'; + $error = "{$errorMessage} to a {$status} package."; + do_action( + $this->hookName(self::ACTION_FAILED_CONNECTION), + $packageName, + new \WP_Error("no_connect_on_{$status}", $error, $errorData) + ); + + throw new \Exception($error, 0, $this->lastError); + } + + $this->connectedPackages[$packageName] = true; + + // We put connected package's properties in this package's container, so that in modules + // "run" method we can access them if we need to. + $this->containerConfigurator->addService( + sprintf('%s.%s', $package->name(), self::PROPERTIES), + static function () use ($package): Properties { + return $package->properties(); + } + ); + + // If the other package is booted, we can obtain a container, otherwise + // we build a proxy container + $container = $package->statusIs(self::STATUS_BOOTED) + ? $package->container() + : new PackageProxyContainer($package); + + $this->containerConfigurator->addContainer($container); + + do_action( + $this->hookName(self::ACTION_PACKAGE_CONNECTED), + $packageName, + $this->status, + $container instanceof PackageProxyContainer + ); + + return true; + } catch (\Throwable $throwable) { + if (isset($packageName)) { + $this->connectedPackages[$packageName] = false; + } + $this->handleFailure($throwable, self::ACTION_FAILED_BUILD); + + return false; + } + } + + /** + * @return static + */ + public function build(): Package + { + try { + // Don't allow building the application multiple times. + $this->assertStatus(self::STATUS_IDLE, 'build package'); + + do_action( + $this->hookName(self::ACTION_INIT), + $this + ); + // Changing the status here ensures we can not call this method again, and also we can not + // add new modules, because both this and `addModule()` methods check for idle status. + // For backward compatibility, adding new modules via `boot()` will still be possible, even + // if deprecated, at the condition that the container was not yet accessed at that point. + $this->progress(self::STATUS_INITIALIZED); + } catch (\Throwable $throwable) { + $this->handleFailure($throwable, self::ACTION_FAILED_BUILD); + } finally { + $this->built = true; + } + + return $this; + } + + /** + * @param Module ...$defaultModules Deprecated, use `addModule()` to add default modules. + * @return bool + * + * @throws \Throwable + */ + public function boot(Module ...$defaultModules): bool + { + try { + // Call build() if not called yet, and ensure any new module passed here is added + // as well, throwing if the container was already built. + $this->doBuild(...$defaultModules); + + // Don't allow booting the application multiple times. + $this->assertStatus(self::STATUS_MODULES_ADDED, 'boot application', '<'); + $this->assertStatus(self::STATUS_FAILED, 'boot application', '!='); + + $this->progress(self::STATUS_MODULES_ADDED); + + $this->doExecute(); + + $this->progress(self::STATUS_READY); + + do_action( + $this->hookName(self::ACTION_READY), + $this + ); + } catch (\Throwable $throwable) { + $this->handleFailure($throwable, self::ACTION_FAILED_BOOT); + + return false; + } + + $this->progress(self::STATUS_BOOTED); + + return true; + } + + /** + * @param Module ...$defaultModules + * @return void + */ + private function doBuild(Module ...$defaultModules): void + { + if ($defaultModules) { + $this->deprecatedArgument( + sprintf( + 'Passing default modules to %1$s::boot() is deprecated since version 1.7.0.' + . ' Please add modules via %1$s::addModule().', + __CLASS__ + ), + __METHOD__, + '1.7.0' + ); + } + + if (!$this->built) { + array_map([$this, 'addModule'], $defaultModules); + $this->build(); + + return; + } + + if ( + !$defaultModules + || ($this->status >= self::STATUS_MODULES_ADDED) + || ($this->statusIs(self::STATUS_FAILED)) + ) { + // if we don't have default modules, there's nothing to do, and if the status is beyond + // "modules added" or is failed, we do nothing as well and let `boot()` throw. + return; + } + + $backup = $this->status; + + try { + // simulate idle status to prevent `addModule()` from throwing + // only if we don't have a container yet + $this->hasContainer or $this->status = self::STATUS_IDLE; + + foreach ($defaultModules as $defaultModule) { + // If a module was added by `build()` or `addModule()` we can skip it, a + // deprecation was trigger to make it noticeable without breakage + if (!$this->moduleIs($defaultModule->id(), self::MODULE_ADDED)) { + $this->addModule($defaultModule); + } + } + } finally { + $this->status = $backup; + } + } + + /** + * @param Module $module + * @param string $status + * @return bool + */ + private function addModuleServices(Module $module, string $status): bool + { + $services = null; + $addCallback = null; + switch ($status) { + case self::MODULE_REGISTERED: + $services = $module instanceof ServiceModule ? $module->services() : null; + $addCallback = [$this->containerConfigurator, 'addService']; + break; + case self::MODULE_REGISTERED_FACTORIES: + $services = $module instanceof FactoryModule ? $module->factories() : null; + $addCallback = [$this->containerConfigurator, 'addFactory']; + break; + case self::MODULE_EXTENDED: + $services = $module instanceof ExtendingModule ? $module->extensions() : null; + $addCallback = [$this->containerConfigurator, 'addExtension']; + break; + } + + if (!$services) { + return false; + } + + $ids = []; + array_walk( + $services, + static function (callable $service, string $id) use ($addCallback, &$ids) { + /** @var callable(string, callable) $addCallback */ + $addCallback($id, $service); + /** @var list $ids */ + $ids[] = $id; + } + ); + /** @var list $ids */ + $this->moduleProgress($module->id(), $status, $ids); + + return true; + } + + /** + * @return void + * + * @throws \Throwable + */ + private function doExecute(): void + { + foreach ($this->executables as $executable) { + $success = $executable->run($this->container()); + $this->moduleProgress( + $executable->id(), + $success + ? self::MODULE_EXECUTED + : self::MODULE_EXECUTION_FAILED + ); + } + } + + /** + * @param string $moduleId + * @param string $status + * @param list|null $serviceIds + * + * @return void + */ + private function moduleProgress(string $moduleId, string $status, ?array $serviceIds = null) + { + isset($this->moduleStatus[$status]) or $this->moduleStatus[$status] = []; + $this->moduleStatus[$status][] = $moduleId; + + if (!$serviceIds || !$this->properties->isDebug()) { + $this->moduleStatus[self::MODULES_ALL][] = "{$moduleId} {$status}"; + + return; + } + + $description = sprintf('%s %s (%s)', $moduleId, $status, implode(', ', $serviceIds)); + $this->moduleStatus[self::MODULES_ALL][] = $description; + } + + /** + * @return array> + */ + public function modulesStatus(): array + { + return $this->moduleStatus; + } + + /** + * @return array + */ + public function connectedPackages(): array + { + return $this->connectedPackages; + } + + /** + * @param string $packageName + * @return bool + */ + public function isPackageConnected(string $packageName): bool + { + return $this->connectedPackages[$packageName] ?? false; + } + + /** + * @param string $moduleId + * @param string $status + * + * @return bool + */ + public function moduleIs(string $moduleId, string $status): bool + { + return in_array($moduleId, $this->moduleStatus[$status] ?? [], true); + } + + /** + * Return the filter name to be used to extend modules of the plugin. + * + * If the plugin is single file `my-plugin.php` in plugins folder the filter name will be: + * `inpsyde.modularity.my-plugin`. + * + * If the plugin is in a sub-folder e.g. `my-plugin/index.php` the filter name will be: + * `inpsyde.modularity.my-plugin` anyway, so the file name is not relevant. + * + * @param string $suffix + * + * @return string + * @see Package::name() + * + */ + public function hookName(string $suffix = ''): string + { + $filter = self::HOOK_PREFIX . $this->properties->baseName(); + + if ($suffix) { + $filter .= '.' . $suffix; + } + + return $filter; + } + + /** + * @return Properties + */ + public function properties(): Properties + { + return $this->properties; + } + + /** + * @return ContainerInterface + * + * @throws \Exception + */ + public function container(): ContainerInterface + { + $this->assertStatus(self::STATUS_INITIALIZED, 'obtain the container instance', '>='); + $this->hasContainer = true; + + return $this->containerConfigurator->createReadOnlyContainer(); + } + + /** + * @return string + */ + public function name(): string + { + return $this->properties->baseName(); + } + + /** + * @param int $status + */ + private function progress(int $status): void + { + $this->status = $status; + } + + /** + * @param int $status + * + * @return bool + */ + public function statusIs(int $status): bool + { + return $this->status === $status; + } + + /** + * @param \Throwable $throwable + * @param Package::ACTION_FAILED_* $action + * @return void + * @throws \Throwable + */ + private function handleFailure(\Throwable $throwable, string $action): void + { + $this->progress(self::STATUS_FAILED); + $hook = $this->hookName($action); + did_action($hook) or do_action($hook, $throwable); + + if ($this->properties->isDebug()) { + throw $throwable; + } + + $this->lastError = $throwable; + } + + /** + * @param int $status + * @param string $action + * @param string $operator + * + * @throws \Exception + * @psalm-suppress ArgumentTypeCoercion + */ + private function assertStatus(int $status, string $action, string $operator = '=='): void + { + if (!version_compare((string) $this->status, (string) $status, $operator)) { + throw new \Exception( + sprintf("Can't %s at this point of application.", $action), + 0, + $this->lastError + ); + } + } + + /** + * Similar to WP's `_deprecated_argument()`, but executes regardless of WP_DEBUG and without + * translated message (so without attempting loading translation files). + * + * @param string $message + * @param string $function + * @param string $version + * + * @return void + */ + private function deprecatedArgument(string $message, string $function, string $version): void + { + do_action('deprecated_argument_run', $function, $message, $version); + + if (apply_filters('deprecated_argument_trigger_error', true)) { + trigger_error($message, \E_USER_DEPRECATED); + } + } +} diff --git a/lib/packages/Inpsyde/Modularity/Properties/BaseProperties.php b/lib/packages/Inpsyde/Modularity/Properties/BaseProperties.php new file mode 100644 index 000000000..47bb4db74 --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Properties/BaseProperties.php @@ -0,0 +1,217 @@ +sanitizeBaseName($baseName); + $basePath = (string) trailingslashit($basePath); + if ($baseUrl) { + $baseUrl = (string) trailingslashit($baseUrl); + } + + $this->baseName = $baseName; + $this->basePath = $basePath; + $this->baseUrl = $baseUrl; + $this->properties = array_replace(Properties::DEFAULT_PROPERTIES, $properties); + } + + /** + * @param string $name + * + * @return string + */ + protected function sanitizeBaseName(string $name): string + { + substr_count($name, '/') and $name = dirname($name); + + return strtolower(pathinfo($name, PATHINFO_FILENAME)); + } + + /** + * @return string + */ + public function baseName(): string + { + return $this->baseName; + } + + /** + * @return string + */ + public function basePath(): string + { + return $this->basePath; + } + + /** + * @return string|null + */ + public function baseUrl(): ?string + { + return $this->baseUrl; + } + + /** + * @return string + */ + public function author(): string + { + return (string) $this->get(self::PROP_AUTHOR); + } + + /** + * @return string + */ + public function authorUri(): string + { + return (string) $this->get(self::PROP_AUTHOR_URI); + } + + /** + * @return string + */ + public function description(): string + { + return (string) $this->get(self::PROP_DESCRIPTION); + } + + /** + * @return string + */ + public function textDomain(): string + { + return (string) $this->get(self::PROP_TEXTDOMAIN); + } + + /** + * @return string + */ + public function domainPath(): string + { + return (string) $this->get(self::PROP_DOMAIN_PATH); + } + + /** + * @return string + */ + public function name(): string + { + return (string) $this->get(self::PROP_NAME); + } + + /** + * @return string + */ + public function uri(): string + { + return (string) $this->get(self::PROP_URI); + } + + /** + * @return string + */ + public function version(): string + { + return (string) $this->get(self::PROP_VERSION); + } + + /** + * @return string|null + */ + public function requiresWp(): ?string + { + $value = $this->get(self::PROP_REQUIRES_WP); + + return $value && is_string($value) ? $value : null; + } + + /** + * @return string|null + */ + public function requiresPhp(): ?string + { + $value = $this->get(self::PROP_REQUIRES_PHP); + + return $value && is_string($value) ? $value : null; + } + + /** + * @return array + */ + public function tags(): array + { + return (array) $this->get(self::PROP_TAGS); + } + + /** + * @param string $key + * @param null $default + * @return mixed + */ + public function get(string $key, $default = null) + { + return $this->properties[$key] ?? $default; + } + + /** + * @param string $key + * @return bool + */ + public function has(string $key): bool + { + return isset($this->properties[$key]); + } + + /** + * @return bool + * @see Properties::isDebug() + */ + public function isDebug(): bool + { + if ($this->isDebug === null) { + $this->isDebug = defined('WP_DEBUG') && WP_DEBUG; + } + + return $this->isDebug; + } +} diff --git a/lib/packages/Inpsyde/Modularity/Properties/LibraryProperties.php b/lib/packages/Inpsyde/Modularity/Properties/LibraryProperties.php new file mode 100644 index 000000000..5c06577e1 --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Properties/LibraryProperties.php @@ -0,0 +1,209 @@ + 0) { + $properties[self::PROP_AUTHOR] = implode(', ', $names); + } + + // Custom settings which can be stored in composer.json "extra.modularity" + $extra = $composerJsonData['extra']['modularity'] ?? []; + foreach (self::EXTRA_KEYS as $key) { + $properties[$key] = $extra[$key] ?? ''; + } + + // PHP requirement in composer.json "require" or "require-dev" + $properties[self::PROP_REQUIRES_PHP] = self::extractPhpVersion($composerJsonData); + + // composer.json might have "version" in root + $version = $composerJsonData['version'] ?? null; + if ($version && is_string($version)) { + $properties[self::PROP_VERSION] = $version; + } + + [$baseName, $name] = static::buildNames($composerJsonData); + $basePath = dirname($composerJsonFile); + if (empty($properties[self::PROP_NAME])) { + $properties[self::PROP_NAME] = $name; + } + + return new self( + $baseName, + $basePath, + $baseUrl, + $properties + ); + } + + /** + * @param array $composerJsonData + * + * @return array{string, string} + */ + private static function buildNames(array $composerJsonData): array + { + $composerName = (string) ($composerJsonData['name'] ?? ''); + $packageNamePieces = explode('/', $composerName, 2); + $basename = implode('-', $packageNamePieces); + // "inpsyde/foo-bar-baz" => "Inpsyde Foo Bar Baz" + $name = mb_convert_case( + str_replace(['-', '_', '.'], ' ', implode(' ', $packageNamePieces)), + MB_CASE_TITLE + ); + + return [$basename, $name]; + } + + /** + * Check PHP version in require, require-dev. + * + * Attempt to parse requirements to find the _minimum_ accepted version (consistent with WP). + * Composer requirements are parsed in a way that, for example: + * `>=7.2` returns `7.2` + * `^7.3` returns `7.3` + * `5.6 || >= 7.1` returns `5.6` + * `>= 7.1 < 8` returns `7.1` + * + * @param array $composerData + * @param string $key + * + * @return string|null + */ + private static function extractPhpVersion(array $composerData, string $key = 'require'): ?string + { + $nextKey = ($key === 'require') + ? 'require-dev' + : null; + $base = (array) ($composerData[$key] ?? []); + $requirement = $base['php'] ?? null; + $version = ($requirement && is_string($requirement)) + ? trim($requirement) + : null; + if (!$version) { + return $nextKey + ? static::extractPhpVersion($composerData, $nextKey) + : null; + } + + static $matcher; + $matcher or $matcher = static function (string $version): ?string { + $version = trim($version); + if (!$version) { + return null; + } + + // versions range like `>= 7.2.4 < 8` + if (preg_match('{>=?([\s0-9\.]+)<}', $version, $matches)) { + return trim($matches[1], " \t\n\r\0\x0B."); + } + + // aliases like `dev-src#abcde as 7.4` + if (preg_match('{as\s*([\s0-9\.]+)}', $version, $matches)) { + return trim($matches[1], " \t\n\r\0\x0B."); + } + + // Basic requirements like 7.2, >=7.2, ^7.2, ~7.2 + if (preg_match('{^(?:[>=\s~\^]+)?([0-9\.]+)}', $version, $matches)) { + return trim($matches[1], " \t\n\r\0\x0B."); + } + + return null; + }; + + // support for simpler requirements like `7.3`, `>=7.4` or alternative like `5.6 || >=7` + + $alternatives = explode('||', $version); + $found = null; + foreach ($alternatives as $alternative) { + /** @var callable(string):?string $matcher */ + $itemFound = $matcher($alternative); + if ($itemFound && (!$found || version_compare($itemFound, $found, '<'))) { + $found = $itemFound; + } + } + + if ($found) { + return $found; + } + + return $nextKey + ? static::extractPhpVersion($composerData, $nextKey) + : null; + } + + /** + * @param string $url + * + * @return static + * + * @throws \Exception + */ + public function withBaseUrl(string $url): LibraryProperties + { + if ($this->baseUrl !== null) { + throw new \Exception(sprintf('%s::$baseUrl property is not overridable.', __CLASS__)); + } + + $this->baseUrl = trailingslashit($url); + + return $this; + } +} diff --git a/lib/packages/Inpsyde/Modularity/Properties/PluginProperties.php b/lib/packages/Inpsyde/Modularity/Properties/PluginProperties.php new file mode 100644 index 000000000..f3d3f5485 --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Properties/PluginProperties.php @@ -0,0 +1,176 @@ + 'Author', + self::PROP_AUTHOR_URI => 'AuthorURI', + self::PROP_DESCRIPTION => 'Description', + self::PROP_DOMAIN_PATH => 'DomainPath', + self::PROP_NAME => 'Name', + self::PROP_TEXTDOMAIN => 'TextDomain', + self::PROP_URI => 'PluginURI', + self::PROP_VERSION => 'Version', + self::PROP_REQUIRES_WP => 'RequiresWP', + self::PROP_REQUIRES_PHP => 'RequiresPHP', + + // additional headers + self::PROP_NETWORK => 'Network', + ]; + + /** + * @var string + */ + private $pluginMainFile; + + /** + * @var string + */ + private $pluginBaseName; + + /** + * @var bool|null + */ + protected $isMu; + + /** + * @var bool|null + */ + protected $isActive; + + /** + * @var bool|null + */ + protected $isNetworkActive; + + /** + * @param string $pluginMainFile + * + * @return PluginProperties + */ + public static function new(string $pluginMainFile): PluginProperties + { + return new self($pluginMainFile); + } + + /** + * PluginProperties constructor. + * + * @param string $pluginMainFile + */ + protected function __construct(string $pluginMainFile) + { + if (!function_exists('get_plugin_data')) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + + $pluginData = get_plugin_data($pluginMainFile); + $properties = Properties::DEFAULT_PROPERTIES; + + // Map pluginData to internal structure. + foreach (self::HEADERS as $key => $pluginDataKey) { + $properties[$key] = $pluginData[$pluginDataKey] ?? ''; + unset($pluginData[$pluginDataKey]); + } + $properties = array_merge($properties, $pluginData); + + $this->pluginMainFile = wp_normalize_path($pluginMainFile); + + $this->pluginBaseName = plugin_basename($pluginMainFile); + $basePath = plugin_dir_path($pluginMainFile); + $baseUrl = plugins_url('/', $pluginMainFile); + + parent::__construct( + $this->pluginBaseName, + $basePath, + $baseUrl, + $properties + ); + } + + /** + * @return string + */ + public function pluginMainFile(): string + { + return $this->pluginMainFile; + } + + /** + * @return bool + * + * @psalm-suppress PossiblyFalseArgument + */ + public function network(): bool + { + return (bool) $this->get(self::PROP_NETWORK, false); + } + + /** + * @return bool + */ + public function isActive(): bool + { + if ($this->isActive === null) { + if (!function_exists('is_plugin_active')) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + $this->isActive = is_plugin_active($this->pluginBaseName); + } + + return $this->isActive; + } + + /** + * @return bool + */ + public function isNetworkActive(): bool + { + if ($this->isNetworkActive === null) { + if (!function_exists('is_plugin_active_for_network')) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + $this->isNetworkActive = is_plugin_active_for_network($this->pluginBaseName); + } + + return $this->isNetworkActive; + } + + /** + * @return bool + */ + public function isMuPlugin(): bool + { + if ($this->isMu === null) { + /** + * @psalm-suppress UndefinedConstant + * @psalm-suppress MixedArgument + */ + $muPluginDir = wp_normalize_path(WPMU_PLUGIN_DIR); + $this->isMu = strpos($this->pluginMainFile, $muPluginDir) === 0; + } + + return $this->isMu; + } +} diff --git a/lib/packages/Inpsyde/Modularity/Properties/Properties.php b/lib/packages/Inpsyde/Modularity/Properties/Properties.php new file mode 100644 index 000000000..8663d6883 --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Properties/Properties.php @@ -0,0 +1,139 @@ + '', + self::PROP_AUTHOR_URI => '', + self::PROP_DESCRIPTION => '', + self::PROP_DOMAIN_PATH => '', + self::PROP_NAME => '', + self::PROP_TEXTDOMAIN => '', + self::PROP_URI => '', + self::PROP_VERSION => '', + self::PROP_REQUIRES_WP => null, + self::PROP_REQUIRES_PHP => null, + self::PROP_TAGS => [], + ]; + + /** + * @param string $key + * @param null $default + * + * @return mixed + */ + public function get(string $key, $default = null); + + /** + * @param string $key + * + * @return bool + */ + public function has(string $key): bool; + + /** + * @return bool + */ + public function isDebug(): bool; + + /** + * @return string + */ + public function baseName(): string; + + /** + * @return string + */ + public function basePath(): string; + + /** + * @return string|null + */ + public function baseUrl(): ?string; + + /** + * @return string + */ + public function author(): string; + + /** + * @return string + */ + public function authorUri(): string; + + /** + * @return string + */ + public function description(): string; + + /** + * @return string + */ + public function textDomain(): string; + + /** + * @return string + */ + public function domainPath(): string; + + /** + * The name of the plugin, theme or library. + * + * @return string + */ + public function name(): string; + + /** + * The home page of the plugin, theme or library. + * @return string + */ + public function uri(): string; + + /** + * @return string + */ + public function version(): string; + + /** + * Optional. Specify the minimum required WordPress version. + * + * @return string|null + */ + public function requiresWp(): ?string; + + /** + * Optional. Specify the minimum required PHP version. + * + * @return string + */ + public function requiresPhp(): ?string; + + /** + * Optional. Currently, only available for Theme and Library. + * Plugins do not have support for "tags"/"keywords" in header. + * + * @link https://developer.wordpress.org/reference/classes/wp_theme/#properties + * @link https://getcomposer.org/doc/04-schema.md#keywords + * + * @return array + */ + public function tags(): array; +} diff --git a/lib/packages/Inpsyde/Modularity/Properties/ThemeProperties.php b/lib/packages/Inpsyde/Modularity/Properties/ThemeProperties.php new file mode 100644 index 000000000..24a464caa --- /dev/null +++ b/lib/packages/Inpsyde/Modularity/Properties/ThemeProperties.php @@ -0,0 +1,131 @@ + 'Author', + self::PROP_AUTHOR_URI => 'AuthorURI', + self::PROP_DESCRIPTION => 'Description', + self::PROP_DOMAIN_PATH => 'DomainPath', + self::PROP_NAME => 'Name', + self::PROP_TEXTDOMAIN => 'TextDomain', + self::PROP_URI => 'ThemeURI', + self::PROP_VERSION => 'Version', + self::PROP_REQUIRES_WP => 'RequiresWP', + self::PROP_REQUIRES_PHP => 'RequiresPHP', + + // additional headers + self::PROP_STATUS => 'Status', + self::PROP_TAGS => 'Tags', + self::PROP_TEMPLATE => 'Template', + ]; + + /** + * @param string $themeDirectory + * + * @return ThemeProperties + */ + public static function new(string $themeDirectory): ThemeProperties + { + return new self($themeDirectory); + } + + /** + * ThemeProperties constructor. + * + * @param string $themeDirectory + */ + protected function __construct(string $themeDirectory) + { + if (!function_exists('wp_get_theme')) { + require_once ABSPATH . 'wp-includes/theme.php'; + } + + $theme = wp_get_theme($themeDirectory); + $properties = Properties::DEFAULT_PROPERTIES; + + foreach (self::HEADERS as $key => $themeKey) { + /** @psalm-suppress DocblockTypeContradiction */ + $properties[$key] = $theme->get($themeKey) ?? ''; + } + + $baseName = $theme->get_stylesheet(); + $basePath = $theme->get_stylesheet_directory(); + $baseUrl = (string) trailingslashit($theme->get_stylesheet_directory_uri()); + + parent::__construct( + $baseName, + $basePath, + $baseUrl, + $properties + ); + } + + /** + * If the theme is published. + * + * @return string + */ + public function status(): string + { + return (string) $this->get(self::PROP_STATUS); + } + + public function template(): string + { + return (string) $this->get(self::PROP_TEMPLATE); + } + + /** + * @return bool + */ + public function isChildTheme(): bool + { + return (bool) $this->template(); + } + + /** + * @return bool + */ + public function isCurrentTheme(): bool + { + return get_stylesheet() === $this->baseName(); + } + + /** + * @return ThemeProperties|null + */ + public function parentThemeProperties(): ?ThemeProperties + { + $template = $this->template(); + if (!$template) { + return null; + } + + $parent = wp_get_theme($template, get_theme_root($template)); + + return static::new($parent->get_template_directory()); + } +} diff --git a/lib/packages/Psr/Container/ContainerExceptionInterface.php b/lib/packages/Psr/Container/ContainerExceptionInterface.php index e36fa7885..78ee05e4a 100644 --- a/lib/packages/Psr/Container/ContainerExceptionInterface.php +++ b/lib/packages/Psr/Container/ContainerExceptionInterface.php @@ -1,7 +1,4 @@ modules = $modules; + } + + private function setup(): void { + if ( $this->is_initialized ) { + return; + } + + $this->services = array(); + $this->extensions = array(); + + foreach ( $this->modules as $module ) { + $service_provider = $module->setup(); + + $this->services = array_merge( + $this->services, + $service_provider->getFactories() + ); + + foreach ( $service_provider->getExtensions() as $key => $extension ) { + if ( ! isset( $this->extensions[ $key ] ) ) { + $this->extensions[ $key ] = array(); + } + $this->extensions[ $key ][] = $extension; + } + } + + $this->is_initialized = true; + } + + /** + * Returns the services. + * + * @return array|callable[] + */ + public function services(): array { + $this->setup(); + return $this->services; + } + + /** + * Returns the extensions. + * + * @return array|callable[] + */ + public function extensions(): array { + $this->setup(); + + $map = array_map( function ( $extension_group ) { + return function ( $previous, ContainerInterface $container ) use ( $extension_group ) { + $value = $previous; + foreach ( $extension_group as $extension ) { + $value = $extension( $container, $value ); + } + return $value; + }; + }, $this->extensions ); + + return $map; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $container ): bool { + foreach ( $this->modules as $module ) { + $module->run( $container ); + } + return true; + } + +} From 63690fa696fc034b1993a2e5202cef1a4d658d87 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 24 Nov 2023 18:07:56 +0000 Subject: [PATCH 002/134] Fix lint --- bootstrap.php | 46 ++-------------------------- src/DhiiToModularityModule.php | 56 +++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 65 deletions(-) diff --git a/bootstrap.php b/bootstrap.php index fe9a0799b..4ab5049aa 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -5,15 +5,8 @@ * @package WooCommerce\PayPalCommerce */ -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\CachingContainer; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\CompositeCachingServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\CompositeContainer; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\DelegatingContainer; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ProxyContainer; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Package; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Properties\PluginProperties; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\DhiiToModularityModule; @@ -38,46 +31,11 @@ return function ( $modules = apply_filters( 'woocommerce_paypal_payments_modules', $modules ); // Initialize plugin. - $properties = PluginProperties::new(__FILE__); - $bootstrap = Package::new($properties); + $properties = PluginProperties::new( __FILE__ ); + $bootstrap = Package::new( $properties ); $bootstrap->addModule( new DhiiToModularityModule( $modules ) ); $bootstrap->boot(); return $bootstrap->container(); - -// $providers = array_map( -// function ( ModuleInterface $module ): ServiceProviderInterface { -// return $module->setup(); -// }, -// $modules -// ); - -// $provider = new CompositeCachingServiceProvider( $providers ); -// $proxy_container = new ProxyContainer(); -// // TODO: caching does not work currently, -// // may want to consider fixing it later (pass proxy as parent to DelegatingContainer) -// // for now not fixed since we were using this behavior for long time and fixing it now may break things. -// $container = new DelegatingContainer( $provider ); -// /** -// * Skip iterable vs array check. -// * -// * @psalm-suppress PossiblyInvalidArgument -// */ -// $app_container = new CachingContainer( -// new CompositeContainer( -// array_merge( -// $additional_containers, -// array( $container ) -// ) -// ) -// ); -// $proxy_container->setInnerContainer( $app_container ); -// -// foreach ( $modules as $module ) { -// /* @var $module ModuleInterface module */ -// $module->run( $app_container ); -// } -// -// return $app_container; }; diff --git a/src/DhiiToModularityModule.php b/src/DhiiToModularityModule.php index f584857a8..83baeccd8 100644 --- a/src/DhiiToModularityModule.php +++ b/src/DhiiToModularityModule.php @@ -1,6 +1,6 @@ modules = $modules; } + /** + * Performs module-specific setup and initializes this object based on module service providers. + * + * @return void + * @throws Vendor\Dhii\Modular\Module\Exception\ModuleExceptionInterface Throws in case of module setup failure. + */ private function setup(): void { if ( $this->is_initialized ) { return; } - $this->services = array(); + $this->services = array(); $this->extensions = array(); foreach ( $this->modules as $module ) { @@ -85,9 +93,7 @@ class DhiiToModularityModule implements ServiceModule, ExtendingModule, Executab } /** - * Returns the services. - * - * @return array|callable[] + * {@inheritDoc} */ public function services(): array { $this->setup(); @@ -95,24 +101,32 @@ class DhiiToModularityModule implements ServiceModule, ExtendingModule, Executab } /** - * Returns the extensions. - * - * @return array|callable[] + * {@inheritDoc} */ public function extensions(): array { $this->setup(); - $map = array_map( function ( $extension_group ) { - return function ( $previous, ContainerInterface $container ) use ( $extension_group ) { - $value = $previous; - foreach ( $extension_group as $extension ) { - $value = $extension( $container, $value ); - } - return $value; - }; - }, $this->extensions ); - - return $map; + return array_map( + function ( $extension_group ) { + /** + * Maps Dhii extensions to modularity. + * + * @param mixed $previous The previous value. + * @return ContainerInterface $container The container instance. + * + * @psalm-suppress MissingClosureParamType + * @psalm-suppress MissingClosureReturnType + */ + return function ( $previous, ContainerInterface $container ) use ( $extension_group ) { + $value = $previous; + foreach ( $extension_group as $extension ) { + $value = $extension( $container, $value ); + } + return $value; + }; + }, + $this->extensions + ); } /** From 1a21ef0d21418b74460dbaedeab45d61782410d5 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 24 Nov 2023 18:24:30 +0000 Subject: [PATCH 003/134] Fix composer warning --- composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index 36ce94f4e..fd07c70cd 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": "214504278540f7c3d05f10d1e67920b1", + "content-hash": "5c45654af6d2f3addad4a089950e515f", "packages": [ { "name": "container-interop/service-provider", From 838449251fb67077c232d07e7136df55a2e0863e Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 14 Dec 2023 13:55:19 +0000 Subject: [PATCH 004/134] Fix tests. --- tests/PHPUnit/bootstrap.php | 1 + tests/inc/wp_functions.php | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/inc/wp_functions.php diff --git a/tests/PHPUnit/bootstrap.php b/tests/PHPUnit/bootstrap.php index 75145ac11..8910b0241 100644 --- a/tests/PHPUnit/bootstrap.php +++ b/tests/PHPUnit/bootstrap.php @@ -4,6 +4,7 @@ declare(strict_types=1); define('TESTS_ROOT_DIR', dirname(__DIR__)); define('ROOT_DIR', dirname(TESTS_ROOT_DIR)); +require_once TESTS_ROOT_DIR . '/inc/wp_functions.php'; require_once ROOT_DIR . '/vendor/autoload.php'; require_once TESTS_ROOT_DIR . '/stubs/WC_Payment_Gateway.php'; require_once TESTS_ROOT_DIR . '/stubs/WC_Payment_Gateway_CC.php'; diff --git a/tests/inc/wp_functions.php b/tests/inc/wp_functions.php new file mode 100644 index 000000000..035e35885 --- /dev/null +++ b/tests/inc/wp_functions.php @@ -0,0 +1,41 @@ + Date: Fri, 15 Dec 2023 14:16:53 +0000 Subject: [PATCH 005/134] Refactor some modules to native modularity support. --- bootstrap.php | 13 +++++++ modules/ppcp-admin-notices/module.php | 4 +- .../ppcp-admin-notices/src/AdminNotices.php | 34 ++++++++--------- modules/ppcp-api-client/module.php | 4 +- modules/ppcp-api-client/src/ApiModule.php | 34 ++++++++--------- modules/ppcp-applepay/module.php | 4 +- modules/ppcp-applepay/src/ApplepayModule.php | 35 +++++++++--------- modules/ppcp-blocks/module.php | 4 +- modules/ppcp-blocks/src/BlocksModule.php | 37 ++++++++++--------- modules/ppcp-button/module.php | 4 +- modules/ppcp-button/src/ButtonModule.php | 37 +++++++++---------- 11 files changed, 107 insertions(+), 103 deletions(-) diff --git a/bootstrap.php b/bootstrap.php index 4ab5049aa..b4f61914c 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -34,6 +34,19 @@ return function ( $properties = PluginProperties::new( __FILE__ ); $bootstrap = Package::new( $properties ); + + + foreach ($modules as $key => $module) { + if ( + $module instanceof \WooCommerce\PayPalCommerce\AdminNotices\AdminNotices || + $module instanceof \WooCommerce\PayPalCommerce\Button\ButtonModule + ) { + $bootstrap->addModule( $module ); + unset($modules[$key]); + } + } + + $bootstrap->addModule( new DhiiToModularityModule( $modules ) ); $bootstrap->boot(); diff --git a/modules/ppcp-admin-notices/module.php b/modules/ppcp-admin-notices/module.php index 94db126b1..cb59f2988 100644 --- a/modules/ppcp-admin-notices/module.php +++ b/modules/ppcp-admin-notices/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\AdminNotices; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): AdminNotices { return new AdminNotices(); }; diff --git a/modules/ppcp-admin-notices/src/AdminNotices.php b/modules/ppcp-admin-notices/src/AdminNotices.php index 73fe24b71..fd3166d50 100644 --- a/modules/ppcp-admin-notices/src/AdminNotices.php +++ b/modules/ppcp-admin-notices/src/AdminNotices.php @@ -9,30 +9,36 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\AdminNotices; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class AdminNotices */ -class AdminNotices implements ModuleInterface { +class AdminNotices implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { add_action( 'admin_notices', function() use ( $c ) { @@ -40,13 +46,7 @@ class AdminNotices implements ModuleInterface { $renderer->render(); } ); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } } diff --git a/modules/ppcp-api-client/module.php b/modules/ppcp-api-client/module.php index d01a4253f..401dab48a 100644 --- a/modules/ppcp-api-client/module.php +++ b/modules/ppcp-api-client/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\ApiClient; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return function (): ModuleInterface { +return function (): ApiModule { return new ApiModule(); }; diff --git a/modules/ppcp-api-client/src/ApiModule.php b/modules/ppcp-api-client/src/ApiModule.php index 42bc1f117..f4db40f11 100644 --- a/modules/ppcp-api-client/src/ApiModule.php +++ b/modules/ppcp-api-client/src/ApiModule.php @@ -12,31 +12,37 @@ namespace WooCommerce\PayPalCommerce\ApiClient; use WC_Order; use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry; use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderTransient; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; /** * Class ApiModule */ -class ApiModule implements ModuleInterface { +class ApiModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { add_action( 'woocommerce_after_calculate_totals', function ( \WC_Cart $cart ) { @@ -94,13 +100,7 @@ class ApiModule implements ModuleInterface { 10, 2 ); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } } diff --git a/modules/ppcp-applepay/module.php b/modules/ppcp-applepay/module.php index b8a05dcc9..1ab30942c 100644 --- a/modules/ppcp-applepay/module.php +++ b/modules/ppcp-applepay/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Applepay; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): ApplepayModule { return new ApplepayModule(); }; diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index 86aaff278..74aa3f0ea 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -17,30 +17,37 @@ use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice; use WooCommerce\PayPalCommerce\Onboarding\Environment; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class ApplepayModule */ -class ApplepayModule implements ModuleInterface { +class ApplepayModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; + /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { $module = $this; // Clears product status when appropriate. @@ -116,14 +123,8 @@ class ApplepayModule implements ModuleInterface { 100, 2 ); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } /** diff --git a/modules/ppcp-blocks/module.php b/modules/ppcp-blocks/module.php index cfb4f43f9..042ab6f56 100644 --- a/modules/ppcp-blocks/module.php +++ b/modules/ppcp-blocks/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Blocks; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): BlocksModule { return new BlocksModule(); }; diff --git a/modules/ppcp-blocks/src/BlocksModule.php b/modules/ppcp-blocks/src/BlocksModule.php index 1766806b7..afe4eb430 100644 --- a/modules/ppcp-blocks/src/BlocksModule.php +++ b/modules/ppcp-blocks/src/BlocksModule.php @@ -12,29 +12,36 @@ namespace WooCommerce\PayPalCommerce\Blocks; use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry; use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class BlocksModule */ -class BlocksModule implements ModuleInterface { +class BlocksModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; + /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { if ( ! class_exists( 'Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType' ) || ! function_exists( 'woocommerce_store_api_register_payment_requirements' ) @@ -54,7 +61,7 @@ class BlocksModule implements ModuleInterface { } ); - return; + return true; } add_action( @@ -88,13 +95,7 @@ class BlocksModule implements ModuleInterface { $endpoint->handle_request(); } ); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } } diff --git a/modules/ppcp-button/module.php b/modules/ppcp-button/module.php index b2077096e..68f04fe13 100644 --- a/modules/ppcp-button/module.php +++ b/modules/ppcp-button/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Button; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): ButtonModule { return new ButtonModule(); }; diff --git a/modules/ppcp-button/src/ButtonModule.php b/modules/ppcp-button/src/ButtonModule.php index 67dec01f3..cd2c8d381 100644 --- a/modules/ppcp-button/src/ButtonModule.php +++ b/modules/ppcp-button/src/ButtonModule.php @@ -14,8 +14,6 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\SimulateCartEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint; @@ -23,29 +21,36 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint; use WooCommerce\PayPalCommerce\Button\Endpoint\StartPayPalVaultingEndpoint; use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class ButtonModule */ -class ButtonModule implements ModuleInterface { - +class ButtonModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { add_action( 'wp', @@ -91,6 +96,8 @@ class ButtonModule implements ModuleInterface { ); $this->register_ajax_endpoints( $c ); + + return true; } /** @@ -211,12 +218,4 @@ class ButtonModule implements ModuleInterface { } ); } - - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { - } } From e5404848059e97dbeb8fc1e2f222e97533dc95fb Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Tue, 19 Dec 2023 10:13:45 +0000 Subject: [PATCH 006/134] Fix extensions. --- bootstrap.php | 5 +++-- modules/ppcp-applepay/extensions.php | 2 +- modules/ppcp-blocks/extensions.php | 10 +++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/bootstrap.php b/bootstrap.php index b4f61914c..3d15509c5 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -34,11 +34,12 @@ return function ( $properties = PluginProperties::new( __FILE__ ); $bootstrap = Package::new( $properties ); - - foreach ($modules as $key => $module) { if ( $module instanceof \WooCommerce\PayPalCommerce\AdminNotices\AdminNotices || + $module instanceof \WooCommerce\PayPalCommerce\ApiClient\ApiModule || + $module instanceof \WooCommerce\PayPalCommerce\Applepay\ApplepayModule || + $module instanceof \WooCommerce\PayPalCommerce\Blocks\BlocksModule || $module instanceof \WooCommerce\PayPalCommerce\Button\ButtonModule ) { $bootstrap->addModule( $module ); diff --git a/modules/ppcp-applepay/extensions.php b/modules/ppcp-applepay/extensions.php index 694a7b8a9..89828849f 100644 --- a/modules/ppcp-applepay/extensions.php +++ b/modules/ppcp-applepay/extensions.php @@ -18,7 +18,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return array( - 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { + 'wcgateway.settings.fields' => function ( array $fields, ContainerInterface $container ): array { // Eligibility check. if ( ! $container->has( 'applepay.eligible' ) || ! $container->get( 'applepay.eligible' ) ) { diff --git a/modules/ppcp-blocks/extensions.php b/modules/ppcp-blocks/extensions.php index 31f90576d..b4f643969 100644 --- a/modules/ppcp-blocks/extensions.php +++ b/modules/ppcp-blocks/extensions.php @@ -13,7 +13,7 @@ use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; return array( - 'wcgateway.button.locations' => function ( ContainerInterface $container, array $locations ): array { + 'wcgateway.button.locations' => function ( array $locations, ContainerInterface $container ): array { return array_merge( $locations, array( @@ -22,13 +22,13 @@ return array( ) ); }, - 'wcgateway.settings.pay-later.messaging-locations' => function ( ContainerInterface $container, array $locations ): array { + 'wcgateway.settings.pay-later.messaging-locations' => function ( array $locations, ContainerInterface $container ): array { unset( $locations['checkout-block-express'] ); unset( $locations['cart-block'] ); return $locations; }, - 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { + 'wcgateway.settings.fields' => function ( array $fields, ContainerInterface $container ): array { $insert_after = function( array $array, string $key, array $new ): array { $keys = array_keys( $array ); $index = array_search( $key, $keys, true ); @@ -59,7 +59,7 @@ Skipping the final confirmation on the checkout page may impact the buyer experi ); }, - 'button.pay-now-contexts' => function ( ContainerInterface $container, array $contexts ): array { + 'button.pay-now-contexts' => function ( array $contexts, ContainerInterface $container ): array { if ( ! $container->get( 'blocks.settings.final_review_enabled' ) ) { $contexts[] = 'checkout-block'; $contexts[] = 'cart-block'; @@ -68,7 +68,7 @@ Skipping the final confirmation on the checkout page may impact the buyer experi return $contexts; }, - 'button.handle-shipping-in-paypal' => function ( ContainerInterface $container ): bool { + 'button.handle-shipping-in-paypal' => function ( bool $previous, ContainerInterface $container ): bool { return ! $container->get( 'blocks.settings.final_review_enabled' ); }, ); From 429232f60f37c01f19bdedf95f739bae48fd5f29 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Tue, 19 Dec 2023 17:26:09 +0000 Subject: [PATCH 007/134] Refactor remaining modules to Modularity. Remove Dhii dependencies. --- bootstrap.php | 16 +- modules/ppcp-card-fields/module.php | 4 +- .../ppcp-card-fields/src/CardFieldsModule.php | 30 ++-- modules/ppcp-compat/module.php | 4 +- modules/ppcp-compat/src/CompatModule.php | 39 +++-- modules/ppcp-googlepay/extensions.php | 2 +- modules/ppcp-googlepay/module.php | 4 +- .../ppcp-googlepay/src/GooglepayModule.php | 35 ++--- modules/ppcp-onboarding/module.php | 4 +- .../ppcp-onboarding/src/OnboardingModule.php | 34 ++--- modules/ppcp-order-tracking/module.php | 4 +- .../src/OrderTrackingModule.php | 29 ++-- .../ppcp-paypal-subscriptions/extensions.php | 2 - modules/ppcp-paypal-subscriptions/module.php | 4 +- .../src/PayPalSubscriptionsModule.php | 28 ++-- .../ppcp-save-payment-methods/extensions.php | 2 - modules/ppcp-save-payment-methods/module.php | 4 +- .../src/SavePaymentMethodsModule.php | 31 ++-- .../ppcp-saved-payment-checker/extensions.php | 2 +- modules/ppcp-saved-payment-checker/module.php | 4 +- .../src/SavedPaymentCheckerModule.php | 28 ++-- modules/ppcp-session/module.php | 4 +- modules/ppcp-session/src/SessionModule.php | 35 ++--- modules/ppcp-status-report/module.php | 4 +- .../src/StatusReportModule.php | 33 ++-- modules/ppcp-uninstall/extensions.php | 2 +- modules/ppcp-uninstall/module.php | 4 +- .../ppcp-uninstall/src/UninstallModule.php | 28 ++-- modules/ppcp-vaulting/module.php | 4 +- modules/ppcp-vaulting/src/VaultingModule.php | 34 +++-- modules/ppcp-wc-gateway/extensions.php | 16 +- modules/ppcp-wc-gateway/module.php | 4 +- .../ppcp-wc-gateway/src/WCGatewayModule.php | 37 +++-- modules/ppcp-wc-subscriptions/module.php | 4 +- .../src/WcSubscriptionsModule.php | 36 +++-- modules/ppcp-webhooks/extensions.php | 3 +- modules/ppcp-webhooks/module.php | 4 +- modules/ppcp-webhooks/src/WebhookModule.php | 34 ++--- modules/woocommerce-logging/module.php | 4 +- .../src/WooCommerceLoggingModule.php | 28 ++-- src/DhiiToModularityModule.php | 142 ------------------ src/PluginModule.php | 27 ++-- tests/PHPUnit/ModularTestCase.php | 17 ++- .../Processor/OrderProcessorTest.php | 4 +- .../WcSubscriptions/RenewalHandlerTest.php | 4 +- 45 files changed, 341 insertions(+), 481 deletions(-) delete mode 100644 src/DhiiToModularityModule.php diff --git a/bootstrap.php b/bootstrap.php index 3d15509c5..1972d92d3 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -8,7 +8,6 @@ use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Package; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Properties\PluginProperties; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; -use WooCommerce\PayPalCommerce\DhiiToModularityModule; return function ( string $root_dir, @@ -34,21 +33,10 @@ return function ( $properties = PluginProperties::new( __FILE__ ); $bootstrap = Package::new( $properties ); - foreach ($modules as $key => $module) { - if ( - $module instanceof \WooCommerce\PayPalCommerce\AdminNotices\AdminNotices || - $module instanceof \WooCommerce\PayPalCommerce\ApiClient\ApiModule || - $module instanceof \WooCommerce\PayPalCommerce\Applepay\ApplepayModule || - $module instanceof \WooCommerce\PayPalCommerce\Blocks\BlocksModule || - $module instanceof \WooCommerce\PayPalCommerce\Button\ButtonModule - ) { - $bootstrap->addModule( $module ); - unset($modules[$key]); - } + foreach ( $modules as $module ) { + $bootstrap->addModule( $module ); } - - $bootstrap->addModule( new DhiiToModularityModule( $modules ) ); $bootstrap->boot(); return $bootstrap->container(); diff --git a/modules/ppcp-card-fields/module.php b/modules/ppcp-card-fields/module.php index 088900ab9..94cc0782f 100644 --- a/modules/ppcp-card-fields/module.php +++ b/modules/ppcp-card-fields/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\CardFields; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): CardFieldsModule { return new CardFieldsModule(); }; diff --git a/modules/ppcp-card-fields/src/CardFieldsModule.php b/modules/ppcp-card-fields/src/CardFieldsModule.php index 8524f1f6d..ddcdf962d 100644 --- a/modules/ppcp-card-fields/src/CardFieldsModule.php +++ b/modules/ppcp-card-fields/src/CardFieldsModule.php @@ -9,9 +9,10 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\CardFields; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; @@ -19,24 +20,29 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class CardFieldsModule */ -class CardFieldsModule implements ModuleInterface { +class CardFieldsModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { if ( ! $c->get( 'card-fields.eligible' ) ) { - return; + return true; } /** @@ -117,5 +123,7 @@ class CardFieldsModule implements ModuleInterface { return $data; } ); + + return true; } } diff --git a/modules/ppcp-compat/module.php b/modules/ppcp-compat/module.php index 2f9ccf4b0..50c3e58d2 100644 --- a/modules/ppcp-compat/module.php +++ b/modules/ppcp-compat/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Compat; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): CompatModule { return new CompatModule(); }; diff --git a/modules/ppcp-compat/src/CompatModule.php b/modules/ppcp-compat/src/CompatModule.php index 44cfd1988..3f1d29c89 100644 --- a/modules/ppcp-compat/src/CompatModule.php +++ b/modules/ppcp-compat/src/CompatModule.php @@ -9,9 +9,10 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Compat; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\Compat\Assets\CompatAssets; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; @@ -20,17 +21,21 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class CompatModule */ -class CompatModule implements ModuleInterface { +class CompatModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; + /** - * Setup the compatibility module. - * - * @return ServiceProviderInterface + * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; + } + + /** + * {@inheritDoc} + */ + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; } /** @@ -38,7 +43,7 @@ class CompatModule implements ModuleInterface { * * @throws NotFoundException */ - public function run( ContainerInterface $c ): void { + public function run( ContainerInterface $c ): bool { $this->initialize_ppec_compat_layer( $c ); $this->fix_site_ground_optimizer_compatibility( $c ); @@ -54,14 +59,8 @@ class CompatModule implements ModuleInterface { $this->migrate_smart_button_settings( $c ); $this->fix_page_builders(); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } /** diff --git a/modules/ppcp-googlepay/extensions.php b/modules/ppcp-googlepay/extensions.php index 1583e5c6e..68b400c98 100644 --- a/modules/ppcp-googlepay/extensions.php +++ b/modules/ppcp-googlepay/extensions.php @@ -18,7 +18,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return array( - 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { + 'wcgateway.settings.fields' => function ( array $fields, ContainerInterface $container ): array { // Eligibility check. if ( ! $container->has( 'googlepay.eligible' ) || ! $container->get( 'googlepay.eligible' ) ) { diff --git a/modules/ppcp-googlepay/module.php b/modules/ppcp-googlepay/module.php index 2e146435b..cfa949499 100644 --- a/modules/ppcp-googlepay/module.php +++ b/modules/ppcp-googlepay/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Googlepay; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): GooglepayModule { return new GooglepayModule(); }; diff --git a/modules/ppcp-googlepay/src/GooglepayModule.php b/modules/ppcp-googlepay/src/GooglepayModule.php index e478881ba..fcc87ada8 100644 --- a/modules/ppcp-googlepay/src/GooglepayModule.php +++ b/modules/ppcp-googlepay/src/GooglepayModule.php @@ -15,30 +15,37 @@ use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; use WooCommerce\PayPalCommerce\Googlepay\Endpoint\UpdatePaymentDataEndpoint; use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus; use WooCommerce\PayPalCommerce\Googlepay\Helper\AvailabilityNotice; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class GooglepayModule */ -class GooglepayModule implements ModuleInterface { +class GooglepayModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; + /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { // Clears product status when appropriate. add_action( @@ -159,13 +166,7 @@ class GooglepayModule implements ModuleInterface { }, 1 ); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } } diff --git a/modules/ppcp-onboarding/module.php b/modules/ppcp-onboarding/module.php index 55d1b4df3..dc255e3c2 100644 --- a/modules/ppcp-onboarding/module.php +++ b/modules/ppcp-onboarding/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Onboarding; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): OnboardingModule { return new OnboardingModule(); }; diff --git a/modules/ppcp-onboarding/src/OnboardingModule.php b/modules/ppcp-onboarding/src/OnboardingModule.php index 578cda42c..40e137832 100644 --- a/modules/ppcp-onboarding/src/OnboardingModule.php +++ b/modules/ppcp-onboarding/src/OnboardingModule.php @@ -10,33 +10,39 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Onboarding; use WooCommerce\PayPalCommerce\Onboarding\Endpoint\UpdateSignupLinksEndpoint; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets; use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class OnboardingModule */ -class OnboardingModule implements ModuleInterface { +class OnboardingModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { $asset_loader = $c->get( 'onboarding.assets' ); /** @@ -107,13 +113,7 @@ class OnboardingModule implements ModuleInterface { // Initialize REST routes at the appropriate time. $rest_controller = $c->get( 'onboarding.rest' ); add_action( 'rest_api_init', array( $rest_controller, 'register_routes' ) ); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } } diff --git a/modules/ppcp-order-tracking/module.php b/modules/ppcp-order-tracking/module.php index a82bbb033..7816e8d4a 100644 --- a/modules/ppcp-order-tracking/module.php +++ b/modules/ppcp-order-tracking/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\OrderTracking; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): OrderTrackingModule { return new OrderTrackingModule(); }; diff --git a/modules/ppcp-order-tracking/src/OrderTrackingModule.php b/modules/ppcp-order-tracking/src/OrderTrackingModule.php index 5d5905cef..bc3bdf960 100644 --- a/modules/ppcp-order-tracking/src/OrderTrackingModule.php +++ b/modules/ppcp-order-tracking/src/OrderTrackingModule.php @@ -10,9 +10,10 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\OrderTracking; use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\OrderTracking\Assets\OrderEditPageAssets; @@ -22,8 +23,8 @@ use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; /** * Class OrderTrackingModule */ -class OrderTrackingModule implements ModuleInterface { - +class OrderTrackingModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; use TrackingAvailabilityTrait; public const PPCP_TRACKING_INFO_META_NAME = '_ppcp_paypal_tracking_info_meta_name'; @@ -31,11 +32,15 @@ class OrderTrackingModule implements ModuleInterface { /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; + } + + /** + * {@inheritDoc} + */ + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; } /** @@ -44,7 +49,7 @@ class OrderTrackingModule implements ModuleInterface { * @param ContainerInterface $c A services container instance. * @throws NotFoundException */ - public function run( ContainerInterface $c ): void { + public function run( ContainerInterface $c ): bool { $endpoint = $c->get( 'order-tracking.endpoint.controller' ); assert( $endpoint instanceof OrderTrackingEndpoint ); @@ -109,5 +114,7 @@ class OrderTrackingModule implements ModuleInterface { 10, 2 ); + + return true; } } diff --git a/modules/ppcp-paypal-subscriptions/extensions.php b/modules/ppcp-paypal-subscriptions/extensions.php index fc91cd245..a02c96045 100644 --- a/modules/ppcp-paypal-subscriptions/extensions.php +++ b/modules/ppcp-paypal-subscriptions/extensions.php @@ -9,6 +9,4 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\PayPalSubscriptions; -use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; - return array(); diff --git a/modules/ppcp-paypal-subscriptions/module.php b/modules/ppcp-paypal-subscriptions/module.php index ee5f79da8..f09b27206 100644 --- a/modules/ppcp-paypal-subscriptions/module.php +++ b/modules/ppcp-paypal-subscriptions/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\PayPalSubscriptions; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): PayPalSubscriptionsModule { return new PayPalSubscriptionsModule(); }; diff --git a/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php index a69aaefef..e1d32fde7 100644 --- a/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php +++ b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php @@ -22,9 +22,10 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\Onboarding\Environment; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; @@ -34,22 +35,27 @@ use WP_Post; /** * Class SavedPaymentCheckerModule */ -class PayPalSubscriptionsModule implements ModuleInterface { +class PayPalSubscriptionsModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { add_action( 'save_post', /** @@ -641,6 +647,8 @@ class PayPalSubscriptionsModule implements ModuleInterface { } } ); + + return true; } /** diff --git a/modules/ppcp-save-payment-methods/extensions.php b/modules/ppcp-save-payment-methods/extensions.php index 1758f8960..cbcb904d7 100644 --- a/modules/ppcp-save-payment-methods/extensions.php +++ b/modules/ppcp-save-payment-methods/extensions.php @@ -9,6 +9,4 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\SavePaymentMethods; -use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; - return array(); diff --git a/modules/ppcp-save-payment-methods/module.php b/modules/ppcp-save-payment-methods/module.php index 85f1b6416..a4187d4e3 100644 --- a/modules/ppcp-save-payment-methods/module.php +++ b/modules/ppcp-save-payment-methods/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\SavePaymentMethods; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): SavePaymentMethodsModule { return new SavePaymentMethodsModule(); }; diff --git a/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php index 9dcb02359..4f5c8e8ba 100644 --- a/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php +++ b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php @@ -22,9 +22,10 @@ use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait; use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CaptureCardPayment; use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken; use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; @@ -33,26 +34,30 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class SavePaymentMethodsModule */ -class SavePaymentMethodsModule implements ModuleInterface { - +class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; use ContextTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { if ( ! $c->get( 'save-payment-methods.eligible' ) ) { - return; + return true; } add_filter( @@ -335,6 +340,8 @@ class SavePaymentMethodsModule implements ModuleInterface { $endpoint->handle_request(); } ); + + return true; } /** diff --git a/modules/ppcp-saved-payment-checker/extensions.php b/modules/ppcp-saved-payment-checker/extensions.php index e712a03fc..dcdbd169d 100644 --- a/modules/ppcp-saved-payment-checker/extensions.php +++ b/modules/ppcp-saved-payment-checker/extensions.php @@ -14,7 +14,7 @@ use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; return array( - 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { + 'wcgateway.settings.fields' => function ( array $fields, ContainerInterface $container ): array { $subscription_helper = $container->get( 'wc-subscriptions.helper' ); assert( $subscription_helper instanceof SubscriptionHelper ); diff --git a/modules/ppcp-saved-payment-checker/module.php b/modules/ppcp-saved-payment-checker/module.php index 9f5217ab8..63e55692b 100644 --- a/modules/ppcp-saved-payment-checker/module.php +++ b/modules/ppcp-saved-payment-checker/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\SavedPaymentChecker; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): SavedPaymentCheckerModule { return new SavedPaymentCheckerModule(); }; diff --git a/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php b/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php index 6a6ae3c79..2c2d58ff1 100644 --- a/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php +++ b/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php @@ -11,31 +11,37 @@ namespace WooCommerce\PayPalCommerce\SavedPaymentChecker; use Psr\Log\LoggerInterface; use WC_Order; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class SavedPaymentCheckerModule */ -class SavedPaymentCheckerModule implements ModuleInterface { +class SavedPaymentCheckerModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { /** * Set authorize intent for vaulted subscriptions, so we can void if payment not saved. @@ -138,5 +144,7 @@ class SavedPaymentCheckerModule implements ModuleInterface { } } ); + + return true; } } diff --git a/modules/ppcp-session/module.php b/modules/ppcp-session/module.php index 80392d729..b75551e9f 100644 --- a/modules/ppcp-session/module.php +++ b/modules/ppcp-session/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Session; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return function (): ModuleInterface { +return function (): SessionModule { return new SessionModule(); }; diff --git a/modules/ppcp-session/src/SessionModule.php b/modules/ppcp-session/src/SessionModule.php index cecc1a98f..e67d6014c 100644 --- a/modules/ppcp-session/src/SessionModule.php +++ b/modules/ppcp-session/src/SessionModule.php @@ -14,16 +14,19 @@ use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Session\Cancellation\CancelController; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class SessionModule */ -class SessionModule implements ModuleInterface { +class SessionModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; + /** * A flag to avoid multiple requests to reload order. * @@ -34,17 +37,21 @@ class SessionModule implements ModuleInterface { /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { add_action( 'woocommerce_init', function () use ( $c ) { @@ -96,13 +103,7 @@ class SessionModule implements ModuleInterface { 10, 2 ); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } } diff --git a/modules/ppcp-status-report/module.php b/modules/ppcp-status-report/module.php index 35edc894c..0dd438cdb 100644 --- a/modules/ppcp-status-report/module.php +++ b/modules/ppcp-status-report/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\StatusReport; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): StatusReportModule { return new StatusReportModule(); }; diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index f26412778..ec9703814 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -9,10 +9,11 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\StatusReport; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint; @@ -26,16 +27,21 @@ use WooCommerce\PayPalCommerce\Webhooks\WebhookEventStorage; /** * Class StatusReportModule */ -class StatusReportModule implements ModuleInterface { +class StatusReportModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; + } + + /** + * {@inheritDoc} + */ + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; } /** @@ -43,7 +49,7 @@ class StatusReportModule implements ModuleInterface { * * @param ContainerInterface $c A services container instance. */ - public function run( ContainerInterface $c ): void { + public function run( ContainerInterface $c ): bool { add_action( 'woocommerce_system_status_report', function () use ( $c ) { @@ -183,12 +189,9 @@ class StatusReportModule implements ModuleInterface { ); } ); - } - /** - * {@inheritDoc} - */ - public function getKey() { } + return true; + } /** * It returns the current onboarding status. diff --git a/modules/ppcp-uninstall/extensions.php b/modules/ppcp-uninstall/extensions.php index 94e44737e..6f40091e7 100644 --- a/modules/ppcp-uninstall/extensions.php +++ b/modules/ppcp-uninstall/extensions.php @@ -14,7 +14,7 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return array( - 'wcgateway.settings.fields' => static function ( ContainerInterface $container, array $fields ): array { + 'wcgateway.settings.fields' => static function ( array $fields, ContainerInterface $container ): array { $uninstall_fields = array( 'uninstall_heading' => array( 'heading' => __( 'Uninstall/Clear Database', 'woocommerce-paypal-payments' ), diff --git a/modules/ppcp-uninstall/module.php b/modules/ppcp-uninstall/module.php index c3783cbb3..a3fca3039 100644 --- a/modules/ppcp-uninstall/module.php +++ b/modules/ppcp-uninstall/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Uninstall; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return function (): ModuleInterface { +return function (): UninstallModule { return new UninstallModule(); }; diff --git a/modules/ppcp-uninstall/src/UninstallModule.php b/modules/ppcp-uninstall/src/UninstallModule.php index 25d65ae0f..2cb2dce52 100644 --- a/modules/ppcp-uninstall/src/UninstallModule.php +++ b/modules/ppcp-uninstall/src/UninstallModule.php @@ -12,31 +12,37 @@ namespace WooCommerce\PayPalCommerce\Uninstall; use Exception; use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData; use WooCommerce\PayPalCommerce\Uninstall\Assets\ClearDatabaseAssets; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class UninstallModule */ -class UninstallModule implements ModuleInterface { +class UninstallModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $container ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $container ): bool { $page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' ); if ( Settings::CONNECTION_TAB_ID === $page_id ) { $this->registerClearDatabaseAssets( $container->get( 'uninstall.clear-db-assets' ) ); @@ -50,6 +56,8 @@ class UninstallModule implements ModuleInterface { $action_names = $container->get( 'uninstall.ppcp-all-action-names' ); $this->handleClearDbAjaxRequest( $request_data, $clear_db, $clear_db_endpoint, $option_names, $scheduled_action_names, $action_names ); + + return true; } /** diff --git a/modules/ppcp-vaulting/module.php b/modules/ppcp-vaulting/module.php index fb42c4f9c..4266fbf00 100644 --- a/modules/ppcp-vaulting/module.php +++ b/modules/ppcp-vaulting/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Vaulting; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): VaultingModule { return new VaultingModule(); }; diff --git a/modules/ppcp-vaulting/src/VaultingModule.php b/modules/ppcp-vaulting/src/VaultingModule.php index c9e7bd40a..c150dfe96 100644 --- a/modules/ppcp-vaulting/src/VaultingModule.php +++ b/modules/ppcp-vaulting/src/VaultingModule.php @@ -13,9 +13,10 @@ use Psr\Log\LoggerInterface; use RuntimeException; use WC_Payment_Token; use WC_Payment_Tokens; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; @@ -26,17 +27,21 @@ use WP_User_Query; /** * Class StatusReportModule */ -class VaultingModule implements ModuleInterface { - +class VaultingModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; + } + + /** + * {@inheritDoc} + */ + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; } /** @@ -45,7 +50,7 @@ class VaultingModule implements ModuleInterface { * @param ContainerInterface $container A services container instance. * @throws NotFoundException When service could not be found. */ - public function run( ContainerInterface $container ): void { + public function run( ContainerInterface $container ): bool { $listener = $container->get( 'vaulting.customer-approval-listener' ); assert( $listener instanceof CustomerApprovalListener ); @@ -203,6 +208,8 @@ class VaultingModule implements ModuleInterface { return $methods; } ); + + return true; } /** @@ -260,9 +267,4 @@ class VaultingModule implements ModuleInterface { $timestamp += $interval_in_seconds; } } - - /** - * {@inheritDoc} - */ - public function getKey() { } } diff --git a/modules/ppcp-wc-gateway/extensions.php b/modules/ppcp-wc-gateway/extensions.php index aca11f1b1..fe2de006b 100644 --- a/modules/ppcp-wc-gateway/extensions.php +++ b/modules/ppcp-wc-gateway/extensions.php @@ -17,15 +17,15 @@ use Psr\Log\LoggerInterface; return array( - 'api.merchant_email' => static function ( ContainerInterface $container ): string { + 'api.merchant_email' => static function ( string $previous, ContainerInterface $container ): string { $settings = $container->get( 'wcgateway.settings' ); return $settings->has( 'merchant_email' ) ? (string) $settings->get( 'merchant_email' ) : ''; }, - 'api.merchant_id' => static function ( ContainerInterface $container ): string { + 'api.merchant_id' => static function ( string $previous, ContainerInterface $container ): string { $settings = $container->get( 'wcgateway.settings' ); return $settings->has( 'merchant_id' ) ? (string) $settings->get( 'merchant_id' ) : ''; }, - 'api.partner_merchant_id' => static function ( ContainerInterface $container ): string { + 'api.partner_merchant_id' => static function ( string $previous, ContainerInterface $container ): string { $environment = $container->get( 'onboarding.environment' ); /** @@ -36,20 +36,20 @@ return array( return $environment->current_environment_is( Environment::SANDBOX ) ? (string) $container->get( 'api.partner_merchant_id-sandbox' ) : (string) $container->get( 'api.partner_merchant_id-production' ); }, - 'api.key' => static function ( ContainerInterface $container ): string { + 'api.key' => static function ( string $previous, ContainerInterface $container ): string { $settings = $container->get( 'wcgateway.settings' ); $key = $settings->has( 'client_id' ) ? (string) $settings->get( 'client_id' ) : ''; return $key; }, - 'api.secret' => static function ( ContainerInterface $container ): string { + 'api.secret' => static function ( string $previous, ContainerInterface $container ): string { $settings = $container->get( 'wcgateway.settings' ); return $settings->has( 'client_secret' ) ? (string) $settings->get( 'client_secret' ) : ''; }, - 'api.prefix' => static function ( ContainerInterface $container ): string { + 'api.prefix' => static function ( string $previous, ContainerInterface $container ): string { $settings = $container->get( 'wcgateway.settings' ); return $settings->has( 'prefix' ) ? (string) $settings->get( 'prefix' ) : 'WC-'; }, - 'woocommerce.logger.woocommerce' => function ( ContainerInterface $container ): LoggerInterface { + 'woocommerce.logger.woocommerce' => function ( LoggerInterface $previous, ContainerInterface $container ): LoggerInterface { if ( ! function_exists( 'wc_get_logger' ) || ! $container->get( 'wcgateway.logging.is-enabled' ) ) { return new NullLogger(); } @@ -60,7 +60,7 @@ return array( $source ); }, - 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { + 'wcgateway.settings.fields' => function ( array $fields, ContainerInterface $container ): array { $files = array( 'paypal-smart-button-fields.php', 'connection-tab-fields.php', diff --git a/modules/ppcp-wc-gateway/module.php b/modules/ppcp-wc-gateway/module.php index 64b4601d8..ce8f30ed6 100644 --- a/modules/ppcp-wc-gateway/module.php +++ b/modules/ppcp-wc-gateway/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): WCGatewayModule { return new WCGatewayModule(); }; diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index 6af49c778..c3efb1210 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -13,10 +13,11 @@ use Psr\Log\LoggerInterface; use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint; -use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WC_Order; use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository; use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture; @@ -54,22 +55,27 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class WcGatewayModule */ -class WCGatewayModule implements ModuleInterface { +class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { $this->register_payment_gateways( $c ); $this->register_order_functionality( $c ); $this->register_columns( $c ); @@ -430,6 +436,8 @@ class WCGatewayModule implements ModuleInterface { $c->get( 'wcgateway.cli.settings.command' ) ); } + + return true; } /** @@ -698,13 +706,4 @@ class WCGatewayModule implements ModuleInterface { 2 ); } - - - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { - } } diff --git a/modules/ppcp-wc-subscriptions/module.php b/modules/ppcp-wc-subscriptions/module.php index a298bac91..2d87674af 100644 --- a/modules/ppcp-wc-subscriptions/module.php +++ b/modules/ppcp-wc-subscriptions/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcSubscriptions; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): WcSubscriptionsModule { return new WcSubscriptionsModule(); }; diff --git a/modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php b/modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php index c5fb04541..dc58f836e 100644 --- a/modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php +++ b/modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php @@ -11,12 +11,12 @@ namespace WooCommerce\PayPalCommerce\WcSubscriptions; use Psr\Log\LoggerInterface; use WC_Order; -use WC_Subscription; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; @@ -28,24 +28,28 @@ use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; /** * Class SubscriptionModule */ -class WcSubscriptionsModule implements ModuleInterface { - +class WcSubscriptionsModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; use TransactionIdHandlingTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { add_action( 'woocommerce_scheduled_subscription_payment_' . PayPalGateway::ID, /** @@ -142,14 +146,8 @@ class WcSubscriptionsModule implements ModuleInterface { 20, 2 ); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } /** diff --git a/modules/ppcp-webhooks/extensions.php b/modules/ppcp-webhooks/extensions.php index 7368e3c89..5f61258b6 100644 --- a/modules/ppcp-webhooks/extensions.php +++ b/modules/ppcp-webhooks/extensions.php @@ -10,10 +10,11 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Webhooks; use WooCommerce\PayPalCommerce\Onboarding\State; +use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return array( - 'wcgateway.settings.fields' => static function ( $container, array $fields ): array { + 'wcgateway.settings.fields' => static function ( array $fields, ContainerInterface $container ): array { $status_page_fields = array( 'webhook_status_heading' => array( 'heading' => __( 'Webhook Status', 'woocommerce-paypal-payments' ), diff --git a/modules/ppcp-webhooks/module.php b/modules/ppcp-webhooks/module.php index 7d223a528..2425c3049 100644 --- a/modules/ppcp-webhooks/module.php +++ b/modules/ppcp-webhooks/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Webhooks; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): WebhookModule { return new WebhookModule(); }; diff --git a/modules/ppcp-webhooks/src/WebhookModule.php b/modules/ppcp-webhooks/src/WebhookModule.php index 2458e5b4d..04c389263 100644 --- a/modules/ppcp-webhooks/src/WebhookModule.php +++ b/modules/ppcp-webhooks/src/WebhookModule.php @@ -10,10 +10,11 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Webhooks; use WooCommerce\PayPalCommerce\Onboarding\State; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use Exception; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; @@ -25,22 +26,27 @@ use WooCommerce\PayPalCommerce\Webhooks\Status\Assets\WebhooksStatusPageAssets; /** * Class WebhookModule */ -class WebhookModule implements ModuleInterface { +class WebhookModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $container ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $container ): bool { $logger = $container->get( 'woocommerce.logger.woocommerce' ); assert( $logger instanceof LoggerInterface ); @@ -158,13 +164,7 @@ class WebhookModule implements ModuleInterface { ); } ); - } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { + return true; } } diff --git a/modules/woocommerce-logging/module.php b/modules/woocommerce-logging/module.php index b4ebf4c90..ac9624d5f 100644 --- a/modules/woocommerce-logging/module.php +++ b/modules/woocommerce-logging/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\WooCommerce\Logging; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return function (): ModuleInterface { +return function (): WooCommerceLoggingModule { return new WooCommerceLoggingModule(); }; diff --git a/modules/woocommerce-logging/src/WooCommerceLoggingModule.php b/modules/woocommerce-logging/src/WooCommerceLoggingModule.php index b314bc445..f345da263 100644 --- a/modules/woocommerce-logging/src/WooCommerceLoggingModule.php +++ b/modules/woocommerce-logging/src/WooCommerceLoggingModule.php @@ -9,38 +9,36 @@ declare(strict_types=1); namespace WooCommerce\WooCommerce\Logging; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class WooCommerceLoggingModule */ -class WooCommerceLoggingModule implements ModuleInterface { +class WooCommerceLoggingModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; } - /** - * Returns the key for the module. - * - * @return string|void + * {@inheritDoc} */ - public function getKey() { + public function run( ContainerInterface $c ): bool { + return true; } } diff --git a/src/DhiiToModularityModule.php b/src/DhiiToModularityModule.php deleted file mode 100644 index 83baeccd8..000000000 --- a/src/DhiiToModularityModule.php +++ /dev/null @@ -1,142 +0,0 @@ -modules = $modules; - } - - /** - * Performs module-specific setup and initializes this object based on module service providers. - * - * @return void - * @throws Vendor\Dhii\Modular\Module\Exception\ModuleExceptionInterface Throws in case of module setup failure. - */ - private function setup(): void { - if ( $this->is_initialized ) { - return; - } - - $this->services = array(); - $this->extensions = array(); - - foreach ( $this->modules as $module ) { - $service_provider = $module->setup(); - - $this->services = array_merge( - $this->services, - $service_provider->getFactories() - ); - - foreach ( $service_provider->getExtensions() as $key => $extension ) { - if ( ! isset( $this->extensions[ $key ] ) ) { - $this->extensions[ $key ] = array(); - } - $this->extensions[ $key ][] = $extension; - } - } - - $this->is_initialized = true; - } - - /** - * {@inheritDoc} - */ - public function services(): array { - $this->setup(); - return $this->services; - } - - /** - * {@inheritDoc} - */ - public function extensions(): array { - $this->setup(); - - return array_map( - function ( $extension_group ) { - /** - * Maps Dhii extensions to modularity. - * - * @param mixed $previous The previous value. - * @return ContainerInterface $container The container instance. - * - * @psalm-suppress MissingClosureParamType - * @psalm-suppress MissingClosureReturnType - */ - return function ( $previous, ContainerInterface $container ) use ( $extension_group ) { - $value = $previous; - foreach ( $extension_group as $extension ) { - $value = $extension( $container, $value ); - } - return $value; - }; - }, - $this->extensions - ); - } - - /** - * {@inheritDoc} - */ - public function run( ContainerInterface $container ): bool { - foreach ( $this->modules as $module ) { - $module->run( $container ); - } - return true; - } - -} diff --git a/src/PluginModule.php b/src/PluginModule.php index 5ec283941..fa4784f5c 100644 --- a/src/PluginModule.php +++ b/src/PluginModule.php @@ -9,37 +9,36 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class PluginModule */ -class PluginModule implements ModuleInterface { +class PluginModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/services.php', - require __DIR__ . '/extensions.php' - ); + public function services(): array { + return require __DIR__ . '/services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/extensions.php'; } /** - * Returns the key for the module. - * - * @return string|void + * {@inheritDoc} */ - public function getKey() { + public function run( ContainerInterface $c ): bool { + return true; } } diff --git a/tests/PHPUnit/ModularTestCase.php b/tests/PHPUnit/ModularTestCase.php index a880acfbe..f7a5561cb 100644 --- a/tests/PHPUnit/ModularTestCase.php +++ b/tests/PHPUnit/ModularTestCase.php @@ -4,10 +4,10 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce; use WooCommerce\PayPalCommerce\Helper\RedirectorStub; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use function Brain\Monkey\Functions\when; @@ -68,16 +68,19 @@ class ModularTestCase extends TestCase } ], $overriddenServices); - $module = new class ($overriddenServices) implements ModuleInterface { + $module = new class ($overriddenServices) implements ServiceModule, ExecutableModule { + use ModuleClassNameIdTrait; + public function __construct(array $services) { $this->services = $services; } - public function setup(): ServiceProviderInterface{ - return new ServiceProvider($this->services, []); + public function services(): array { + return $this->services; } - public function run(ContainerInterface $c): void { + public function run(ContainerInterface $c): bool { + return true; } }; diff --git a/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php b/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php index d27ec6ff7..1422b23c7 100644 --- a/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php +++ b/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php @@ -7,7 +7,6 @@ use Exception; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\Dictionary; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization; @@ -23,6 +22,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderHelper; use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Session\SessionHandler; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Container\ReadOnlyContainer; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; @@ -37,7 +37,7 @@ class OrderProcessorTest extends TestCase public function setUp(): void { parent::setUp(); - $this->environment = new Environment(new Dictionary([])); + $this->environment = new Environment(new ReadOnlyContainer([], [], [], [])); } public function testAuthorize() { diff --git a/tests/PHPUnit/WcSubscriptions/RenewalHandlerTest.php b/tests/PHPUnit/WcSubscriptions/RenewalHandlerTest.php index 3899fa0f7..ef754852b 100644 --- a/tests/PHPUnit/WcSubscriptions/RenewalHandlerTest.php +++ b/tests/PHPUnit/WcSubscriptions/RenewalHandlerTest.php @@ -3,7 +3,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcSubscriptions; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\Dictionary; use Exception; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; @@ -22,6 +21,7 @@ use WooCommerce\PayPalCommerce\TestCase; use Mockery; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Container\ReadOnlyContainer; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; @@ -50,7 +50,7 @@ class RenewalHandlerTest extends TestCase $this->purchaseUnitFactory = Mockery::mock(PurchaseUnitFactory::class); $this->shippingPreferenceFactory = Mockery::mock(ShippingPreferenceFactory::class); $this->payerFactory = Mockery::mock(PayerFactory::class); - $this->environment = new Environment(new Dictionary([])); + $this->environment = new Environment(new ReadOnlyContainer([], [], [], [])); $authorizedPaymentProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class); $settings = Mockery::mock(Settings::class); $settings From 2d21035457dc3a2256a641a8ae339b9daa17ff9d Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Wed, 20 Dec 2023 15:33:40 +0000 Subject: [PATCH 008/134] Fix uninstall dependency. --- uninstall.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uninstall.php b/uninstall.php index 59c98d3c0..26fa6cb67 100644 --- a/uninstall.php +++ b/uninstall.php @@ -8,7 +8,7 @@ declare(strict_types=1); use WooCommerce\PayPalCommerce\Uninstall\ClearDatabaseInterface; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\CachingContainer; +use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { @@ -35,7 +35,7 @@ require $main_plugin_file; $bootstrap = require "{$root_dir}/bootstrap.php"; $app_container = $bootstrap( $root_dir ); - assert( $app_container instanceof CachingContainer ); + assert( $app_container instanceof ContainerInterface ); $settings = $app_container->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); From 4f61ed45a76325557b5a363976a100241dd39e12 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Wed, 20 Dec 2023 15:56:11 +0000 Subject: [PATCH 009/134] Moving inpsyde/modularity to require-dev. --- composer.json | 4 +- composer.lock | 138 +++++++++++++++++++++++++------------------------- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/composer.json b/composer.json index 96c9459ef..79fb463ef 100644 --- a/composer.json +++ b/composer.json @@ -11,14 +11,14 @@ "wikimedia/composer-merge-plugin": "^2.0", "wp-oop/wordpress-interface": "^0.1.0-alpha1", "dhii/versions": "^0.1.0-alpha1", - "symfony/polyfill-php80": "^1.19", - "inpsyde/modularity": "^1.7" + "symfony/polyfill-php80": "^1.19" }, "require-dev": { "psr/container": "^1.0", "dhii/module-interface": "^0.2 || ^0.3", "container-interop/service-provider": "^0.4.0", "dhii/containers": "^0.1.0-alpha1", + "inpsyde/modularity": "^1.7", "woocommerce/woocommerce-sniffs": "^0.1.0", "phpunit/phpunit": "^7.0 | ^8.0 | ^9.0", "brain/monkey": "^2.4", diff --git a/composer.lock b/composer.lock index fd07c70cd..b6a1169eb 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": "5c45654af6d2f3addad4a089950e515f", + "content-hash": "6451ae49d3d58728421aa734385ab707", "packages": [ { "name": "container-interop/service-provider", @@ -294,74 +294,6 @@ }, "time": "2021-12-08T16:54:50+00:00" }, - { - "name": "inpsyde/modularity", - "version": "1.7.2", - "source": { - "type": "git", - "url": "https://github.com/inpsyde/modularity.git", - "reference": "43f4b3a7c8fbb585a44fb7a619e2546b338a8934" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/inpsyde/modularity/zipball/43f4b3a7c8fbb585a44fb7a619e2546b338a8934", - "reference": "43f4b3a7c8fbb585a44fb7a619e2546b338a8934", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": ">=7.2", - "psr/container": "^1.1.0 || ^2" - }, - "require-dev": { - "brain/monkey": "^2.6.1", - "inpsyde/php-coding-standards": "^1", - "johnpbloch/wordpress-core": ">=5.8", - "mikey179/vfsstream": "^v1.6.10", - "php-stubs/wordpress-stubs": ">=5.8@stable", - "phpunit/phpunit": "^8.5.21 || ^9.6.7", - "vimeo/psalm": "^4.13.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Inpsyde\\Modularity\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0-or-later" - ], - "authors": [ - { - "name": "Inpsyde GmbH", - "email": "hello@inpsyde.com", - "homepage": "https://inpsyde.com/", - "role": "Company" - }, - { - "name": "Christian Leucht", - "email": "c.leucht@inpsyde.com", - "role": "Developer" - }, - { - "name": "Giuseppe Mazzapica", - "email": "g.mazzapica@inpsyde.com", - "role": "Developer" - } - ], - "description": "Modular PSR-11 implementation for WordPress plugins, themes or libraries.", - "support": { - "issues": "https://github.com/inpsyde/modularity/issues", - "source": "https://github.com/inpsyde/modularity/tree/1.7.2" - }, - "time": "2023-11-16T11:19:47+00:00" - }, { "name": "psr/container", "version": "1.1.1", @@ -1783,6 +1715,74 @@ }, "time": "2020-07-09T08:09:16+00:00" }, + { + "name": "inpsyde/modularity", + "version": "1.7.2", + "source": { + "type": "git", + "url": "https://github.com/inpsyde/modularity.git", + "reference": "43f4b3a7c8fbb585a44fb7a619e2546b338a8934" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/inpsyde/modularity/zipball/43f4b3a7c8fbb585a44fb7a619e2546b338a8934", + "reference": "43f4b3a7c8fbb585a44fb7a619e2546b338a8934", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2", + "psr/container": "^1.1.0 || ^2" + }, + "require-dev": { + "brain/monkey": "^2.6.1", + "inpsyde/php-coding-standards": "^1", + "johnpbloch/wordpress-core": ">=5.8", + "mikey179/vfsstream": "^v1.6.10", + "php-stubs/wordpress-stubs": ">=5.8@stable", + "phpunit/phpunit": "^8.5.21 || ^9.6.7", + "vimeo/psalm": "^4.13.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Inpsyde\\Modularity\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Inpsyde GmbH", + "email": "hello@inpsyde.com", + "homepage": "https://inpsyde.com/", + "role": "Company" + }, + { + "name": "Christian Leucht", + "email": "c.leucht@inpsyde.com", + "role": "Developer" + }, + { + "name": "Giuseppe Mazzapica", + "email": "g.mazzapica@inpsyde.com", + "role": "Developer" + } + ], + "description": "Modular PSR-11 implementation for WordPress plugins, themes or libraries.", + "support": { + "issues": "https://github.com/inpsyde/modularity/issues", + "source": "https://github.com/inpsyde/modularity/tree/1.7.2" + }, + "time": "2023-11-16T11:19:47+00:00" + }, { "name": "mockery/mockery", "version": "1.3.6", From cbc8de5a9d0e28f619df778f45ff23fb4bdb9e43 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 19 Apr 2024 15:26:55 +0100 Subject: [PATCH 010/134] Migrated AXO to modularity. --- modules/ppcp-axo/extensions.php | 2 +- modules/ppcp-axo/module.php | 4 +--- modules/ppcp-axo/src/AxoModule.php | 36 +++++++++++++++--------------- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/modules/ppcp-axo/extensions.php b/modules/ppcp-axo/extensions.php index 93e36e31c..51860df61 100644 --- a/modules/ppcp-axo/extensions.php +++ b/modules/ppcp-axo/extensions.php @@ -16,7 +16,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Helper\DisplayManager; return array( - 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { + 'wcgateway.settings.fields' => function ( array $fields, ContainerInterface $container ): array { $insert_after = function( array $array, string $key, array $new ): array { $keys = array_keys( $array ); diff --git a/modules/ppcp-axo/module.php b/modules/ppcp-axo/module.php index 8e0a3064f..4d71cadde 100644 --- a/modules/ppcp-axo/module.php +++ b/modules/ppcp-axo/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Axo; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): AxoModule { return new AxoModule(); }; diff --git a/modules/ppcp-axo/src/AxoModule.php b/modules/ppcp-axo/src/AxoModule.php index 6680c9fd7..b22e107ba 100644 --- a/modules/ppcp-axo/src/AxoModule.php +++ b/modules/ppcp-axo/src/AxoModule.php @@ -16,29 +16,36 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\Axo\Assets\AxoManager; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class AxoModule */ -class AxoModule implements ModuleInterface { +class AxoModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; + /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services(): array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): bool { $module = $this; add_filter( @@ -173,6 +180,7 @@ class AxoModule implements ModuleInterface { 1 ); + return true; } /** @@ -213,12 +221,4 @@ class AxoModule implements ModuleInterface { return $localized_script_data; } - - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { - } } From 534e41252476c65512992c162719c38353957c87 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Fri, 12 Jul 2024 17:32:59 +0200 Subject: [PATCH 011/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Extract=20preview?= =?UTF-8?q?=20classes=20to=20own=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../js/Preview/ApplePayPreviewButton.js | 61 ++++++++++ .../Preview/ApplePayPreviewButtonManager.js | 49 ++++++++ .../ppcp-applepay/resources/js/boot-admin.js | 110 +----------------- .../js/modules/Renderer/PreviewButton.js | 2 +- .../modules/Renderer/PreviewButtonManager.js | 2 +- .../js/Preview/GooglePayPreviewButton.js | 53 +++++++++ .../Preview/GooglePayPreviewButtonManager.js | 56 +++++++++ .../ppcp-googlepay/resources/js/boot-admin.js | 109 +---------------- 8 files changed, 223 insertions(+), 219 deletions(-) create mode 100644 modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js create mode 100644 modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js create mode 100644 modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js create mode 100644 modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js diff --git a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js new file mode 100644 index 000000000..6e3f721da --- /dev/null +++ b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js @@ -0,0 +1,61 @@ +import ApplepayButton from '../ApplepayButton'; +import PreviewButton from '../../../../ppcp-button/resources/js/modules/Renderer/PreviewButton'; + +/** + * A single Apple Pay preview button instance. + */ +export default class ApplePayPreviewButton extends PreviewButton { + constructor( args ) { + super( args ); + + this.selector = `${ args.selector }ApplePay`; + this.defaultAttributes = { + button: { + type: 'pay', + color: 'black', + lang: 'en', + }, + }; + } + + createNewWrapper() { + const element = super.createNewWrapper(); + element.addClass( 'ppcp-button-apm ppcp-button-applepay' ); + + return element; + } + + createButton( buttonConfig ) { + const button = new ApplepayButton( + 'preview', + null, + buttonConfig, + this.ppcpConfig + ); + + button.init( this.apiConfig ); + } + + /** + * Merge form details into the config object for preview. + * Mutates the previewConfig object; no return value. + * @param buttonConfig + * @param ppcpConfig + */ + dynamicPreviewConfig( buttonConfig, ppcpConfig ) { + // The Apple Pay button expects the "wrapper" to be an ID without `#` prefix! + buttonConfig.button.wrapper = buttonConfig.button.wrapper.replace( + /^#/, + '' + ); + + // Merge the current form-values into the preview-button configuration. + if ( ppcpConfig.button ) { + buttonConfig.button.type = ppcpConfig.button.style.type; + buttonConfig.button.color = ppcpConfig.button.style.color; + buttonConfig.button.lang = + ppcpConfig.button.style?.lang || + ppcpConfig.button.style.language; + } + } +} diff --git a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js new file mode 100644 index 000000000..43ecc37b8 --- /dev/null +++ b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js @@ -0,0 +1,49 @@ +import PreviewButtonManager from '../../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager'; +import ApplePayPreviewButton from './ApplePayPreviewButton'; + +/** + * Manages all Apple Pay preview buttons on this page. + */ +export default class ApplePayPreviewButtonManager extends PreviewButtonManager { + constructor() { + const args = { + methodName: 'ApplePay', + buttonConfig: window.wc_ppcp_applepay_admin, + }; + + super( args ); + } + + /** + * Responsible for fetching and returning the PayPal configuration object for this payment + * method. + * + * @param {{}} payPal - The PayPal SDK object provided by WidgetBuilder. + * @return {Promise<{}>} + */ + async fetchConfig( payPal ) { + const apiMethod = payPal?.Applepay()?.config; + + if ( ! apiMethod ) { + this.error( + 'configuration object cannot be retrieved from PayPal' + ); + return {}; + } + + return await apiMethod(); + } + + /** + * This method is responsible for creating a new PreviewButton instance and returning it. + * + * @param {string} wrapperId - CSS ID of the wrapper element. + * @return {ApplePayPreviewButton} + */ + createButtonInstance( wrapperId ) { + return new ApplePayPreviewButton( { + selector: wrapperId, + apiConfig: this.apiConfig, + } ); + } +} diff --git a/modules/ppcp-applepay/resources/js/boot-admin.js b/modules/ppcp-applepay/resources/js/boot-admin.js index 080d7c8aa..e92c03cdf 100644 --- a/modules/ppcp-applepay/resources/js/boot-admin.js +++ b/modules/ppcp-applepay/resources/js/boot-admin.js @@ -1,6 +1,4 @@ -import ApplepayButton from './ApplepayButton'; -import PreviewButton from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButton'; -import PreviewButtonManager from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager'; +import ApplePayPreviewButtonManager from './Preview/ApplePayPreviewButtonManager'; /** * Accessor that creates and returns a single PreviewButtonManager instance. @@ -14,111 +12,5 @@ const buttonManager = () => { return ApplePayPreviewButtonManager.instance; }; -/** - * Manages all Apple Pay preview buttons on this page. - */ -class ApplePayPreviewButtonManager extends PreviewButtonManager { - constructor() { - const args = { - methodName: 'ApplePay', - buttonConfig: window.wc_ppcp_applepay_admin, - }; - - super( args ); - } - - /** - * Responsible for fetching and returning the PayPal configuration object for this payment - * method. - * - * @param {{}} payPal - The PayPal SDK object provided by WidgetBuilder. - * @return {Promise<{}>} - */ - async fetchConfig( payPal ) { - const apiMethod = payPal?.Applepay()?.config; - - if ( ! apiMethod ) { - this.error( - 'configuration object cannot be retrieved from PayPal' - ); - return {}; - } - - return await apiMethod(); - } - - /** - * This method is responsible for creating a new PreviewButton instance and returning it. - * - * @param {string} wrapperId - CSS ID of the wrapper element. - * @return {ApplePayPreviewButton} - */ - createButtonInstance( wrapperId ) { - return new ApplePayPreviewButton( { - selector: wrapperId, - apiConfig: this.apiConfig, - } ); - } -} - -/** - * A single Apple Pay preview button instance. - */ -class ApplePayPreviewButton extends PreviewButton { - constructor( args ) { - super( args ); - - this.selector = `${ args.selector }ApplePay`; - this.defaultAttributes = { - button: { - type: 'pay', - color: 'black', - lang: 'en', - }, - }; - } - - createNewWrapper() { - const element = super.createNewWrapper(); - element.addClass( 'ppcp-button-applepay' ); - - return element; - } - - createButton( buttonConfig ) { - const button = new ApplepayButton( - 'preview', - null, - buttonConfig, - this.ppcpConfig - ); - - button.init( this.apiConfig ); - } - - /** - * Merge form details into the config object for preview. - * Mutates the previewConfig object; no return value. - * @param buttonConfig - * @param ppcpConfig - */ - dynamicPreviewConfig( buttonConfig, ppcpConfig ) { - // The Apple Pay button expects the "wrapper" to be an ID without `#` prefix! - buttonConfig.button.wrapper = buttonConfig.button.wrapper.replace( - /^#/, - '' - ); - - // Merge the current form-values into the preview-button configuration. - if ( ppcpConfig.button ) { - buttonConfig.button.type = ppcpConfig.button.style.type; - buttonConfig.button.color = ppcpConfig.button.style.color; - buttonConfig.button.lang = - ppcpConfig.button.style?.lang || - ppcpConfig.button.style.language; - } - } -} - // Initialize the preview button manager. buttonManager(); diff --git a/modules/ppcp-button/resources/js/modules/Renderer/PreviewButton.js b/modules/ppcp-button/resources/js/modules/Renderer/PreviewButton.js index cec951927..ac189e89e 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/PreviewButton.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/PreviewButton.js @@ -30,7 +30,7 @@ class PreviewButton { */ createNewWrapper() { const previewId = this.selector.replace( '#', '' ); - const previewClass = 'ppcp-button-apm'; + const previewClass = 'ppcp-preview-button'; return jQuery( `
` ); } diff --git a/modules/ppcp-button/resources/js/modules/Renderer/PreviewButtonManager.js b/modules/ppcp-button/resources/js/modules/Renderer/PreviewButtonManager.js index 42e715904..9cb9fa81f 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/PreviewButtonManager.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/PreviewButtonManager.js @@ -95,7 +95,7 @@ class PreviewButtonManager { */ createDummy( wrapperId ) { const elButton = document.createElement( 'div' ); - elButton.classList.add( 'ppcp-button-apm', 'ppcp-button-dummy' ); + elButton.classList.add( 'ppcp-preview-button', 'ppcp-button-dummy' ); elButton.innerHTML = `${ this.apiError ?? 'Not Available' }`; diff --git a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js new file mode 100644 index 000000000..7bd3ffa7f --- /dev/null +++ b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js @@ -0,0 +1,53 @@ +import GooglepayButton from '../GooglepayButton'; +import PreviewButton from '../../../../ppcp-button/resources/js/modules/Renderer/PreviewButton'; + +/** + * A single GooglePay preview button instance. + */ +export default class GooglePayPreviewButton extends PreviewButton { + constructor( args ) { + super( args ); + + this.selector = `${ args.selector }GooglePay`; + this.defaultAttributes = { + button: { + style: { + type: 'pay', + color: 'black', + language: 'en', + }, + }, + }; + } + + createNewWrapper() { + const element = super.createNewWrapper(); + element.addClass( 'ppcp-button-apm ppcp-button-googlepay' ); + + return element; + } + + createButton( buttonConfig ) { + const button = new GooglepayButton( + 'preview', + null, + buttonConfig, + this.ppcpConfig + ); + + button.init( this.apiConfig ); + } + + /** + * Merge form details into the config object for preview. + * Mutates the previewConfig object; no return value. + * @param buttonConfig + * @param ppcpConfig + */ + dynamicPreviewConfig( buttonConfig, ppcpConfig ) { + // Merge the current form-values into the preview-button configuration. + if ( ppcpConfig.button && buttonConfig.button ) { + Object.assign( buttonConfig.button.style, ppcpConfig.button.style ); + } + } +} diff --git a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js new file mode 100644 index 000000000..0aaef0396 --- /dev/null +++ b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js @@ -0,0 +1,56 @@ +import PreviewButtonManager from '../../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager'; +import GooglePayPreviewButton from './GooglePayPreviewButton'; + +/** + * Manages all GooglePay preview buttons on this page. + */ +export default class GooglePayPreviewButtonManager extends PreviewButtonManager { + constructor() { + const args = { + methodName: 'GooglePay', + buttonConfig: window.wc_ppcp_googlepay_admin, + }; + + super( args ); + } + + /** + * Responsible for fetching and returning the PayPal configuration object for this payment + * method. + * + * @param {{}} payPal - The PayPal SDK object provided by WidgetBuilder. + * @return {Promise<{}>} + */ + async fetchConfig( payPal ) { + const apiMethod = payPal?.Googlepay()?.config; + + if ( ! apiMethod ) { + this.error( + 'configuration object cannot be retrieved from PayPal' + ); + return {}; + } + + try { + return await apiMethod(); + } catch ( error ) { + if ( error.message.includes( 'Not Eligible' ) ) { + this.apiError = 'Not Eligible'; + } + return null; + } + } + + /** + * This method is responsible for creating a new PreviewButton instance and returning it. + * + * @param {string} wrapperId - CSS ID of the wrapper element. + * @return {GooglePayPreviewButton} + */ + createButtonInstance( wrapperId ) { + return new GooglePayPreviewButton( { + selector: wrapperId, + apiConfig: this.apiConfig, + } ); + } +} diff --git a/modules/ppcp-googlepay/resources/js/boot-admin.js b/modules/ppcp-googlepay/resources/js/boot-admin.js index 41cace0c0..953a6088e 100644 --- a/modules/ppcp-googlepay/resources/js/boot-admin.js +++ b/modules/ppcp-googlepay/resources/js/boot-admin.js @@ -1,6 +1,4 @@ -import GooglepayButton from './GooglepayButton'; -import PreviewButton from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButton'; -import PreviewButtonManager from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager'; +import GooglePayPreviewButtonManager from './Preview/GooglePayPreviewButtonManager'; /** * Accessor that creates and returns a single PreviewButtonManager instance. @@ -14,110 +12,5 @@ const buttonManager = () => { return GooglePayPreviewButtonManager.instance; }; -/** - * Manages all GooglePay preview buttons on this page. - */ -class GooglePayPreviewButtonManager extends PreviewButtonManager { - constructor() { - const args = { - methodName: 'GooglePay', - buttonConfig: window.wc_ppcp_googlepay_admin, - }; - - super( args ); - } - - /** - * Responsible for fetching and returning the PayPal configuration object for this payment - * method. - * - * @param {{}} payPal - The PayPal SDK object provided by WidgetBuilder. - * @return {Promise<{}>} - */ - async fetchConfig( payPal ) { - const apiMethod = payPal?.Googlepay()?.config; - - if ( ! apiMethod ) { - this.error( - 'configuration object cannot be retrieved from PayPal' - ); - return {}; - } - - try { - return await apiMethod(); - } catch ( error ) { - if ( error.message.includes( 'Not Eligible' ) ) { - this.apiError = 'Not Eligible'; - } - return null; - } - } - - /** - * This method is responsible for creating a new PreviewButton instance and returning it. - * - * @param {string} wrapperId - CSS ID of the wrapper element. - * @return {GooglePayPreviewButton} - */ - createButtonInstance( wrapperId ) { - return new GooglePayPreviewButton( { - selector: wrapperId, - apiConfig: this.apiConfig, - } ); - } -} - -/** - * A single GooglePay preview button instance. - */ -class GooglePayPreviewButton extends PreviewButton { - constructor( args ) { - super( args ); - - this.selector = `${ args.selector }GooglePay`; - this.defaultAttributes = { - button: { - style: { - type: 'pay', - color: 'black', - language: 'en', - }, - }, - }; - } - - createNewWrapper() { - const element = super.createNewWrapper(); - element.addClass( 'ppcp-button-googlepay' ); - - return element; - } - - createButton( buttonConfig ) { - const button = new GooglepayButton( - 'preview', - null, - buttonConfig, - this.ppcpConfig - ); - - button.init( this.apiConfig ); - } - - /** - * Merge form details into the config object for preview. - * Mutates the previewConfig object; no return value. - * @param buttonConfig - * @param ppcpConfig - */ - dynamicPreviewConfig( buttonConfig, ppcpConfig ) { - // Merge the current form-values into the preview-button configuration. - if ( ppcpConfig.button && buttonConfig.button ) { - Object.assign( buttonConfig.button.style, ppcpConfig.button.style ); - } - } -} - // Initialize the preview button manager. buttonManager(); From 2da8b516ff37f6f9e2999e8cee617a1f1befd513 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Fri, 12 Jul 2024 19:02:21 +0200 Subject: [PATCH 012/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Code=20organizatio?= =?UTF-8?q?n=20and=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move base classes for the preview buttons into “Preview” folder - Remove jQuery use inside those base classes - Extract dummy button to own class --- .../js/Preview/ApplePayPreviewButton.js | 8 ++-- .../Preview/ApplePayPreviewButtonManager.js | 2 +- .../js/modules/Preview/DummyPreviewButton.js | 31 +++++++++++++++ .../{Renderer => Preview}/PreviewButton.js | 39 ++++++++++++++++--- .../PreviewButtonManager.js | 34 ++++++---------- .../js/Preview/GooglePayPreviewButton.js | 8 ++-- .../Preview/GooglePayPreviewButtonManager.js | 2 +- 7 files changed, 85 insertions(+), 39 deletions(-) create mode 100644 modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js rename modules/ppcp-button/resources/js/modules/{Renderer => Preview}/PreviewButton.js (84%) rename modules/ppcp-button/resources/js/modules/{Renderer => Preview}/PreviewButtonManager.js (92%) diff --git a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js index 6e3f721da..de4807f78 100644 --- a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js +++ b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js @@ -1,5 +1,5 @@ import ApplepayButton from '../ApplepayButton'; -import PreviewButton from '../../../../ppcp-button/resources/js/modules/Renderer/PreviewButton'; +import PreviewButton from '../../../../ppcp-button/resources/js/modules/Preview/PreviewButton'; /** * A single Apple Pay preview button instance. @@ -19,10 +19,10 @@ export default class ApplePayPreviewButton extends PreviewButton { } createNewWrapper() { - const element = super.createNewWrapper(); - element.addClass( 'ppcp-button-apm ppcp-button-applepay' ); + const wrapper = super.createNewWrapper(); + wrapper.classList.add( 'ppcp-button-apm', 'ppcp-button-applepay' ); - return element; + return wrapper; } createButton( buttonConfig ) { diff --git a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js index 43ecc37b8..741b800db 100644 --- a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js +++ b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js @@ -1,4 +1,4 @@ -import PreviewButtonManager from '../../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager'; +import PreviewButtonManager from '../../../../ppcp-button/resources/js/modules/Preview/PreviewButtonManager'; import ApplePayPreviewButton from './ApplePayPreviewButton'; /** diff --git a/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js b/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js new file mode 100644 index 000000000..e7fe3e3ff --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js @@ -0,0 +1,31 @@ +import PreviewButton from './PreviewButton'; + +/** + * Dummy preview button, to use in case an APM button cannot be rendered + */ +export default class DummyPreviewButton extends PreviewButton { + #innerEl; + + constructor( args ) { + super( args ); + + this.selector = `${ args.selector }Dummy`; + this.label = args.label || 'Not Available'; + } + + createNewWrapper() { + const wrapper = super.createNewWrapper(); + wrapper.classList.add( 'ppcp-button-apm', 'ppcp-button-dummy' ); + + return wrapper; + } + + createButton( buttonConfig ) { + this.#innerEl?.remove(); + + this.#innerEl = document.createElement( 'div' ); + this.#innerEl.innerHTML = `
${ this.label }
`; + + this.domWrapper.appendChild( this.#innerEl ); + } +} diff --git a/modules/ppcp-button/resources/js/modules/Renderer/PreviewButton.js b/modules/ppcp-button/resources/js/modules/Preview/PreviewButton.js similarity index 84% rename from modules/ppcp-button/resources/js/modules/Renderer/PreviewButton.js rename to modules/ppcp-button/resources/js/modules/Preview/PreviewButton.js index ac189e89e..72f8c07df 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/PreviewButton.js +++ b/modules/ppcp-button/resources/js/modules/Preview/PreviewButton.js @@ -26,13 +26,16 @@ class PreviewButton { /** * Creates a new DOM node to contain the preview button. * - * @return {jQuery} Always a single jQuery element with the new DOM node. + * @return {HTMLElement} Always a single jQuery element with the new DOM node. */ createNewWrapper() { + const wrapper = document.createElement( 'div' ); const previewId = this.selector.replace( '#', '' ); const previewClass = 'ppcp-preview-button'; - return jQuery( `
` ); + wrapper.setAttribute( 'id', previewId ); + wrapper.setAttribute( 'class', previewClass ); + return wrapper; } /** @@ -109,10 +112,12 @@ class PreviewButton { console.error( 'Skip render, button is not configured yet' ); return; } + this.domWrapper = this.createNewWrapper(); - this.domWrapper.insertAfter( this.wrapper ); + this._insertWrapper(); } else { - this.domWrapper.empty().show(); + this._emptyWrapper(); + this._showWrapper(); } this.isVisible = true; @@ -151,16 +156,38 @@ class PreviewButton { * Using a timeout here will make the button visible again at the end of the current * event queue. */ - setTimeout( () => this.domWrapper.show() ); + setTimeout( () => this._showWrapper() ); } remove() { this.isVisible = false; if ( this.domWrapper ) { - this.domWrapper.hide().empty(); + this._hideWrapper(); + this._emptyWrapper(); } } + + _showWrapper() { + this.domWrapper.style.display = ''; + } + + _hideWrapper() { + this.domWrapper.style.display = 'none'; + } + + _emptyWrapper() { + this.domWrapper.innerHTML = ''; + } + + _insertWrapper() { + const wrapperElement = document.querySelector( this.wrapper ); + + wrapperElement.parentNode.insertBefore( + this.domWrapper, + wrapperElement.nextSibling + ); + } } export default PreviewButton; diff --git a/modules/ppcp-button/resources/js/modules/Renderer/PreviewButtonManager.js b/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js similarity index 92% rename from modules/ppcp-button/resources/js/modules/Renderer/PreviewButtonManager.js rename to modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js index 9cb9fa81f..c2df2b839 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/PreviewButtonManager.js +++ b/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js @@ -1,6 +1,7 @@ import { loadCustomScript } from '@paypal/paypal-js'; -import widgetBuilder from './WidgetBuilder'; import { debounce } from '../../../../../ppcp-blocks/resources/js/Helper/debounce'; +import widgetBuilder from '../Renderer/WidgetBuilder'; +import DummyPreviewButton from './DummyPreviewButton'; /** * Manages all PreviewButton instances of a certain payment method on the page. @@ -89,27 +90,14 @@ class PreviewButtonManager { * * This dummy is only visible on the admin side, and not rendered on the front-end. * - * @todo Consider refactoring this into a new class that extends the PreviewButton class. * @param wrapperId * @return {any} */ - createDummy( wrapperId ) { - const elButton = document.createElement( 'div' ); - elButton.classList.add( 'ppcp-preview-button', 'ppcp-button-dummy' ); - elButton.innerHTML = `${ - this.apiError ?? 'Not Available' - }`; - - document.querySelector( wrapperId ).appendChild( elButton ); - - const instDummy = { - setDynamic: () => instDummy, - setPpcpConfig: () => instDummy, - render: () => {}, - remove: () => {}, - }; - - return instDummy; + createDummyButtonInstance( wrapperId ) { + return new DummyPreviewButton( { + selector: wrapperId, + label: this.apiError, + } ); } registerEventListeners() { @@ -309,13 +297,13 @@ class PreviewButtonManager { const createButton = () => { if ( ! this.buttons[ id ] ) { let newInst; + if ( this.apiConfig && 'object' === typeof this.apiConfig ) { - newInst = this.createButtonInstance( id ).setButtonConfig( - this.buttonConfig - ); + newInst = this.createButtonInstance( id ); } else { - newInst = this.createDummy( id ); + newInst = this.createDummyButtonInstance( id ); } + newInst.setButtonConfig( this.buttonConfig ); this.buttons[ id ] = newInst; } diff --git a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js index 7bd3ffa7f..97bb62ea4 100644 --- a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js +++ b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js @@ -1,5 +1,5 @@ import GooglepayButton from '../GooglepayButton'; -import PreviewButton from '../../../../ppcp-button/resources/js/modules/Renderer/PreviewButton'; +import PreviewButton from '../../../../ppcp-button/resources/js/modules/Preview/PreviewButton'; /** * A single GooglePay preview button instance. @@ -21,10 +21,10 @@ export default class GooglePayPreviewButton extends PreviewButton { } createNewWrapper() { - const element = super.createNewWrapper(); - element.addClass( 'ppcp-button-apm ppcp-button-googlepay' ); + const wrapper = super.createNewWrapper(); + wrapper.classList.add( 'ppcp-button-apm', 'ppcp-button-googlepay' ); - return element; + return wrapper; } createButton( buttonConfig ) { diff --git a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js index 0aaef0396..0406c1cc4 100644 --- a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js +++ b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js @@ -1,4 +1,4 @@ -import PreviewButtonManager from '../../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager'; +import PreviewButtonManager from '../../../../ppcp-button/resources/js/modules/Preview/PreviewButtonManager'; import GooglePayPreviewButton from './GooglePayPreviewButton'; /** From 7f9cbd6f58da6b66d0b51c761e47c36f0ee92b88 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 15 Jul 2024 13:16:08 +0200 Subject: [PATCH 013/134] =?UTF-8?q?=F0=9F=90=9B=20Fix=20general=20preview?= =?UTF-8?q?=20button=20shape?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/ApplepayButton.js | 1 + .../js/modules/Preview/DummyPreviewButton.js | 17 +++++++++++++++++ .../resources/js/GooglepayButton.js | 9 ++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index 2bcac16fc..e60af5e79 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -216,6 +216,7 @@ class ApplepayButton { } const $wrapper = jQuery( '#' + wrapper ); + $wrapper.removeClass( 'ppcp-button-rect ppcp-button-pill' ); $wrapper.addClass( 'ppcp-button-' + ppcpStyle.shape ); if ( ppcpStyle.height ) { diff --git a/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js b/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js index e7fe3e3ff..ed5f3bee7 100644 --- a/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js +++ b/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js @@ -26,6 +26,23 @@ export default class DummyPreviewButton extends PreviewButton { this.#innerEl = document.createElement( 'div' ); this.#innerEl.innerHTML = `
${ this.label }
`; + this._applyShape( this.ppcpConfig?.button?.style?.shape ); + this.domWrapper.appendChild( this.#innerEl ); } + + /** + * Applies the button shape (rect/pill) to the dummy button + * + * @param {string|null} shape + * @private + */ + _applyShape( shape = 'rect' ) { + this.domWrapper.classList.remove( + 'ppcp-button-pill', + 'ppcp-button-rect' + ); + + this.domWrapper.classList.add( `ppcp-button-${ shape }` ); + } } diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 973648af3..8316c42e5 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -202,10 +202,13 @@ class GooglepayButton { const { wrapper, ppcpStyle, buttonStyle } = this.contextConfig(); this.waitForWrapper( wrapper, () => { - jQuery( wrapper ).addClass( 'ppcp-button-' + ppcpStyle.shape ); + const $wrapper = jQuery( wrapper ); + + $wrapper.removeClass( 'ppcp-button-rect ppcp-button-pill' ); + $wrapper.addClass( 'ppcp-button-' + ppcpStyle.shape ); if ( ppcpStyle.height ) { - jQuery( wrapper ).css( 'height', `${ ppcpStyle.height }px` ); + $wrapper.css( 'height', `${ ppcpStyle.height }px` ); } const button = this.paymentsClient.createButton( { @@ -217,7 +220,7 @@ class GooglepayButton { buttonSizeMode: 'fill', } ); - jQuery( wrapper ).append( button ); + $wrapper.append( button ); } ); } From 4cde024320263150d9ff39626d42914b4062630d Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 15 Jul 2024 13:18:07 +0200 Subject: [PATCH 014/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Consolidate=20the?= =?UTF-8?q?=20preview=20button=E2=80=99s=20CSS=20classes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Class names are now generated by the base class. This allows to remove a method from all derived classes --- .../resources/js/Preview/ApplePayPreviewButton.js | 7 ------- .../js/Preview/ApplePayPreviewButtonManager.js | 1 + .../resources/js/modules/Preview/PreviewButton.js | 15 ++++++++++----- .../js/modules/Preview/PreviewButtonManager.js | 8 ++++++++ .../js/Preview/GooglePayPreviewButton.js | 7 ------- .../js/Preview/GooglePayPreviewButtonManager.js | 1 + 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js index de4807f78..2ad3e23f5 100644 --- a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js +++ b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButton.js @@ -18,13 +18,6 @@ export default class ApplePayPreviewButton extends PreviewButton { }; } - createNewWrapper() { - const wrapper = super.createNewWrapper(); - wrapper.classList.add( 'ppcp-button-apm', 'ppcp-button-applepay' ); - - return wrapper; - } - createButton( buttonConfig ) { const button = new ApplepayButton( 'preview', diff --git a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js index 741b800db..be15166e6 100644 --- a/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js +++ b/modules/ppcp-applepay/resources/js/Preview/ApplePayPreviewButtonManager.js @@ -44,6 +44,7 @@ export default class ApplePayPreviewButtonManager extends PreviewButtonManager { return new ApplePayPreviewButton( { selector: wrapperId, apiConfig: this.apiConfig, + methodName: this.methodName, } ); } } diff --git a/modules/ppcp-button/resources/js/modules/Preview/PreviewButton.js b/modules/ppcp-button/resources/js/modules/Preview/PreviewButton.js index 72f8c07df..418bb57f5 100644 --- a/modules/ppcp-button/resources/js/modules/Preview/PreviewButton.js +++ b/modules/ppcp-button/resources/js/modules/Preview/PreviewButton.js @@ -5,16 +5,21 @@ import merge from 'deepmerge'; */ class PreviewButton { /** - * @param {string} selector - CSS ID of the wrapper, including the `#` - * @param {Object} apiConfig - PayPal configuration object; retrieved via a - * widgetBuilder API method + * @param {string} selector - CSS ID of the wrapper, including the `#` + * @param {Object} apiConfig - PayPal configuration object; retrieved via a + * widgetBuilder API method + * @param {string} methodName - Name of the payment method, e.g. "Google Pay" */ - constructor( { selector, apiConfig } ) { + constructor( { selector, apiConfig, methodName = '' } ) { this.apiConfig = apiConfig; this.defaultAttributes = {}; this.buttonConfig = {}; this.ppcpConfig = {}; this.isDynamic = true; + this.methodName = methodName; + this.methodSlug = this.methodName + .toLowerCase() + .replace( /[^a-z]+/g, '' ); // The selector is usually overwritten in constructor of derived class. this.selector = selector; @@ -31,7 +36,7 @@ class PreviewButton { createNewWrapper() { const wrapper = document.createElement( 'div' ); const previewId = this.selector.replace( '#', '' ); - const previewClass = 'ppcp-preview-button'; + const previewClass = `ppcp-preview-button ppcp-button-apm ppcp-button-${ this.methodSlug }`; wrapper.setAttribute( 'id', previewId ); wrapper.setAttribute( 'class', previewClass ); diff --git a/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js b/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js index c2df2b839..186cf7c45 100644 --- a/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js +++ b/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js @@ -21,6 +21,13 @@ class PreviewButtonManager { */ #onInit; + /** + * Initialize the new PreviewButtonManager. + * + * @param {string} methodName - Name of the payment method, e.g. "Google Pay" + * @param {Object} buttonConfig + * @param {Object} defaultAttributes + */ constructor( { methodName, buttonConfig, defaultAttributes } ) { // Define the payment method name in the derived class. this.methodName = methodName; @@ -97,6 +104,7 @@ class PreviewButtonManager { return new DummyPreviewButton( { selector: wrapperId, label: this.apiError, + methodName: this.methodName, } ); } diff --git a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js index 97bb62ea4..e6b27ee55 100644 --- a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js +++ b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButton.js @@ -20,13 +20,6 @@ export default class GooglePayPreviewButton extends PreviewButton { }; } - createNewWrapper() { - const wrapper = super.createNewWrapper(); - wrapper.classList.add( 'ppcp-button-apm', 'ppcp-button-googlepay' ); - - return wrapper; - } - createButton( buttonConfig ) { const button = new GooglepayButton( 'preview', diff --git a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js index 0406c1cc4..a3e9f66af 100644 --- a/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js +++ b/modules/ppcp-googlepay/resources/js/Preview/GooglePayPreviewButtonManager.js @@ -51,6 +51,7 @@ export default class GooglePayPreviewButtonManager extends PreviewButtonManager return new GooglePayPreviewButton( { selector: wrapperId, apiConfig: this.apiConfig, + methodName: this.methodName, } ); } } From 6081b9ddf9b2aa1fa32a507f4adb7576d64ac289 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 15 Jul 2024 13:19:37 +0200 Subject: [PATCH 015/134] =?UTF-8?q?=F0=9F=A9=B9=20Adjust=20the=20height=20?= =?UTF-8?q?of=20the=20Dummy=20preview-button?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dummy button now better aligns with the button settings --- .../js/modules/Preview/DummyPreviewButton.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js b/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js index ed5f3bee7..c780d188d 100644 --- a/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js +++ b/modules/ppcp-button/resources/js/modules/Preview/DummyPreviewButton.js @@ -26,7 +26,7 @@ export default class DummyPreviewButton extends PreviewButton { this.#innerEl = document.createElement( 'div' ); this.#innerEl.innerHTML = `
${ this.label }
`; - this._applyShape( this.ppcpConfig?.button?.style?.shape ); + this._applyStyles( this.ppcpConfig?.button?.style ); this.domWrapper.appendChild( this.#innerEl ); } @@ -34,15 +34,19 @@ export default class DummyPreviewButton extends PreviewButton { /** * Applies the button shape (rect/pill) to the dummy button * - * @param {string|null} shape + * @param {{shape: string, height: number|null}} style * @private */ - _applyShape( shape = 'rect' ) { + _applyStyles( style ) { this.domWrapper.classList.remove( 'ppcp-button-pill', 'ppcp-button-rect' ); - this.domWrapper.classList.add( `ppcp-button-${ shape }` ); + this.domWrapper.classList.add( `ppcp-button-${ style.shape }` ); + + if ( style.height ) { + this.domWrapper.style.height = `${ style.height }px`; + } } } From 07ec924c77cbcfa05d2807d5ae4eb4c4a59908ee Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 15 Jul 2024 13:43:09 +0200 Subject: [PATCH 016/134] =?UTF-8?q?=F0=9F=92=84=20Display=20the=20APM=20lo?= =?UTF-8?q?go=20in=20dummy=20preview-buttons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-applepay/resources/css/styles.scss | 5 +++++ modules/ppcp-googlepay/resources/css/styles.scss | 5 +++++ .../ppcp-wc-gateway/resources/css/common.scss | 16 ++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/modules/ppcp-applepay/resources/css/styles.scss b/modules/ppcp-applepay/resources/css/styles.scss index 3818b8db5..1cf632fd2 100644 --- a/modules/ppcp-applepay/resources/css/styles.scss +++ b/modules/ppcp-applepay/resources/css/styles.scss @@ -23,6 +23,11 @@ &.ppcp-button-minicart { --apple-pay-button-display: block; } + + &.ppcp-preview-button.ppcp-button-dummy { + /* URL must specify the correct module-folder! */ + --apm-button-dummy-background: url(../../../ppcp-applepay/assets/images/applepay.png); + } } .wp-block-woocommerce-checkout, .wp-block-woocommerce-cart { diff --git a/modules/ppcp-googlepay/resources/css/styles.scss b/modules/ppcp-googlepay/resources/css/styles.scss index c60212a2e..ad638b0b3 100644 --- a/modules/ppcp-googlepay/resources/css/styles.scss +++ b/modules/ppcp-googlepay/resources/css/styles.scss @@ -6,6 +6,11 @@ outline-offset: -1px; border-radius: var(--apm-button-border-radius); } + + &.ppcp-preview-button.ppcp-button-dummy { + /* URL must specify the correct module-folder! */ + --apm-button-dummy-background: url(../../../ppcp-googlepay/assets/images/googlepay.png); + } } .wp-block-woocommerce-checkout, .wp-block-woocommerce-cart { diff --git a/modules/ppcp-wc-gateway/resources/css/common.scss b/modules/ppcp-wc-gateway/resources/css/common.scss index b694547c8..9071e9e5a 100644 --- a/modules/ppcp-wc-gateway/resources/css/common.scss +++ b/modules/ppcp-wc-gateway/resources/css/common.scss @@ -31,9 +31,25 @@ $background-ident-color: #fbfbfb; &.ppcp-button-dummy { display: flex; + min-height: 25px; align-items: center; justify-content: center; background: #0001; + position: relative; + + &:before { + content: ''; + position: absolute; + left: 12px; + top: 50%; + transform: translateY(-50%); + width: 42px; + height: 24px; + background-image: var(--apm-button-dummy-background, none); + background-repeat: no-repeat; + background-size: contain; + background-position: center left; + } } } From a4a4f80a9935a21f5ba3247964957593c9141cca Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 15 Jul 2024 13:58:58 +0200 Subject: [PATCH 017/134] =?UTF-8?q?=F0=9F=90=9B=20Isolate=20preview=20chan?= =?UTF-8?q?ges=20to=20relevant=20sections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this, any style change updated all preview buttons on the current page. Now, most changes are limited to the current section. For exaple, changing the height of “Mini Cart Buttons” only updates the mini cart button preview, and no other preview sections. --- .../js/modules/Preview/PreviewButtonManager.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js b/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js index 186cf7c45..2afafad23 100644 --- a/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js +++ b/modules/ppcp-button/resources/js/modules/Preview/PreviewButtonManager.js @@ -283,6 +283,17 @@ class PreviewButtonManager { */ _configureAllButtons( ppcpConfig ) { Object.entries( this.buttons ).forEach( ( [ id, button ] ) => { + const limitWrapper = ppcpConfig.button?.wrapper; + + /** + * When the ppcpConfig object specifies a button wrapper, then ensure to limit preview + * changes to this individual wrapper. If no button wrapper is defined, the + * configuration is relevant for all buttons on the page. + */ + if ( limitWrapper && button.wrapper !== limitWrapper ) { + return; + } + this._configureButton( id, { ...ppcpConfig, button: { From 651549dbb01c2db35723ca30e7eceb4850dc9995 Mon Sep 17 00:00:00 2001 From: George Burduli Date: Tue, 16 Jul 2024 15:10:09 +0400 Subject: [PATCH 018/134] Display notice if Checkout Blocks is not active --- .../ppcp-wc-gateway/resources/css/common.scss | 8 +++++ modules/ppcp-wc-gateway/services.php | 30 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/modules/ppcp-wc-gateway/resources/css/common.scss b/modules/ppcp-wc-gateway/resources/css/common.scss index b694547c8..7a65a701c 100644 --- a/modules/ppcp-wc-gateway/resources/css/common.scss +++ b/modules/ppcp-wc-gateway/resources/css/common.scss @@ -82,6 +82,14 @@ $background-ident-color: #fbfbfb; } } +.ppcp-notice-success { + border-left-color: #00a32a; + + .highlight { + color: #00a32a; + } +} + .ppcp-notice-warning { border-left-color: #dba617; diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index f0d848216..45a93e346 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -26,6 +26,7 @@ use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Admin\RenderReauthorizeAction; use WooCommerce\PayPalCommerce\WcGateway\Endpoint\CaptureCardPayment; use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint; +use WooCommerce\PayPalCommerce\WcGateway\Helper\CartCheckoutDetector; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer; @@ -292,6 +293,24 @@ return array( static function ( ContainerInterface $container ): AuthorizeOrderActionNotice { return new AuthorizeOrderActionNotice(); }, + 'wcgateway.notice.checkout-blocks' => + static function ( ContainerInterface $container ): string { + $instructions_link = 'https://woocommerce.com/document/cart-checkout-blocks-status/#using-the-cart-and-checkout-blocks'; + if ( ! CartCheckoutDetector::has_block_checkout() ) { + $notice_content = sprintf( + /* translators: %1$s: URL to the instructions page. */ + __( + 'Your store\'s checkout page currently uses a classic checkout layout or a custom checkout widget. Advanced Card Processing now also supports the new & improved Checkout block. See this page for instructions on upgrading to the new Checkout layout.', + 'woocommerce-paypal-payments' + ), + esc_url( $instructions_link ) + ); + } else { + return ''; + } + + return '

' . $notice_content . '

'; + }, 'wcgateway.settings.sections-renderer' => static function ( ContainerInterface $container ): SectionsRenderer { return new SectionsRenderer( $container->get( 'wcgateway.current-ppcp-settings-page-id' ), @@ -533,6 +552,17 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), + 'dcc_block_checkout_notice' => array( + 'heading' => '', + 'html' => $container->get( 'wcgateway.notice.checkout-blocks' ), + 'type' => 'ppcp-html', + 'classes' => array(), + 'screens' => array( + State::STATE_ONBOARDED, + ), + 'requirements' => array( 'dcc' ), + 'gateway' => 'dcc', + ), 'dcc_enabled' => array( 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), 'desc_tip' => true, From 5d429c75e00f6711e312edd2f04e095bee87f7eb Mon Sep 17 00:00:00 2001 From: George Burduli Date: Tue, 16 Jul 2024 15:36:18 +0400 Subject: [PATCH 019/134] Improve notice format and text --- modules/ppcp-wc-gateway/services.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 45a93e346..5a5ee4d26 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -295,14 +295,16 @@ return array( }, 'wcgateway.notice.checkout-blocks' => static function ( ContainerInterface $container ): string { + $checkout_page_link = esc_url( get_edit_post_link( wc_get_page_id( 'checkout' ) ) ?? '' ); $instructions_link = 'https://woocommerce.com/document/cart-checkout-blocks-status/#using-the-cart-and-checkout-blocks'; - if ( ! CartCheckoutDetector::has_block_checkout() ) { + if ( CartCheckoutDetector::has_block_checkout() ) { $notice_content = sprintf( /* translators: %1$s: URL to the instructions page. */ __( - 'Your store\'s checkout page currently uses a classic checkout layout or a custom checkout widget. Advanced Card Processing now also supports the new & improved Checkout block. See this page for instructions on upgrading to the new Checkout layout.', + 'Info: The Checkout page of your store currently uses a classic checkout layout or a custom checkout widget. Advanced Card Processing supports the new Checkout block which improves conversion rates. See this page for instructions on how to upgrade to the new Checkout layout.', 'woocommerce-paypal-payments' ), + esc_url( $checkout_page_link ), esc_url( $instructions_link ) ); } else { From e1a93b373d0dc2065fc618880aa445421722bfcc Mon Sep 17 00:00:00 2001 From: George Burduli Date: Tue, 16 Jul 2024 15:38:19 +0400 Subject: [PATCH 020/134] Fix condition, translation instructions --- modules/ppcp-wc-gateway/services.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 5a5ee4d26..0adc2dbad 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -297,9 +297,9 @@ return array( static function ( ContainerInterface $container ): string { $checkout_page_link = esc_url( get_edit_post_link( wc_get_page_id( 'checkout' ) ) ?? '' ); $instructions_link = 'https://woocommerce.com/document/cart-checkout-blocks-status/#using-the-cart-and-checkout-blocks'; - if ( CartCheckoutDetector::has_block_checkout() ) { + if ( ! CartCheckoutDetector::has_block_checkout() ) { $notice_content = sprintf( - /* translators: %1$s: URL to the instructions page. */ + /* translators: %1$s: URL to the Checkout edit page. %2$s: URL to the WooCommerce Checkout instructions. */ __( 'Info: The Checkout page of your store currently uses a classic checkout layout or a custom checkout widget. Advanced Card Processing supports the new Checkout block which improves conversion rates. See this page for instructions on how to upgrade to the new Checkout layout.', 'woocommerce-paypal-payments' From cb9785993f005c5dd0bccb293cc34b1e221c6040 Mon Sep 17 00:00:00 2001 From: George Burduli Date: Tue, 16 Jul 2024 15:55:59 +0400 Subject: [PATCH 021/134] Only display notice if Fastlane is disabled --- modules/ppcp-wc-gateway/services.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 0adc2dbad..4286872cc 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -297,6 +297,14 @@ return array( static function ( ContainerInterface $container ): string { $checkout_page_link = esc_url( get_edit_post_link( wc_get_page_id( 'checkout' ) ) ?? '' ); $instructions_link = 'https://woocommerce.com/document/cart-checkout-blocks-status/#using-the-cart-and-checkout-blocks'; + + $settings = $container->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + if ( $settings->has( 'axo_enabled' ) && $settings->get( 'axo_enabled' ) ) { + return ''; + } + if ( ! CartCheckoutDetector::has_block_checkout() ) { $notice_content = sprintf( /* translators: %1$s: URL to the Checkout edit page. %2$s: URL to the WooCommerce Checkout instructions. */ From fc8b1dd6a68371306c47ce0123aee554b612e64b Mon Sep 17 00:00:00 2001 From: George Burduli Date: Tue, 16 Jul 2024 15:58:16 +0400 Subject: [PATCH 022/134] Reformat --- modules/ppcp-wc-gateway/services.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 4286872cc..575477bb4 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -295,9 +295,6 @@ return array( }, 'wcgateway.notice.checkout-blocks' => static function ( ContainerInterface $container ): string { - $checkout_page_link = esc_url( get_edit_post_link( wc_get_page_id( 'checkout' ) ) ?? '' ); - $instructions_link = 'https://woocommerce.com/document/cart-checkout-blocks-status/#using-the-cart-and-checkout-blocks'; - $settings = $container->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); @@ -305,6 +302,9 @@ return array( return ''; } + $checkout_page_link = esc_url( get_edit_post_link( wc_get_page_id( 'checkout' ) ) ?? '' ); + $instructions_link = 'https://woocommerce.com/document/cart-checkout-blocks-status/#using-the-cart-and-checkout-blocks'; + if ( ! CartCheckoutDetector::has_block_checkout() ) { $notice_content = sprintf( /* translators: %1$s: URL to the Checkout edit page. %2$s: URL to the WooCommerce Checkout instructions. */ From a65d599ec9ca7f163c4a0e9bb6d76346eb72fd88 Mon Sep 17 00:00:00 2001 From: George Burduli Date: Wed, 17 Jul 2024 13:01:11 +0400 Subject: [PATCH 023/134] Remove redundant 'else' condition --- modules/ppcp-wc-gateway/services.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 575477bb4..3bdaefe30 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -305,20 +305,20 @@ return array( $checkout_page_link = esc_url( get_edit_post_link( wc_get_page_id( 'checkout' ) ) ?? '' ); $instructions_link = 'https://woocommerce.com/document/cart-checkout-blocks-status/#using-the-cart-and-checkout-blocks'; - if ( ! CartCheckoutDetector::has_block_checkout() ) { - $notice_content = sprintf( - /* translators: %1$s: URL to the Checkout edit page. %2$s: URL to the WooCommerce Checkout instructions. */ - __( - 'Info: The Checkout page of your store currently uses a classic checkout layout or a custom checkout widget. Advanced Card Processing supports the new Checkout block which improves conversion rates. See this page for instructions on how to upgrade to the new Checkout layout.', - 'woocommerce-paypal-payments' - ), - esc_url( $checkout_page_link ), - esc_url( $instructions_link ) - ); - } else { + if ( CartCheckoutDetector::has_block_checkout() ) { return ''; } + $notice_content = sprintf( + /* translators: %1$s: URL to the Checkout edit page. %2$s: URL to the WooCommerce Checkout instructions. */ + __( + 'Info: The Checkout page of your store currently uses a classic checkout layout or a custom checkout widget. Advanced Card Processing supports the new Checkout block which improves conversion rates. See this page for instructions on how to upgrade to the new Checkout layout.', + 'woocommerce-paypal-payments' + ), + esc_url( $checkout_page_link ), + esc_url( $instructions_link ) + ); + return '

' . $notice_content . '

'; }, 'wcgateway.settings.sections-renderer' => static function ( ContainerInterface $container ): SectionsRenderer { From c664a8308b4b70500c828c387643e41d1ad2fecb Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 17 Jul 2024 14:05:18 +0200 Subject: [PATCH 024/134] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20incorrect=20?= =?UTF-8?q?
=20tags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ppcp-wc-gateway/src/Settings/Fields/card-button-fields.php | 2 +- .../src/Settings/Fields/pay-later-tab-fields.php | 2 +- .../src/Settings/Fields/paypal-smart-button-fields.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/card-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/card-button-fields.php index 1b8d13d9c..1bb6c24b8 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/card-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/card-button-fields.php @@ -32,7 +32,7 @@ return function ( ContainerInterface $container, array $fields ): array { ), '', '', - '' + '
' ), 'type' => 'ppcp-heading', 'screens' => array( diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/pay-later-tab-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/pay-later-tab-fields.php index 06b4f51ce..0090b6632 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/pay-later-tab-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/pay-later-tab-fields.php @@ -847,7 +847,7 @@ return function ( ContainerInterface $container, array $fields ): array { __( 'When enabled, a %1$sPay Later button%2$s is displayed for eligible customers.%3$sPayPal buttons must be enabled to display the Pay Later button.', 'woocommerce-paypal-payments' ), '', '', - '' + '
' ), ), 'pay_later_button_enabled' => array( diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php index 3a2513e98..011cfd192 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php @@ -233,7 +233,7 @@ return function ( ContainerInterface $container, array $fields ): array { ), '', '', - '' + '
' ), 'type' => 'ppcp-heading', 'screens' => array( From 7ed92c8fc26352aebf615132618d55bce7b11e23 Mon Sep 17 00:00:00 2001 From: George Burduli Date: Thu, 18 Jul 2024 15:10:15 +0400 Subject: [PATCH 025/134] Fix Fastlane condition --- modules/ppcp-wc-gateway/services.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 3bdaefe30..7bcfc4abb 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -298,17 +298,22 @@ return array( $settings = $container->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); - if ( $settings->has( 'axo_enabled' ) && $settings->get( 'axo_enabled' ) ) { + if ( + $container->has( 'axo.available' ) && + $container->get( 'axo.available' ) && + $settings->has( 'axo_enabled' ) && + $settings->get( 'axo_enabled' ) + ) { + return ''; + } + + if ( CartCheckoutDetector::has_block_checkout() ) { return ''; } $checkout_page_link = esc_url( get_edit_post_link( wc_get_page_id( 'checkout' ) ) ?? '' ); $instructions_link = 'https://woocommerce.com/document/cart-checkout-blocks-status/#using-the-cart-and-checkout-blocks'; - if ( CartCheckoutDetector::has_block_checkout() ) { - return ''; - } - $notice_content = sprintf( /* translators: %1$s: URL to the Checkout edit page. %2$s: URL to the WooCommerce Checkout instructions. */ __( From a829c5b50d5017bd3ae1d79eccf550fccc5255e8 Mon Sep 17 00:00:00 2001 From: George Burduli Date: Thu, 18 Jul 2024 15:17:19 +0400 Subject: [PATCH 026/134] Simplify Fastlane condition --- modules/ppcp-wc-gateway/services.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 7bcfc4abb..d91aa80d6 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -298,12 +298,10 @@ return array( $settings = $container->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); - if ( - $container->has( 'axo.available' ) && - $container->get( 'axo.available' ) && - $settings->has( 'axo_enabled' ) && - $settings->get( 'axo_enabled' ) - ) { + $axo_available = $container->has( 'axo.available' ) && $container->get( 'axo.available' ); + $axo_enabled = $settings->has( 'axo_enabled' ) && $settings->get( 'axo_enabled' ); + + if ( $axo_available && $axo_enabled ) { return ''; } From 9fbc28506fcaceec2c4ecdf774e5fe5dd0483043 Mon Sep 17 00:00:00 2001 From: George Burduli Date: Tue, 13 Aug 2024 11:41:32 +0400 Subject: [PATCH 027/134] Update Google Pay icon with SVG --- modules/ppcp-googlepay/extensions.php | 4 ++-- modules/ppcp-googlepay/resources/css/styles.scss | 6 ++++++ modules/ppcp-googlepay/src/GooglePayGateway.php | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-googlepay/extensions.php b/modules/ppcp-googlepay/extensions.php index e0a01901f..516c4937e 100644 --- a/modules/ppcp-googlepay/extensions.php +++ b/modules/ppcp-googlepay/extensions.php @@ -72,7 +72,7 @@ return array( 'googlepay_button_enabled' => array( 'title' => __( 'Google Pay Button', 'woocommerce-paypal-payments' ), 'title_html' => sprintf( - '%s', + '%s', $module_url, __( 'Google Pay', 'woocommerce-paypal-payments' ) ), @@ -117,7 +117,7 @@ return array( 'googlepay_button_enabled' => array( 'title' => __( 'Google Pay Button', 'woocommerce-paypal-payments' ), 'title_html' => sprintf( - '%s', + '%s', $module_url, __( 'Google Pay', 'woocommerce-paypal-payments' ) ), diff --git a/modules/ppcp-googlepay/resources/css/styles.scss b/modules/ppcp-googlepay/resources/css/styles.scss index 6cf2119a0..c1eae1563 100644 --- a/modules/ppcp-googlepay/resources/css/styles.scss +++ b/modules/ppcp-googlepay/resources/css/styles.scss @@ -17,3 +17,9 @@ #ppc-button-ppcp-googlepay { display: none; } + +label[for='payment_method_ppcp-googlepay'] { + img { + max-height: 25px; + } +} diff --git a/modules/ppcp-googlepay/src/GooglePayGateway.php b/modules/ppcp-googlepay/src/GooglePayGateway.php index 26a84f326..eafe983de 100644 --- a/modules/ppcp-googlepay/src/GooglePayGateway.php +++ b/modules/ppcp-googlepay/src/GooglePayGateway.php @@ -99,7 +99,7 @@ class GooglePayGateway extends WC_Payment_Gateway { $this->description = $this->get_option( 'description', '' ); $this->module_url = $module_url; - $this->icon = esc_url( $this->module_url ) . 'assets/images/googlepay.png'; + $this->icon = esc_url( $this->module_url ) . 'assets/images/googlepay.svg'; $this->init_form_fields(); $this->init_settings(); From 95487b69e1c360ce3db438c5d9cbd57431094039 Mon Sep 17 00:00:00 2001 From: George Burduli Date: Tue, 13 Aug 2024 11:45:53 +0400 Subject: [PATCH 028/134] Update Apple Pay icon with SVG --- modules/ppcp-applepay/extensions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-applepay/extensions.php b/modules/ppcp-applepay/extensions.php index daf5cf2ea..b126290f2 100644 --- a/modules/ppcp-applepay/extensions.php +++ b/modules/ppcp-applepay/extensions.php @@ -101,7 +101,7 @@ return array( 'applepay_button_enabled' => array( 'title' => __( 'Apple Pay Button', 'woocommerce-paypal-payments' ), 'title_html' => sprintf( - '%s', + '%s', $module_url, __( 'Apple Pay', 'woocommerce-paypal-payments' ) ), @@ -155,7 +155,7 @@ return array( 'applepay_button_enabled' => array( 'title' => __( 'Apple Pay Button', 'woocommerce-paypal-payments' ), 'title_html' => sprintf( - '%s', + '%s', $module_url, __( 'Apple Pay', 'woocommerce-paypal-payments' ) ), From 42c2e4c9275944a4138a1b3356ba5e25de7dfcec Mon Sep 17 00:00:00 2001 From: George Burduli Date: Tue, 13 Aug 2024 11:47:22 +0400 Subject: [PATCH 029/134] Remove redundant PNGs --- .../ppcp-applepay/assets/images/applepay.png | Bin 13805 -> 0 bytes .../ppcp-googlepay/assets/images/googlepay.png | Bin 19520 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 modules/ppcp-applepay/assets/images/applepay.png delete mode 100644 modules/ppcp-googlepay/assets/images/googlepay.png diff --git a/modules/ppcp-applepay/assets/images/applepay.png b/modules/ppcp-applepay/assets/images/applepay.png deleted file mode 100644 index d46807d77f7c31c33d8ea4b3cb7f5f2ee927d2fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13805 zcmeHrby$?$y7$l}9fH&_gdjCAba!`2!!QgmbeDj1i2?$GG!g;=5(0uC-Q5k+Qc9PA z-{`ydyW^bmowKj+JO6F2>tWWjo_qb)x_@`9b*~sL4Mlw12e<$L0AE>2P6zp0fPCz* zF_HhD=9s(y07y^#^$b0ApgurXcNZIkBOK`I=L!eHeGxVQfbaZJ`eSeEPw5dWJh61B z?vw;;#y*%nm$yy{FUbR6><8KPfer1weSeQPB02PN7xW*t zQvz>Y-)u*O+HCk$Wk0kZA;tK4*($C%N#W1Cz|o>5*)2%^8zry;ywz@apoX zVf3;}6IIhn8^!<(djtplR-ROZ8x(&%yLMUj<(~bFpXrKQ{L>EE;c*XOf0_BuV|u?ZC%-`HgMMqJ~=jTvw6^;Nk^riu;_=$zXWKx3A)iXN25}Utu`(oo;?!k zQu=nEBs}A5Yis98zL}}f2q_VWD=RGy&pNoQA;HwU&etN7F(C!rt4IUwN*dEtC5T6v zUbc6m$lokoHujTj;Bk|aFFlx%l+9YC>}8%twUyeWW=zV1UABTWo&J)7bmLv&jWpfi z2I~+j?mRhNoxZ|kW8)qENkiQsplx~i`IZTQPj{gF!@TicmV@{3qHrT5_hMC%(v1mn z%$ol~;JP5dCKIt`WRvA|zWLbjOHcp1vc~z{1t%3mPnP#Gd}hg8GI<_nt20SMVsmmr zU#Lutb$0`08`{?Eud!F=bSAQ*Z4G_?GlB9cX-%LS7L5+ z6FcqVRUwK!0X`2igN+f`GtDV#Rm03J-k=*XMAzySK0P4JWMh;4$th`sHK*B3EwVp- z6>J~;CcKxV8)9UBxz?;}=zV*PeR3lES)%>sCgFWN_-SKuykeT9S$_}X;7Y{h4Dr@? znVUWAlc$OPw9udcrKKb7a!)_KS`GV?d!&!Bx}N}PtE^r}Oyg!2rr_$PR4K^wrSPjR zwV{a*m6Hu92i`{s$?;5sC=GdamJJPMaV+^8yM6#X6pm4iZx{BMli)7M&k6hvz`lbKJ7`N?QM|mPPSQQHYDKSqXxx#_+=9HHm+B^b<0!SAUh#LvfiKFf=IF z`W8bVOWgahm}ya08{5u&rzCf?R_)FAoFPg4OP>*mw8(Be2gRH?H^1PZCGZrpD6tuyegjk@!rs`(toN zf+7VjsvXz0(%Ns$if8Hj=blTOyf<=cM#=T<2%MU}kHYK^-h!u^?ZlI)o9v*65fW4| zjFv?140s`53?@4(gg}H=UuuN8pnZOv(1W|tr(8Q(vBOwU7(YCiv=P6Sq=ZVvs5l~w zhK?^_x5{Rh-awKsXzNWf`b<>`M^ki>koCyqYC^fviH`PUXvr-!S@#na0JOx?n~tf!NU65otJC(WGQtg6LmAi`W-58c9Pugdll zz`lKZMv#W?0}M!I`M{vr zkIKDIe&V#I_vk}p&zv3fASMCiXd#RyJxju)vS}qHo}h}2Pub`tU-_U+Rz_s3*BOoqOB%+hSi9(lH8yvFqzt@@G`Ti{WTN}7vvXhrM4 zgl^pKFB98!ko^*kF<&B|0&}e&1&i@J7~;7BISiF9*PV#q5aFB*DA2+$kNPh9(fH9@ zD7+0(o3DqDU);HwVs`d|6mU^I8dE1)i}E(xxYiH9rBS*0qVM%~=i6(B)VT7(Trpl~ zinI|Zr&#?;0r!=W1}>YO4=x4qjvusKx}1y58pWc{0E^pzD`o4OpO-Ln>s#%^nEY=A z{gHs%1BMDW=tALc>D=UMv_C_xDW)wBrL4<=?=(5F$46E9Yji@0%DR=BW?5S)fkH@u zsg&4#4D?%cF}-os z=7n)qS%#^D>6BtWM;#jkYu<090?HO f9GcMSv>+i6?F+b@lXEo6-N+8z#dJTt^- zy#>zS_K}}U0JmsPsdre5_g*q^c%fqBKFd?+EP`uud2cnJO9y5y`D^6uOo}Iomil@O zy8;AT_JvTLc^}h!t!7qD2x^$VXL~x!#RHtccLnQlJH7W1-X~ zKMzsJ-;1|M5IUEJ+U=oKp9>xVlN&@RHWz<^2-%IU0 z|2oArs9$Agc%poEXLE?v_Cw=a`iarOXV;0a*Pjy_Uep277ZunJ2Iq0F?EsV{7S6mW zA!|hOhMw9MQgk+iaTT>{bBxqDD%{DcKt_Ib5Up7^^|=jzf6+PL&R*j&;_}6$Qi(RH zr)k5xzP+vyGUL=YIjr{DbRSXMVP+fEW88LDGfH&$Gjj3Im-lc_sq9M2c9;plmUfBR z#LbgB_c+44cr+V(z<9VTDoLGP;fg&5VbV_hpy%kUS1ABH zNNGW%@gx#3dOO3FD?_Xt<>J!Na~`=STA8KtJQ)ovRyT=S{vNd6Jb>OiJv~j+t5%p& z#7S(VQ0 z^u;d7rRf*xv$%KWs2=ia4Aejx4l-grIO8DeEtAuSBN0B)xffsa%dx|3(Zg|MY@Oa1@v^A=qKd$JQ8rFeyp)0Ccc-@*NPANl_K;f++DhI$8#CWDKjQNq@dDa_ihH~0^w9|@w* z^RU-;;usN7Ui8l83(EdBw7olp7}X)eA>w33sN>8r8CTmp&Jy&SUwa>fR|B zb~MZC-m9`q_d2zXT4>fVBAu=+5VzSN4L>A?0&~pikrbwYPTXj?^qtBy`Deui12F`- zsdlOM1wR2k1_{H_+v^P35&P%;a&XK5!&G6OTt6)$5)7O=@Ku6;$gvi0E9t%o`7Pe* zvPXgt?{4;JA4uTt(5<%pwoYUIm6bu9JOgcuyj?Fzr|j7lRkbPqtm}sn9X@Nb_JWL= zj zyY_V={gSQ&8O@(?I#%bP)=?3)Y_wqAk$GHPN4-Ub$50iq9&!ka_qlJUZ1rZ8V#927hFAIdxRw>&)3&}K5@nj(Yf5Y&DB&HnqefkP0p$z zYL+pfX7h>}QM_^<){CtCPxat@_EeMw5pPDK@j&q|EDCEfVA1@@qJ4g?R$gGcnG4%! zW8==NmlaVMtNy+6!4H<4Lnb#lTCKiJrJUB1AB0GMq~d&DCpVzmNl>xDVMv=+lbeqj zNcZCH0!@DK5F5L2AD}z_E}f$pP8L2OM3FP~k#}2)flj^DUEG@oLY0->$FOQWicUnp zXDCA47}a2Cqs@}yCTeq%2VgWAD0(oU)pYxrBFPDOgB--DLfuq8BtKgUSoOOBzDt;Rrg)I5(g9H zldMnR(gK^OU$NzR>I>US66aq*9$x6+K`G-B^cz^kpQ8rS?ju==TBRReyIhZv^_;QUxg3`!e^NlajQe>a)NajLcE{mS!V#^Yn~hO3U7~_s_QMa?-i#_qmsk@O;k6JYj|Cv?uN<+ zquQQ|v7fko%^B_w;JJ*qfq#B*{ji32<=)*<*`SZ?QxW!)j5f*il&huDoWcHpnedUe z;>M(%H70lzUq8bxW@!QUvEct8c z6Jd*|87Rh{s#IG*43lVmu|vDKH1Dpk9l%!09C$>?JWjtd5FF=r7}D_dMUTRzvZL>k zXgjWxo3mFVTrWZ$+S=l~O2eMjR1j2z0xwb4_P-Q-1u@@ovwes@`|^?g`#14#%P2C;#j16(h0Sy8tqo0u6a{JtVyh> zul_cGVZEx~?^%sOMfH~W6`rhcApG?nUsPf%=oL^pJoJ$YYllLdK^7Sv+kCvwp`vMv z99M)XGuWLY7ZtyH59?>x%98O_9}YJg8CIh?%{C1E>oUdz{+=rd@62wTFHbQmPG7a? zVA)70zpwr9l^9%!Z)#f42Pgcvh!UB7Z!X!aPgA#dJLCd#UBm(Q#Y3NIT2B8V6bKlf z)IY`)5<*wNOKx6XT@pWNzI{?Ow?asq?jBqq%bb_gYZcet*l9a#|^A$k?IKe%kKwl?EXAcoyanNsE5oG&UH#Z3QTg1~r9Av1j1(bDhhXeVz z__)BF^1cXfUXTPXP|V%hMnp$W;V%%#H*t`ir>Cn3H@AbN? z&CAP)l;HI6bM}P#ayol3{(|@eLk{i%b4R#(B3zt-zc8UzE?%DEAQ199@UQE0a#dIV z6W-b5FDxMW;P!>Oa`SM3xt*N2|9*srr@S{3JQ@UhXisyf@t0 zlkx8%tYLqSclC02{H=~Pj2rF&t%-N6!17&+u2$eq$r0)YV1gTwq?m z^iq}+2O)d7tP$2C);16*kDwJVC!8Mw=HwINvEdXJvKHcmSRsF4Hr9erDDU4vC_8(2 zLY-mozd|685WFx551%#Mh7%6shjQ{kd8|31LJ&A79}k>Y0469X0Eb%r9fYPk0_nz3 z$N#6*Si?kYT-=?YNc$t4ptf*sS7+PbbNsT9h_sfnIEa@E{I?!0N2uqo0pcJvgtM3L z-#+LeoZz~i&|fU_2=ed>@__{ec?9@`Az*>O2^qlMJ&>;Z3zG-T1^EN_PZNsBx;VPH ztGigk#X*qYgML{`1gR&IYv?bZM`Hi(N0Kfg>kfx{!sU<;5)O=v888nguaF*(fC#^k z2tc~L0hI&H(goAK`c{zE&dOQ#$iU<$i zKfxgviLmke@1%c)El}(apHV`1c)Gaz{qFiBmUZE7f4u$i>WKIq#6aNha1?>U{!ke9 zTTScVD@CIH@e%Q#c+daX0slntaIx|9fx5$`ZIS$ngQS0DOQ6_)f&ZT5U*h-Qbp4yIe~E#AN%-I1^>4cVB?kT_;eUJA|2MjD|5l{Josp*?A7lx7 zYvG%QEMGCLR2AiZ7qWmW*-uZAEgV-RBM$%okM!4r0!YuKM0R3%Dyz$5eMQH`A%4Zur1gB~53&%3WRE{bJ)L?kHSoEV^WDeLHO4nvBz9WF@@J^{A3ebO z{@i4cS z0s}1#&8bPj_yM0fH{&W}G0($6K)j$P2SsWr*?3!m40*3=C*z^eR(-c>PwY#Ut0PQv?$eQ*L#&j&{GPE~JL=_~fKeMP?p1B7`?x!^xtq zwkvzX`r}8TBs-GE=jpo-IDYO!Oq<>1tJ0RaxVS9}nKq>Iz)?jzJWj&veY$VK?ge-; zz`O;7on5D%q@pq zG;foU;{wD0c7+J;E?QJHH04Qb`>urr>Y}2eSRMabJY_WR_xt?q#oCO@o!IvBic#@L z>pko&bIl|#-(1%g8XFlU+7S!2>9q0Vex2cB0_@e1Z&6S%>7Z*=YIzUsrX=u{&%Amx zI`c3Q3^?ih35DF~#4mI8i5PI? zlu$#km4PxO*vJ;~ODSY4IsyGxE1Zc4*^<#D*I`ML1|=p~#ABBT+odb)R>9K9DI(i6 zG(HCGkX)VlGl+<qr^+rOnOhwgz8^A*n4q)vl;mat~-Q zebK?jX2xxN8IYEq-rnDjtD&I*77$<&IP+%M+uf~nZ9|QWgY`7FEiN{h43Evv$LhZ` zXqn)-44_+FTm&zz(4TCNL`eaGHfP-;8`B?!qPyU6r_u0ve%)L(7DexKPRGScV$$yT zp1a#0F-Fbmz3J%>Xhb}t6D1Jia+g1TI52#sv57wZ57)OiN31bq`AH#q-!6 zf|)%`RMPsfPlbz%>w0wzPfq>W-e|U4rT4M1(Q0SBu=7JUS3y+_j;WavIgqrD4oQ%bTIaL->Tzca>+8gHbOaCx#44i>*T}*mele4V zjGR2LvGD;K7D4#l*D+T&KYk2LYilMDBjZ9UH8r){(VG0m=4M`FDelnFP-SgRM-&}h z+F={kC^Bl40B5JCmF}A=;o;#xFc3gao}#ixO`XHY#)h*u^ZsESA|rvBnOW(2o!;&8 z5IVisIW~sEke7!|KoFUq&uHG{8^TUSrKGIfR;ZdfIzHY%`;do$cx%h%^5$gZDCcBb zR#6f1`g3_XCkYAZk=tcYoYz~8Y$h4|jD+p+aUv?Jn8-+llm)W;k_tCQ^FL!#aEi57v0Eh2?T&%EegkcdT zq@+Y3>C-bXcvDwL;eUM%=I05?Y8LNqY-m$u@;^`w2@OTf6o2w6@!RTZ2o5QW=Z<-{ zm|tkVVm$A7U_b!aW-u+AZ6iz6=TKiyFV#BWJ~9B{@WSqJPj`1K^`Et+Dw`5JJ3C5h zO0DH4k}c=6Pb#q*8w0_C*PdnOHJD+T_*RZEd;8dfqoag@6tr&#>(7zP^4>8gcw6x0 z$9Es_xb0wCUfpHMS=&cbt{&TgRM|&Pt8$Uhj!4kirQ1C!UOAZji^N1?2Y=Z>amMn7 z5}W}L=Sj;c65;@A%Kel!)%`ZmuO&W8(*m zPLsunlp>yXBV@dsocQwcT{JP4(Xvl(*~`ky`HitkZHeD=ZtJ|PYM`pw9&C#teYmnK zHZ(*cCm$HG^vMS@9T6G9Gj42b?8YG8Jkj&?`jib9_Zwt9Ojc&{fn+W2>n2-5TTq!v zJ;Cku*@SQ5&1x7{+0HB4qW%{#G1BKlj?+#*&T1k@3jZdABazU~`J>QywQ&~(b z$eoes@zMUAt9Q_??ae6$YMF6!dTr3<`yc&h;)zP=?Ch#G!#-Ps)ZaH3uTJ8&TTnwJ z9yXUv8dwYR^SiOg`glzTF8okKI^egZPh*RNG`=6aWb48m%e+W`lG?S1O=KK!CLL(Q$#&IGP~iuer@#KGcG#15PS7& zl=YCh;`8>=JXtNn%iu9fZDwl)1&Y7$QVO^%w-f2;+Y;7I zdr3(FY_kj|y(y4+a~QpM_;Um@1;mYpb`O1N)3{uD-_pI&m$dS+T#cn;uEy3)h#6z1 z!mQ(Do4fJWKU7wx53}bOu06= ztz+8TC-1GFpL@Id_-u2$vL8V1;-Q~DiE^2K>{aLTgHZ3aT%x*})O!ycH8qJH^({7( zqP@*W!^6WfG&XE)8%sQ!Tir9RA|@s_^Y0m1*GAskg(8!OifWfxW9n!nxEt-P#&*PN z?s&6*rt6p`YEPunm>m<87!6@SvHW?5R$N}*RliWze9{_-g@uKVj_&z`Keo%N%&;m{ zUjZ%bGd4DMa7_&)Gc(f?0mmREC8eaMu3w3l1GNErq|HRO0r3GgEj z`G>fM)z&!Mg8a^zqLGC36<)jo{QRpk7O!c&0^h2kyic-Nz1==oaPe}cr>8eGWNjJi z9~?yP(cIL!+aiAdH3gQ z_sWNdwoiyBSF;-BKwVwW?jz5xZWk5q_XW5Ul}du<9Kz9qi;G#mx%V8cgW>&Tf(oZBEq4Hgw<> z=crA0jhe6PNw>P3ynIQ(PYWHL(C9+d#N-b@vW5?KcVpXRG1&{vlr)hO^`wlW2V$g2 z1U4$HbAm-7L;Oy*coaIlu#lU(;SXGUY6b>|*?JfHy~BvoQhTQF$_5SZE1c<>n3>szzK(64 zL`8zQxW3iqOY!TQdKg&OuO6(2J*O7*{^922h-szi?w-2*%I;-zUmvAFnFHfR-1FxN z$;qd~5G+C(p~Kqs8ct45AV~}#1@-VYtx=^b1CtJ0o#XPLNN3*DpFwH+dw7aiSd>)M zvK$oa=LZYD{e#w7T~@P|d6yH};t%MZW~aJ`Ry1=I1_f8Xw1%LS>2|W#`ZkMIoh`UP zZEa^bw+Zp^I?nb44QHyJZ|_XWpi0Tfp(6vC=>GkvPd?vTkw(lnGb5&;z~oMh_6ksw zm&dp}pU~{>?Uh0x*!K7Lzie(sXx`@zdK*)OEO(Geh-wFU>@aY+hpc}DoR;HyQ`i&J z(_{B$DprvOLq=vqObm{rlhf+{TIk`SYxly-zNCkcNYUB3dGG5*`k~C2T8EixgDgHH zQ#1euKql{y#?D{G@lgSMGwt z{Wnz2zcW14$h1@^BqW@#m{+cA?t<3Y6g+?F`WAV8%*@p z(vJNH-_`RYTRF?i%UL-%I)~|lr0jRyy8R_`qL2r7L{}{d!xJ8f<>lhyVksDG-N8bE z!{oE61B))R%(;~{FV*fIwfU!^k4Nj3HbW1}8*Fr<0^*7Np1FQ$MR`6npy95B8l0N+ zg3I)S52<*XMUb(sY1PvMC8phn{#L z66{@>G5%datOfVpbHYu1ef>lwVj<}<{s+YY%uMoZI7W{jYrc`!5{;)5_fL_%d&Tyd zjHK7;y==d=kk2=o7z*j~Rrf!*XlNr5n*`v1EaX2f`ORH6Hf<$X9ZiYR9js?Ba>J53XV7!h!vfkomI=- zJbuTgUjOuwl%gUQvS=jod(zR}jj5oZfUFuY;@=o zIiaU_V!NUN=C4ujOia!1#NQcySqbh3vLPS?(Xgy+=CNb!f*0@d!KXmy64<= z&sz8Q-)1o{GyQf|cRgKQZ*@IGq>_Rp5usT{&t!A_>$UmslG2Nkce^qSUWmF!w`-_Cw>$iHtD{VGU&oQpqjKOVZf zEISu*>*vq7Ac!q*Yv?0Cp0@c@QH9r_I``5)G|*qc-|5A3#sB$T=C;W(7h_MF z)bn@IEw0d9_u1UG{9!e+_nYtKM}OzC+-TJJt-+HQMGG+v(aCQ9li~^={|DKoHH+Je zWt)RXZpt^b{hPPD=G=C}ZUU*TOJe^HXS-bY>!ayOkte)arrG6gZ})clsR`qKk& z<*lN}O~=iBtTtC?#LCAp!9BFQH#a|gwN9GQ^R(R8su@uVbk6;negJ3ILtCG51UC`( zM|)#k=FSf~Wwpa8$=wxO4kq&a=L=FdURKkze#EjK&F6lt?#)Bl?%NAEEt=aO-=CM? z)|q~ks{@2T#9*;&}6)Tbog7JiiE8;#bbW0o&ftkab48-GvMhKedI z%Ft`n{#;pk&!hdhRqJDA(~=iH|2>qYHdE*Qk~eX%H*yu<GEi>Ebu%+=84Q#p+ zfmvSyLE8ZiF}Gj|DeE9X_AgV2dfy=H4EPUqhE_Q*3CG&xS}+gio*U!G1xA;X)@_H= z*xIXoKM6ugR9eL;XMQ|VN2nZzY;9_>bt8!ZqyVW;Y>oozIV&=T1<*Asetb+p`>;&# z`-__FW$$+pcoAN8;XYQ|%k|HCIhqR`;h{ejx6#(M4Xo!+5o(M`TEhgYV$SE`-da*e z`lQOe`}*a}?f`Sd{>6fsEpdJ#girC+tq*j0?3{UW+FSKSEf!UiSiSn~0X^=ND4i>@ zm0)76_bQOU-P3dR(1G#3F^1%CQSg1zvbssyq)6By9n_{ssrg%9-Irf{-RF+(s#d0v zPGUDs-+XM+HUX~0hv|~x5`fi{_Oeq#ZGI9nII} zl50=imWWOCH5tmRRJqf3D4R6fiHfEfwx>~F{yX;}IBnSEno(|R(%pqjRO2J}V-Az* zTLEY5%~weFy|nK*C|huHkn(-a%*#qgfHvJ`@%Djz%V*`KGuuK@8RNENG;2dhC5?-T zVq2hzoL!7+(TA2*95A$PC+&?Sb@LfJ4KgU9Rn08KYBvvf7R+nF^QDbs?MeH+ht6Iy z&y?+ns`4lEO*15%-aANEeD3YB2$wDerp3AwH3_I##=P7m+hYn3SW}iQrYmS;2cEgA zob`EE7#Ft&jWUu>@gcSE$Rm<=lynJ+SE*irVIGF{rn}B{R1&lymlBAXVTM46l@&(X zb6y7jXG;XFO&$**+??GH9H7)&!3#hYD(sPR6+dwVW9Fw^WyHrT$=a=Ca|Xi!JIu3j zYG;=q7K+2?)_VJS8-!0sr9${uilv`OKS*HxvJZ=Zz7mBdL;B9Ttjd=-7Jq{T9AM^k z_K95Plfm#$Mb7*1Sj!#3B!!87LLMb#_%jslwO!-EojUo8awWX*o3N&RXSR5t3(bv%1Jitq-z zAb}=w4e!zFD%|~=i%BEPxR!f^+|v>&c+7&`3j5h2vR`HD;Csn$l2`S-6qxplAI~-p zM(GRkmn8^x1{Vx$djKn6Gv?mJW#XRzX)vxvcqArY+Cgzr374S)7qMAh2@gQh z=I2b7i3@BKcL^v7N7avZo<~dAEJ?i)^8|;>+lawH;?A^9Uq`c3IosH4m}4ZXhLDG{ z3sy@?$VM6^zR{+mEBx}!5fcy3!-u}_v6Gyy5ixfDmnCwQLMpeJSWl%_AaV*zVZQy0 zMY+KkPGERwupMLP#^#UxSg_~*5)Kb<^*-qfzq(hF^Dix2&M#aRC#nNW$}-dks5(}o z_CI~tl8b|o`rHN|sp>XL>e_xmRnpO8pl}BZHsCHwDGRv^RZ==d&k4e5f~TPU0=lc2y=geW9i+QP_+kNp#ERN~W#f~Ob> z5wWcFK6Mp1L$a?n!;n5r$tB9`+v3}eaFubQyb1Zmo{+u$U7n&h?wH=LGpa}kp7EI% zm$d_v!;fB3Ps_5%pD7TMZIlpLCz1?{N+Z1PcM|+k_JJ|hItV=vri=pRQk`!2$11m z{$TZ?-!4uZ_&NRe3zD`?swLcNvBa}E_G2$2kTVSE&M;g!`^3`Yw3y%Fa;aK6Z#X2hsQ#VVpCtJM?dLWPqxId9(hOn#z|4mU*D2sL`KC~i1kjIp<65fTYp*VCB53xO}v=!BZ zLM|Ec_#v_sokPTE?l{rB2FPLEvEE~+J${{4ev!E^qD&L@!K4MOt7zjWzl9}0#ELOl z)oW4wM#;uV*~>E?j8~OORsGw7<&OT8}roX8m&mCHw(H~}B})8N0xY*e*=P_K zdiVLd6!*Ax*1s&X+CgnY{Kioc&Ow*fz1omM4JcI}JFe{bG=$^=WoCt&s0Y84Ugnfd z+B*&~71Jl7aV6R|NWzY&f|zqFOP2<`(td-yu_)`s83{YgBj8y#l4?%`e|tbK`=qYZ zyIR`}_Q?VqB5#w!OVH>Vfxd+C=Ga9P26c}4#Q_6Lp>?W5h}~+^JhTkbF1FZY^ve>d zAW0W#ZK$F6H*9S(7nE2j_n9A+iNYQDKvsmB@Nn>Pa^8R`SP7uO$-ppqX4FAQ6I0NA zqO2elzb9rz0AJ1uo|Yo(9z~5^?pE?T)?AGxK6|t%2SnNjViGm~&dA z)H3y?7QF(C9TB$tU4>Br+u%^daI#*7dDo#_(Locn+mJnLM}ZKe0v5ZSKTol7$Kh1~ z!?;T=eU5f$G(nrG4jqC7?tOg=cR)-ukI+ojvELk2Ej6Q2&1U=YH zCZE}Ylz6`(^9M~dnq)4p-M~ju{6|=ZO6Y2K+9*`q=b*Ue7A0lKicBB;q8ZxdV~hcO zS4wTLPn6YbV5Uz37yv#7M2g>&Uz>X1LR-ji;>rwTt><`Si-a}`H9lm=?E(V&o?Lhd zBMD%z=Y|0L(ybp@GVMD8?6@_@7x_TBP zjuGNRrBzf}F$F!Hqx>#IDkXpct* zx_Vx#rMD`Bq?-|i9O6b8?ra?n9=IEqwe@-U1$i2{^nhiUI1_p-NuDd1DPwGxi+1Y` z*{&M6H$I$;lKl*68s5<1l1F@`Qt>yQIfdJPsPz3&v#I6Hy|$ZFsK}sX{4^0j;&&tp zw6jEd5rqgP)t9-?aEUd&T`Q$E33(7xj#MX3h=is+{s2rRk*u~@mNnBFGS%d7OO3kd z04*D@@CFfGg9LQ-FgoekUf7m$u`1+79cKxA4K%U*ya!iqkFFWDnG#!`;lcl9yoWs+hva#;Sr*HCDkxJS34N^bSGD3Ae zX(yAjluDz>{N~M2=7o}urrla5M`4E6ksZej$aLABZ(yR!l2W!Tp3y%)Yo5EsswRj{ zQzjrx6P4nvM1ecfa@0T=ax1sVQRS~=k{|FrmTR?OPL1lqj+Tv_Tiixb zH29t5L{xc?ZT7tlxIx_CvS}ftj94HF(FD8Zx5qt+7^E;*+sC^f4xRTSgab% z%GARsjwN}5$BkArf;Z340`g!WXAo~8@;w{rl0dY;;E~4TttbqW(jK`97Xas?Q3z+) z8?r(w+qBUeBX(ME1*kCC*{haWsS;?#ZSiOydLYCTghrlcBj4vFDqfd9DeWt#HY#Xr z59Jgz!^~0igxAcJfn6Cw-SD0;q=K6RPZCtU#|M)U7ff~Zx2?@EFhjC=>kCv$%(vr2 zY-hCQ@StUyjaBj_%@c$>!`=(;(MQT$>9jj~DE(T|u8hT?;~vHM0u3gQz~&;A8tTBQ z0)GREGKQeOXeU1Zk6B(?Q&`w7DO;zDshiPc^OxjwXERy8 zpw)}^k;3_@6EWh7n)a0|{VU9v7FJYSxB_Zqf)Xi7*S+XAVOy|0stD2qB{`D8yh3Y4~X^1zAYmu>R9_=rW{~P#hbk$b|`VtMA8c zY-eu{+^kjL27osC6bB7$!=P3TYrw%TqH@@8nubglCqiFY!(-GI;_N)L zpHgOyk+4`3ADMBU@3qm>hI#Buw0s6uce338Dt1U!GNU-W5ovLFGD{~Qyt{H~N!d*m zm8VN7zP{t2ZcR)o3~fecc*(1S!+nNU%&t%C>VQbC{4NjmDrUz#DsebMo54d=TQmZo zBfBO#k&-yCg6MTDHO*za_E>P?nBv(ibV*f-)^VW0$&4l7Z+_WJYs&Yg-K4P@Q#WOTrO!_`62+bvnLvOJ!)w4VhgFtG-GwCErTWfm9FQriC{zYn1;+jFg|vR!JaY zzt&10D^&DuRwCuC+;-5%iO=4BH)RK&HO% zN6C76Bk3a+L(`JZRn#Nd)Vv7)Tq%<-hFmPxA}hY~E0Mk|P%9hTN5tD@6QzrO6%bVD zKPy(qXnX6aHMcM;cCJh>Z4A~8De$>>It97%GbJ2MPxaU4f;*K*&Yz@ta>`$!vVO5S zpLuLoNY-{C%r*>!Y=(Beyj06;+Pm_=q)&F=ThWHX74 z>kK{se9l@D`o*{2{gXELa~MfE>BHxxLWIhbz&3U_(FVm)-xIeu0fU=PCJFnxZc#&gRD74<}IXdQ!VZf$uS1ERJv3D~O;k&_ZZbRuy(F6bt3_Qe2R8&b? zRP>+J1Bh_Q@=f5E>K7syG?I zGrC^As_u~g2|<+G*DU>%Ej*!zER{q!B#2IireETVdNu|E?OL4sm85RB7-Og|CD4gJ z4+5#~6!txMYeV~K6po1&1GY_{;K&5(coQ0refUYhEo%sF+aIRtHnm$B)?7fky0PIH z6y_qRPlo-~;P(5k1fY0cyEpGvkHJ7i?}p?FNR63rYeZ zxpQ-8ga5qq&AVuI>jP?rQ@}SaYb+2&bYumhf;8pjcueeV8I4Tsjm;Q6Y#l&U5r`}j z^l&gTu{LudF*dWXvg0SaZ0{x`u`=Z+(_ohe$~%afSz1YXIhm<=DX5xwS(|X1k_igH z^Lg-q6xf=%7?F6`+Sobsc<__`rI!cv{!cR#8OdK=T&(%YH06~@MD3l-NZ1(J7=aAp z9#(EFWCHLcd`_n3Jj!Ac|4;$?#7}1F;^M%=#N_Vo&gjm{Xzygf#LUgj%>-m&Vqswb z^9b#tACQeokE>`w-B!6@o8QZ(M@RN~&?vwm;ezp$s^8caU z&iNlGfbd}QFmhmGW&|?X+A{rD31=5^H;|HlOz6Lra8?B|YD~&z&i1ZOCT8MpW_B** z|EfaS>_2V#|DXcY{a+NAn*7HE99*4j{=&o5gvrdt%oa43Gich(|1xJuX?dmpkobe4 zg_W(tUs9me`j?(AR_6c1%>LZ@3y=S52}t}u^!~SY{M8xMOJ1Hw%-+QH&-A3l_{l&m zjHXtmJS;5i94yS-;y^ZbHfCmV5iU_~&@WJ&Q;eGh$im9;U&N*DoL!9UOw9f%ZUqu& z=Q1(jFz4c8VCFV8VPG?20WugHv2igN0Xa;#*-gw@Sxt@piwZ?2E08N2+5C4iVKy~0 z=P(CyFqm^PvoWxlvw>6@vzsxn7z4RXfh?xRENpClsWLU;k+65NH3Ip7m93G58IyyZ z#a}o6fXpMTB+XC8!U+7&7Em$G#T+ESPbOz&=j!pFH&m@`%~V{B{vgQA$;`sZ2IS!2 z0s@)YS^hTrFMaA}PR=0r{iBl^$jJJ)-akvh12P5#rqLhg1}XSUEeKT}Q71Da7kejF zdwUyxvOg+F{z(3{CrJ4IUI-~GXHXB%KilLV8%4#;@$XN6?;9JdziyF`{N?LBMkap` z;%ww*X8PAaAi2M9nOGXxS(t%>!atnopY2xv&0?9eu>iS@xtSS^O<0&g2y=lDHU(YG zjo6q?O_*7L>>S+xs@>V%+{N9<$xPS+WGToRkkkHU4GGO(P}2TuZ+AT zmiPbS&p&+R|KbQB)&Cyke}(VA;rcgR|0@LkSDpXuUH^vbe}%yRs`J0S>;E^n;Q#aV zW@ZP<&fGy~vlRo}LD0Dl##mNT?5`6Z*pq0xKj)nn~k&)oxK@!8M9{H4eqZH^-}M;;(AbxcAQ7#$Ub zaYrW}rC&orcau~FhzJPM73%F%OP~V4)8NR&qX4og7KHFhGi~a8-Oc^{g;KL`h1@s; zJ##H`skwO%&axh|p1Ll5j`*Q6fSc*pT|zWyjS~|Ssu)t9ojA%6)RY7AhQF$ZeY2XynNbGSf;d)|rPDM){Jdt1kyvVj8LGGoq2t zb$qeo=eN46Xq9v2e!V%Nr7CS@Rb5c9n*bAR^i`o+;|9v#gC{_jYCKWqySI-orcOs^ zN33s?2kM&?+V9E})*xpm=V7bHHjPFey^pD8kuU;sN*Hj76vAje?+!3Hso?#!dQ@MM{+6h>7hVA0LINQbcIbglRB>3QCI1GWkOc!9nmu4?;w*B6jwIHEJU@wn3$9 zX|*J0L@nHo1985%>dR7~;r`h8(F6t6pt)IQHW2#3yklIzB_#KCXyJI>)6cetrV3wYvICMwWe#LA|`D%_KyGGzVwq1LX5V zFdYk8PEHPAFL4lZ-mGPOMrv4yXt*QE4v-#8ws9C98X`I^?MT8*YNSK$W7-kBY~OSS zf7)1!r?axK@D4=b=)TSdb3SP=4!;xBuJPXX(b0I)D=C$~kr8U50)^49RNIk>s!gA? zh(Yn+zx|xa`udldw7GKaI6`t+?k1PCv{p~q&CDRnob3w8*7vrUVuY8g^hi^rJS6x; zfH*Ny+$llwf^T1BtxgtU$ocsB(2~dErL8smJu9Wr{bqN+4}4!}&~W;7qn zqT_Ihi1oAX{jvH?CHlx&)QRcyOZ|{TUQ0{&;PUz5B$PIZij0CH#9ohxo$MnozV&kD z@XmmLna|P5P67rI7LV~{8IzN)!sB&P(SWJN(b?R|-A;o`9D>B~c`Ag*w z<5~~gn4ugKeV>z~{%|z<7>P&m=rlBoscfA>Mq1CcE}w;nBcR<``RmA3Kkc_TW$`{! zw(Wv!d3%<05f>iYXbpW&*XdqJe|F>@$RH8@(aCWguy){KKv(DWedfGJW_GxWH1T{s zWSw(ef)RGz0zP8)r1`H&1Q4#?hJA|Z&*rC@%`EOSY_>WTvn+gwzm6sj3z_+JcSqdL zaDtPl6-D%vwLi(>Acp-84oBSZqk9TzTT)P2Ppdbd{$5vCx4cdr6e%Y1x)n~`Gdvvb z|IDWgL2Pe7k?{mR;IbJH&4+#$skG*nK|8Tm2ejN<^OEFV2sb`xS zHs3#2zv*2oRU8x=f~@QnKUe~H>g(!{R;yJLr3SvTc%tP3h6+c8XfTY&zC~tpG83q|vUVL&90NJ>ijmBkUFxS~Oo)$ayhrSMezk#bys z+V1FJveCeS5EUzmw1c+4Fp|vg%1|sMeC>C$W@X=>7@9`^l2tNqWxLvDE2p4v0Y9Yh zb{g!yC49P6nK{K|iZes`dFJVd(7}ok zu(=*g7Ab=|8SGoNAQb^wPXG%>u9 zB~H(HAYZZ+pBo~pV1_m4O*A6&>?hkZvo|hs9|gM$F7LYVFsQ;)6FoiFf;6kVH(Tm2 zf_7jNL$GaF)(ia&2fSaK-aqW3zK5+xe99wWb5z&Xj+)eIfX z$jJJ3c6NGMTLO>Q8b6AN2HCc8n%8S(BxUj<_YA8^JU*CD6)@^{BPF znyhq(k#W&PSU5pmtzT?tw!I>(zuVc_EgKgUu4$BDt#`B~&dup-XIH5WzKi6eIMzB& z9keaNpI5Id-EZO}lk!}e-rYFZTq@Q1xhp~_#Z*U-GR8*9t6F?A@=_L0W;+XsI z2K;`@D!LoduB3Un$N%d0G-dT6%%(DExsNihqm$5&sa6wF&_Fzf*dX-7kA0_j_K;7U z_UnO2_#8o7YsCT=D1qQ_FOFk~F#R>Stb*Tc6s$oB)E7|lvuRC&s+y3XP`~Qh?!GCw z3Wrvr86Yx$=f$fUueZI`M=R)fi!g1{*HYUkSy;gakAUDvM+t3U|BCz_59#P7x5-9y zy~*}^pl8@qeHmQMlw!a*LB33;?t z5FzH^fD#lOjI!Q|f9U@T$EYi_NAPR#XZ1{@tc3^fPUS+@&dEunzN6#g%T)q=eHc9* zBN1R55e`fusZ?hci7IgFM`^eJl4UE=T=rBjXKhoBbR;4|^Iz%!*3k82nS5Re=P z@vWH?3Oo>{ykPr&qW(&&7KSLd8gg-mIW6(c4+RA!0NVLT2zMf8COP?YyvG@F&g>nI z;jVGJ<6C|^0reIr>kVj{%PL*qP>>;?Ip2h)I+gJC1E*k844EEdj~}{&BE?$vjS>Qr z9#**0>L5t0wGXgCU!))Ln|`|K*HL*_`R?;>0E^erJy#epMo?7g^5AaX!Gr=3FG$tS zo}x;jPLV-54q0K+@xwnXwEoFlkrdy}i+|HAda-hfbbgKo$EWXyIdOF))W%sonl+Wp zOIi~uXm^CYGNwE~pFeB4Jy}MBJ~|@Jx4`5TY(eMZ-eS-OHfsc$!LARMDj$w@#nvj zI_erZxRDWNz>;IAZ=oL-sZ`&SkbnU_cRp#VLV+^hAPP_dhk}6t_^upzRZ~N^eE6ub z_#@aS;B5Y9l_W|?e~SbPRDmkpx2#rb(?8=vBvP!e662Jq@@#6U6@xFeXEveI51iKt z)85WpB10tkQx8auZ0y|s^gvlCtn^e-S664>Rf##q9Ium-l^u@FZg;p+n#7M#>lvSi zB+tQ*&A-0BdU!bE@sL2@%zPr1k(K3s(BtxF>=O~izbHSs^LXfd$e%yq&bGKNh(pCe z*{-qBNFS$=ZX&<);+H&J9v;3XWh$a+l}Yc>Kmz>-1Ze~_7#IapH%wseJGs1D@NC3@ ze`1S0e?mzVUzB?JpvJpiH0}K6Kvy^Ng0veL&0_LSroDepIXV^D&J1ZRIekLJwa2?3 zC6`O)Hu5PliICy?l}K(Q=B< zX0weDasEms&D!;A{Wkj9qbqgzt*_TZm{?y-nC)s8IgYHSNbi6?}jlJpCiYB@%I*PC*>14RMm83~Nw-T=ik#z9(MGd=Hyt6!qIoBTVMN3dWcOf)_D1zh{_uI77{VL~c|q9|Y>a^*8T63Dlh(oSA0Mqpz$-Oxr&jpKWu?7Jt^b zzEo$igvN2UxqDC0+R|Xab0<(HjZ&bjSZpUiop`KTuPM1pNz=G-?=;3(61~;g!uoAA zw%-qn%-1X=J_vaBwS30h+IQj}`hpkQvZDFg;fX+{m<1MEU?)hgS~`&Ro*6p&o(@w^ z2>YAoku!&YZ3K&j;P=Elm&Y;SNd9U$FxYadN-z6?%lp2f^EWxz_TVS-9rL4LE;J1B zz=nDZ%M1y0y`{_NmiF(cljLDWhHUAd-xkE&f=I5O2jFn{Kbux6=!p9{pE@7>ZI?gbnN*s(6)jE?DMm6HYiiuAzzPp>+(E)8P?Nst z=be|Zcy)y$;zQt&UBbf#YKM7J;Npf0_v*g!a)+5zkdUS(O%CyI#OH@oSf=W*?^bEa z$=hR#*yg}^{5NC<68L_~y8CPyVI7T#xPrE__#q{w!1H=74L zrAH6v0$!cw%bq;pU@rKsdoHJanqe(U0EFn?UUpLnpr!t@+?Q~`xK@n>HTu@8b8}B2 z&d|{DR+*)iSBU0w%tFmiu>iuOxnzj+hU*K$<#T34A0MI0VW|P*kpm|vXlODLlDyvb zvi*aDon^glqnGM-!wRt#c-<~9q)4ec)Ed!bcu=0HHi?>wujc6N+%H=wxjW8&YGVfa zsz2$SG98cmh3diU&5e`IMs1SHQl+&;gVmlcGZW~!kYRq7Q!B-kXGMh_ASr&igpY_^ z2}ODXLwW(VS-@rVKh%tM^{+&Z8T*Z1&IMJCEWzj~7Z! zQa-)hrnAnd%0%K^pVcdD!OGbK9VWOk%$=k&inw2v%NIWnF9neZKO&ZP1y%5NE#3D? zwqbE)Id%v$+C>OLn?*nSMxAbleuco$pA;>+ybOVw$YAZ3sM8pk38fR=zC1!G6>~B$ z5AE(23=Q-h?k8|PNXUhYXYo*2|yagxi=WNRh)ASQkkW;*HQ^(q{mb21rm~SmNB=g&eh2>_4 zD?)TCeK||5C>m54B2ftFaR)#^IEdiEjgi2>!Xjg5Kw9_T2)+HNamrbO0<{Y(7-`Gv z7Szi7S=$Ov5Y7%rN@;`XthG_X(q>pjr0EKYIAw9msSrpEP=H)w`CfAFq<9 zsx*0?awz!y-szXLA%tj2ia4Yz9U9X$$2nx7O_5PPM_~G1#N!8-K0^qav!*6<(}~G- zQxzrrYT5n9(vR+I?`QBD%dBTpY@nw5g7UBwjEl|U?L!s=6Vq^);0IOQQ0$2}z()I` zy?mV}y+pg4?Wv$r0!0q7K$eQSYQ<1`y}Oeq=uBL5zO1La?)%6Js(t9Pkm$-BDB&xY zQluavA<0t$`tB9vM86yRY^M09G zM0Gu12olqbE>e8#>m$SY^5ZFL#ZK>9b2-c^(A?sP?fCKQS7ghL#LVYf=Vdz}Vz3Hr zF?Sb~bRrJhF$x$+x|3czy{lQ^t4#aV6PbA+3MEnRs#d9M?j0)sR_Ztcf+AT0L;$eAIgW zGBN+5f&NNZDZM{AKt{jTrZfc#>`zhn_xLw->TELT9op-jiK^=0G7GvZXj_;fqIamh z_pgBlQ|ALuKU9A(G6|K|BI2oV!@G#L=)0i9Eu+=$AAjb181}z9SeyhVa^@lEg4Hie zFR=B?qV)_=i=nV5VTKB93aE|TKIHdjnYlFX+#Gz=tg{(>Ys@T$9s1%EsFLb;Ko`zh zsUwjm>e4Vy@C=#?w;3h@HdsKlh$FB&FTPZXi7PdEpN%$xk(BUCp*^jJ-dCk_y0v0@ z=-^gfh(`#O0;&aFt+o!a!Ul;5+$iKzEnb5u4h6Jguwe^sI+Hsl30=oiMeg0hgJ?TP zWxU&yz9uvE14q~U4r~X95uX^l+!JVXCC?W#yY~)%*e^%InIYctc@T{m8!FVt0k2(Q z*Q&;gff+t?@&yDL`d~%{_vkUJxqo>0<&-{gKgF3oAtf*CEOP)r@#yLYzVf<^_+~5C zBg$1kOAINquAUcf$rVhihEvn&SttBvMI68+8Od1 zXkhy+TB+^fFP`gwZky}k+bh(+EFo<+XgxE!j+Y83v`@d1AWk;gIlUetM0XwS4tEm<{2gvr93Sa?X3ETDfow6S zxVTDb$?Dn_481KH`a}N9{_|IXQ6xZ{W2M*omrc6E%VX>u_Y4jzSNj@Jjhov{xzuI4 zZZOx0Q|#(a&4v`vr~V5PF8q_G=6*v|6b-6=9AWgyx&9%=Iqz9-JY|ISJGFTn)y}~Z zpR4@<8S19@1EE+sS-I_FUx6_NWv-ahm=#93EY|=AfMz0>A0eC9t>f~g*>)W!&hht|$f$gUa0x_Dt0#c1}-sQSS^`2%xGtH|LEIJg{xv zq2l7&Unz>P85dGI{_Bq$?uk=D!c8Z*3|0(yXe|Fa6h$Ol-OJ|M;&9khpSqegOjRU~ zN~w#i!6Zmnl7UcsP3ml^-ES@92REmi`uf8*ca@KOxdVkZ#f*CVjoR7r0el}n;){kO zJB|hEcxMW%u!05mKZ}^>JLKQeSps9+-WV?`YinL~BJAI}LR9y{Nh;Mp0w5wHW9xj^ znyi8yV227R(cruW2J@YZad41e_V+id)K6p?lZ+-tP#?ED-Dj(8bx@$d3umE9H3v%V z!;g>Y);JeQ8TbiLyH-b-oi{zLGy3n$KL_<%4ipT^+Wv+Eqw(p`@Tqr;u^l-Aa{u9E zj9o`7qOxCE>Yd{g6N5H8vvLu3DDMWWH}pk()`x4~$F?51or&3&UZUyZNl=cy_l-35 zUujxWN6-$_vU+%W8i6W}jE=_bE*D>>vU&2qeS_lWZUtrfK}A+d6wt(>AChG#`RGu! zN)daLN0Tnb)i+yzamJ?a(?7*z#5>UqHU$$qSgen2=jGYALVl*?d;5W~g;~B>t^P_3 zs{fU%GgdQC9MC7HH%Lv&4v+qD=2CS)Yo&6H`GlKDvMnKla!MGw5}*(P_eJEZdxVNl zup~4tE-uc?n(35XD8ix7KFiC74TlM+sA`LkzJ29|O-9SLO@eSF8F-SO@I(UX`EV z#Oa&^5U7BwOcY)+w433sH-b7|6~98BEUttJ()NIY3UF|SREq-PgtzGHv`VjY`PkW9g~w&cZVl+xXh+f zw`wHS-8euLOuq7VkMmv|dpVOjaZd^OSbV%ET5ZdSz<#~k+cI+6_4aIoT-noGTlQ0+W7#h}IS;T1zz2g%5Q}4I&;&X(wm99K%KD|vJ9-pY_j!!souc3R_puP zS&xl{?Olkaw0*+>l~F;_bKNkMo@f#sn@O*4cEIH7{-(iKACDD}F2&hGJw}2&mGOnZ zVoI-u(`+SvdwaS2%}Y;2?`S!?@>AJ}yjO6SqOehd{QSzKdp0IrkMy>8|ucUtdDBb(YO*~o0hPMO0 zeU%S2o<|LPIsdtFT8kcQeXTor-eQ|7iIk;|U(t&QnfztRcKv!w=Gv`Q&aK`|%;U9= zGIvRbxK8-uZge00;0=Z^CvWkm#2lOLI4g+xfv8oApurTJ`(^3FdU#~eq^gxdi4`3! zDw-m?^!`u|BW=URmE%Hnpz2pG;EQ(0^9IN;vMHwqQB9$}d6L6lkvrt43ug%ys=HSM zE`L9u7wb}Bd=3hR2>0#YIaNXGJoJTDn$G1nnnFrCZS!m=y8EX4&}D%*mCf&4?!MI}i3qdj;Qj0Huu?8d zN+C=J^8`&^m}rt%qe_2J()p0=V4{`IT+TshyXM8)Mt&F!46^^vcL6A0AW^%Fzx^S^ z1PXh(1~wBIXcrB)a{c>;*AW=V$#hxJhYO#2oiv^=3tJJCG*xv6g^`fdkXwmai)H}^ zM)MzHiR&gU+3p)YXw9(&n+zv8u#!XCt~Ui1XG?H@AWBKd&W@SZs2F(XurIBv%_$C- zR34AGdJN+!K_=yMp!Q-t98B|DI%#0Ig%Pz_VIb^CNe|t6xCoV_64$gW8Bc@1vDBV9 zxn1eB_+UP*6JgEC!nK78)%*PNWOw{$;lo0RtVIi_2YIIanER?w#Uo4HNbI`FQQQpLkTxpGUUy9w7~-LhxPR|%I(k^jS% zRaBhaWz^MyFGki$h&K&)8xRCn#kq#6lI`fcqk^6;Vlp!D9B+@T7D#0qCCH#%3H6=D zbZ%|YfTQh8WB*~8#bl1G*^dtH(!4weP=%>XU5%EF0;fUSsM=xnQ$mDq@TSi6&)T5i-~DE=1)LtWZ1OC z3aRed=PZ)gni|h6pG`)pjt476Hm(J9dJT|Pd2=>cZQun83&)R}`oLPkKrNr#wPa^T zmoHb5(mqkd5-RSNJgSF*;(SgH5if}FK3r~qXt;H&AUWUkMOZ;Bkj5iH_%<*g}tmKyS`^3j?|E znSJ3WnyILlDxs2zn%%jj8{r1n?&~Vxu{tnzDS{b zv9oOPM7x%LJ+BRv7euwS6Ovcc9AW_JA;XM>=H-IjBS-;3DdPvr8yovuu&~g+FM~H` z+*OZAjKnxwncUHIv<&BJs;Yc*hCsymle@8~Y$*>mdlabN5wkk_Qq{KMWsTaw_3_gc zi)idw#!3|xFCkWQKdF?olwk}^>GVc?bIih`=kmKPY{+!(lTdBhe|2_ zKU-93!6xDgEc2pOlP1nvHZx|{vSMKGp6{^1^rbbP0l+XkK=&NL# From 9002688f699aef96bf02c4ed43c54cd79c82b636 Mon Sep 17 00:00:00 2001 From: George Burduli Date: Tue, 13 Aug 2024 11:50:36 +0400 Subject: [PATCH 030/134] Add SVGs to git --- .../ppcp-applepay/assets/images/applepay.svg | 83 +++++++++++++++++++ .../assets/images/googlepay.svg | 36 ++++++++ 2 files changed, 119 insertions(+) create mode 100644 modules/ppcp-applepay/assets/images/applepay.svg create mode 100644 modules/ppcp-googlepay/assets/images/googlepay.svg diff --git a/modules/ppcp-applepay/assets/images/applepay.svg b/modules/ppcp-applepay/assets/images/applepay.svg new file mode 100644 index 000000000..42e09634d --- /dev/null +++ b/modules/ppcp-applepay/assets/images/applepay.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ppcp-googlepay/assets/images/googlepay.svg b/modules/ppcp-googlepay/assets/images/googlepay.svg new file mode 100644 index 000000000..0abef7bce --- /dev/null +++ b/modules/ppcp-googlepay/assets/images/googlepay.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + From b380350a75f25e84fe6cbe4028f9ac8ca3372d86 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 15:10:42 +0200 Subject: [PATCH 031/134] =?UTF-8?q?=E2=9C=A8=20Include=20numeric=20shippin?= =?UTF-8?q?g=20cost=20in=20ShippingOptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ppcp-googlepay/src/Endpoint/UpdatePaymentDataEndpoint.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ppcp-googlepay/src/Endpoint/UpdatePaymentDataEndpoint.php b/modules/ppcp-googlepay/src/Endpoint/UpdatePaymentDataEndpoint.php index 27da5ef48..1ca438c16 100644 --- a/modules/ppcp-googlepay/src/Endpoint/UpdatePaymentDataEndpoint.php +++ b/modules/ppcp-googlepay/src/Endpoint/UpdatePaymentDataEndpoint.php @@ -146,6 +146,7 @@ class UpdatePaymentDataEndpoint { wc_price( (float) $rate->get_cost(), array( 'currency' => get_woocommerce_currency() ) ) ) ), + 'cost' => $rate->get_cost(), ); } From 6b5421a2b1b0c5c3321b39b06d421b49018b24f8 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 15:41:10 +0200 Subject: [PATCH 032/134] =?UTF-8?q?=F0=9F=90=9B=20Include=20shipping=20cos?= =?UTF-8?q?ts=20in=20Google=20Pay=20dialog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/GooglepayButton.js | 98 ++++++++++++++++--- 1 file changed, 84 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index ac477404b..77c94b3fe 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -396,20 +396,21 @@ class GooglepayButton { return; } - switch ( paymentData.callbackTrigger ) { - case 'INITIALIZE': - case 'SHIPPING_ADDRESS': - paymentDataRequestUpdate.newShippingOptionParameters = - updatedData.shipping_options; - paymentDataRequestUpdate.newTransactionInfo = - this.calculateNewTransactionInfo( updatedData ); - break; - case 'SHIPPING_OPTION': - paymentDataRequestUpdate.newTransactionInfo = - this.calculateNewTransactionInfo( updatedData ); - break; + if ( + [ 'INITIALIZE', 'SHIPPING_ADDRESS' ].includes( + paymentData.callbackTrigger + ) + ) { + paymentDataRequestUpdate.newShippingOptionParameters = + updatedData.shipping_options; } + paymentDataRequestUpdate.newTransactionInfo = + this.calculateNewTransactionInfo( + updatedData, + paymentData?.shippingOptionData?.id + ); + resolve( paymentDataRequestUpdate ); } catch ( error ) { console.error( 'Error during onPaymentDataChanged:', error ); @@ -418,6 +419,68 @@ class GooglepayButton { } ); } + /** + * Returns the shipping costs as numeric value. + * + * TODO - Move this to the PaymentButton base class + * + * @param {string} shippingId - The shipping method ID. + * @param {Object} shippingData - The PaymentDataRequest object that contains shipping options. + * @param {Array} shippingData.shippingOptions + * @param {string} shippingData.defaultSelectedOptionId + * + * @return {number} The shipping costs. + */ + getShippingCosts( + shippingId, + { shippingOptions = [], defaultSelectedOptionId = '' } = {} + ) { + if ( ! shippingOptions?.length ) { + this.log( 'Cannot calculate shipping cost: No Shipping Options' ); + return 0; + } + + const findOptionById = ( id ) => + shippingOptions.find( ( option ) => option.id === id ); + + const getValidShippingId = () => { + if ( + 'shipping_option_unselected' === shippingId || + ! findOptionById( shippingId ) + ) { + // Entered on initial call, and when changing the shipping country. + return defaultSelectedOptionId; + } + + return shippingId; + }; + + const currentOption = findOptionById( getValidShippingId() ); + + return currentOption?.cost ? this.toAmount( currentOption.cost ) : 0; + } + + /** + * Converts the provided value to a number with configurable precision. + * + * TODO - Move this to the PaymentButton base class + * + * @param {any} value - The value to convert. + * @param {number} [precision=2] - The number of decimal places. + * @return {number} Always a numeric value with the specified precision. + */ + toAmount( value, precision = 2 ) { + const number = Number( value ); + + if ( isNaN( number ) ) { + return 0; + } + + const multiplier = Math.pow( 10, precision ); + + return Math.round( number * multiplier ) / multiplier; + } + unserviceableShippingAddressError() { return { reason: 'SHIPPING_ADDRESS_UNSERVICEABLE', @@ -426,12 +489,19 @@ class GooglepayButton { }; } - calculateNewTransactionInfo( updatedData ) { + calculateNewTransactionInfo( updatedData, shippingId ) { + const shippingCost = this.getShippingCosts( + shippingId, + updatedData.shipping_options + ); + const subTotal = this.toAmount( updatedData.total_str ); + const totalPrice = shippingCost + subTotal; + return { countryCode: updatedData.country_code, currencyCode: updatedData.currency_code, totalPriceStatus: 'FINAL', - totalPrice: updatedData.total_str, + totalPrice: totalPrice.toFixed( 2 ), }; } From 7946150f5b975ed228cb7ff8fc5b28f8fe5b5921 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 18:41:42 +0200 Subject: [PATCH 033/134] =?UTF-8?q?=E2=9C=A8=20New=20TransactionInfo=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/Context/BaseHandler.js | 15 ++++--- .../resources/js/Context/PayNowHandler.js | 15 ++++--- .../js/Context/SingleProductHandler.js | 15 ++++--- .../resources/js/GooglepayButton.js | 4 +- .../resources/js/Helper/TransactionInfo.js | 43 +++++++++++++++++++ 5 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js diff --git a/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js b/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js index d61b674a7..014a6f2ce 100644 --- a/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js @@ -1,5 +1,6 @@ import ErrorHandler from '../../../../ppcp-button/resources/js/modules/ErrorHandler'; import CartActionHandler from '../../../../ppcp-button/resources/js/modules/ActionHandler/CartActionHandler'; +import TransactionInfo from '../Helper/TransactionInfo'; class BaseHandler { constructor( buttonConfig, ppcpConfig, externalHandler ) { @@ -35,12 +36,14 @@ class BaseHandler { // handle script reload const data = result.data; - resolve( { - countryCode: data.country_code, - currencyCode: data.currency_code, - totalPriceStatus: 'FINAL', - totalPrice: data.total_str, - } ); + resolve( + new TransactionInfo( + data.total, + data.currency_code, + data.country_code, + true + ) + ); } ); } ); } diff --git a/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js b/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js index 79de6b39d..29e91d39b 100644 --- a/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js @@ -1,6 +1,7 @@ import Spinner from '../../../../ppcp-button/resources/js/modules/Helper/Spinner'; import BaseHandler from './BaseHandler'; import CheckoutActionHandler from '../../../../ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler'; +import TransactionInfo from '../Helper/TransactionInfo'; class PayNowHandler extends BaseHandler { validateContext() { @@ -14,12 +15,14 @@ class PayNowHandler extends BaseHandler { return new Promise( async ( resolve, reject ) => { const data = this.ppcpConfig.pay_now; - resolve( { - countryCode: data.country_code, - currencyCode: data.currency_code, - totalPriceStatus: 'FINAL', - totalPrice: data.total_str, - } ); + resolve( + new TransactionInfo( + data.total, + data.currency_code, + data.country_code, + true + ) + ); } ); } diff --git a/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js b/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js index a8aa6e8bd..6066b9eca 100644 --- a/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js @@ -3,6 +3,7 @@ import SimulateCart from '../../../../ppcp-button/resources/js/modules/Helper/Si import ErrorHandler from '../../../../ppcp-button/resources/js/modules/ErrorHandler'; import UpdateCart from '../../../../ppcp-button/resources/js/modules/Helper/UpdateCart'; import BaseHandler from './BaseHandler'; +import TransactionInfo from '../Helper/TransactionInfo'; class SingleProductHandler extends BaseHandler { validateContext() { @@ -42,12 +43,14 @@ class SingleProductHandler extends BaseHandler { this.ppcpConfig.ajax.simulate_cart.endpoint, this.ppcpConfig.ajax.simulate_cart.nonce ).simulate( ( data ) => { - resolve( { - countryCode: data.country_code, - currencyCode: data.currency_code, - totalPriceStatus: 'FINAL', - totalPrice: data.total_str, - } ); + resolve( + new TransactionInfo( + data.total, + data.currency_code, + data.country_code, + true + ) + ); }, products ); } ); } diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 77c94b3fe..cd468b93e 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -331,7 +331,7 @@ class GooglepayButton { const paymentDataRequest = Object.assign( {}, baseRequest ); paymentDataRequest.allowedPaymentMethods = googlePayConfig.allowedPaymentMethods; - paymentDataRequest.transactionInfo = this.transactionInfo; + paymentDataRequest.transactionInfo = this.transactionInfo.dataObject; paymentDataRequest.merchantInfo = googlePayConfig.merchantInfo; if ( @@ -376,7 +376,7 @@ class GooglepayButton { const updatedData = await new UpdatePaymentData( this.buttonConfig.ajax.update_payment_data ).update( paymentData ); - const transactionInfo = this.transactionInfo; + const transactionInfo = this.transactionInfo.dataObject; this.log( 'onPaymentDataChanged:updatedData', updatedData ); this.log( diff --git a/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js new file mode 100644 index 000000000..66e198374 --- /dev/null +++ b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js @@ -0,0 +1,43 @@ +export default class TransactionInfo { + #country = ''; + #currency = ''; + #isFinal = false; + #amount = 0; + + constructor( amount, currency, country, isFinal ) { + this.#country = country; + this.#currency = currency; + this.#isFinal = isFinal; + + this.amount = amount; + } + + set amount( newAmount ) { + this.#amount = Number( newAmount ) || 0; + } + + get currencyCode() { + return this.#currency; + } + + get countryCode() { + return this.#country; + } + + get totalPriceStatus() { + return this.#isFinal ? 'FINAL' : 'DRAFT'; + } + + get totalPrice() { + return this.#amount.toFixed( 2 ); + } + + get dataObject() { + return { + countryCode: this.countryCode, + currencyCode: this.currencyCode, + totalPriceStatus: this.totalPriceStatus, + totalPrice: this.totalPrice, + }; + } +} From 611ab4c5a7077bababc255ab9071e4705ff4c3c5 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 18:53:39 +0200 Subject: [PATCH 034/134] =?UTF-8?q?=E2=9C=A8=20New=20TransactionInfo=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/Context/BaseHandler.js | 15 +++++++-------- .../resources/js/Context/PayNowHandler.js | 14 +++++++------- .../resources/js/Context/SingleProductHandler.js | 14 +++++++------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js b/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js index 014a6f2ce..eebfd7518 100644 --- a/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js @@ -35,15 +35,14 @@ class BaseHandler { // handle script reload const data = result.data; - - resolve( - new TransactionInfo( - data.total, - data.currency_code, - data.country_code, - true - ) + const transaction = new TransactionInfo( + data.total, + data.currency_code, + data.country_code, + true ); + + resolve( transaction ); } ); } ); } diff --git a/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js b/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js index 29e91d39b..9d35da16e 100644 --- a/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js @@ -15,14 +15,14 @@ class PayNowHandler extends BaseHandler { return new Promise( async ( resolve, reject ) => { const data = this.ppcpConfig.pay_now; - resolve( - new TransactionInfo( - data.total, - data.currency_code, - data.country_code, - true - ) + const transaction = new TransactionInfo( + data.total, + data.currency_code, + data.country_code, + true ); + + resolve( transaction ); } ); } diff --git a/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js b/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js index 6066b9eca..61b7997c2 100644 --- a/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js @@ -43,14 +43,14 @@ class SingleProductHandler extends BaseHandler { this.ppcpConfig.ajax.simulate_cart.endpoint, this.ppcpConfig.ajax.simulate_cart.nonce ).simulate( ( data ) => { - resolve( - new TransactionInfo( - data.total, - data.currency_code, - data.country_code, - true - ) + const transaction = new TransactionInfo( + data.total, + data.currency_code, + data.country_code, + true ); + + resolve( transaction ); }, products ); } ); } From 3b92eaac813325f358da9be4072ce9a7110f188a Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 19:31:51 +0200 Subject: [PATCH 035/134] =?UTF-8?q?=E2=9C=A8=20Store=20shipping=20cost=20i?= =?UTF-8?q?n=20the=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Endpoint/SimulateCartEndpoint.php | 5 ++-- .../resources/js/Context/BaseHandler.js | 1 + .../resources/js/Context/PayNowHandler.js | 1 + .../js/Context/SingleProductHandler.js | 1 + .../resources/js/Helper/TransactionInfo.js | 24 ++++++++++++++++--- .../Endpoint/UpdatePaymentDataEndpoint.php | 5 ++-- 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-button/src/Endpoint/SimulateCartEndpoint.php b/modules/ppcp-button/src/Endpoint/SimulateCartEndpoint.php index 36069e463..a96302e65 100644 --- a/modules/ppcp-button/src/Endpoint/SimulateCartEndpoint.php +++ b/modules/ppcp-button/src/Endpoint/SimulateCartEndpoint.php @@ -85,7 +85,8 @@ class SimulateCartEndpoint extends AbstractCartEndpoint { $this->add_products( $products ); $this->cart->calculate_totals(); - $total = (float) $this->cart->get_total( 'numeric' ); + $total = (float) $this->cart->get_total( 'numeric' ); + $shipping_fee = (float) $this->cart->get_shipping_total(); $this->restore_real_cart(); @@ -113,7 +114,7 @@ class SimulateCartEndpoint extends AbstractCartEndpoint { wp_send_json_success( array( 'total' => $total, - 'total_str' => ( new Money( $total, $currency_code ) )->value_str(), + 'shipping_fee' => $shipping_fee, 'currency_code' => $currency_code, 'country_code' => $shop_country_code, 'funding' => array( diff --git a/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js b/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js index eebfd7518..a9297fca6 100644 --- a/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js @@ -37,6 +37,7 @@ class BaseHandler { const data = result.data; const transaction = new TransactionInfo( data.total, + data.shipping_fee, data.currency_code, data.country_code, true diff --git a/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js b/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js index 9d35da16e..8516d8809 100644 --- a/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js @@ -17,6 +17,7 @@ class PayNowHandler extends BaseHandler { const transaction = new TransactionInfo( data.total, + data.shipping_fee, data.currency_code, data.country_code, true diff --git a/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js b/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js index 61b7997c2..3502e7701 100644 --- a/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js @@ -45,6 +45,7 @@ class SingleProductHandler extends BaseHandler { ).simulate( ( data ) => { const transaction = new TransactionInfo( data.total, + data.shipping_fee, data.currency_code, data.country_code, true diff --git a/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js index 66e198374..012b024b5 100644 --- a/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js +++ b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js @@ -3,19 +3,35 @@ export default class TransactionInfo { #currency = ''; #isFinal = false; #amount = 0; + #shippingFee = 0; - constructor( amount, currency, country, isFinal ) { + constructor( total, shippingFee, currency, country, isFinal ) { this.#country = country; this.#currency = currency; this.#isFinal = isFinal; - this.amount = amount; + this.shippingFee = shippingFee; + this.amount = total - shippingFee; } set amount( newAmount ) { this.#amount = Number( newAmount ) || 0; } + set shippingFee( newCost ) { + this.#shippingFee = Number( newCost ) || 0; + } + + set total( newTotal ) { + newTotal = Number( newTotal ) || 0; + + if ( ! newTotal ) { + return; + } + + this.#amount = newTotal - this.#shippingFee; + } + get currencyCode() { return this.#currency; } @@ -29,7 +45,9 @@ export default class TransactionInfo { } get totalPrice() { - return this.#amount.toFixed( 2 ); + const total = this.#amount + this.#shippingFee; + + return total.toFixed( 2 ); } get dataObject() { diff --git a/modules/ppcp-googlepay/src/Endpoint/UpdatePaymentDataEndpoint.php b/modules/ppcp-googlepay/src/Endpoint/UpdatePaymentDataEndpoint.php index 1ca438c16..e489bc771 100644 --- a/modules/ppcp-googlepay/src/Endpoint/UpdatePaymentDataEndpoint.php +++ b/modules/ppcp-googlepay/src/Endpoint/UpdatePaymentDataEndpoint.php @@ -90,7 +90,8 @@ class UpdatePaymentDataEndpoint { WC()->cart->calculate_fees(); WC()->cart->calculate_totals(); - $total = (float) WC()->cart->get_total( 'numeric' ); + $total = (float) WC()->cart->get_total( 'numeric' ); + $shipping_fee = (float) WC()->cart->get_shipping_total(); // Shop settings. $base_location = wc_get_base_location(); @@ -100,7 +101,7 @@ class UpdatePaymentDataEndpoint { wp_send_json_success( array( 'total' => $total, - 'total_str' => ( new Money( $total, $currency_code ) )->value_str(), + 'shipping_fee' => $shipping_fee, 'currency_code' => $currency_code, 'country_code' => $shop_country_code, 'shipping_options' => $this->get_shipping_options(), From 179c1d6831adf8bf81a967f3242bd6ce777dd790 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 19:34:13 +0200 Subject: [PATCH 036/134] =?UTF-8?q?=F0=9F=94=A5=20Minor=20clean-up?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/GooglepayButton.js | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index cd468b93e..6ad65c6d5 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -386,7 +386,6 @@ class GooglepayButton { updatedData.country_code = transactionInfo.countryCode; updatedData.currency_code = transactionInfo.currencyCode; - updatedData.total_str = transactionInfo.totalPrice; // Handle unserviceable address. if ( ! updatedData.shipping_options?.shippingOptions?.length ) { @@ -425,7 +424,8 @@ class GooglepayButton { * TODO - Move this to the PaymentButton base class * * @param {string} shippingId - The shipping method ID. - * @param {Object} shippingData - The PaymentDataRequest object that contains shipping options. + * @param {Object} shippingData - The PaymentDataRequest object that + * contains shipping options. * @param {Array} shippingData.shippingOptions * @param {string} shippingData.defaultSelectedOptionId * @@ -460,27 +460,6 @@ class GooglepayButton { return currentOption?.cost ? this.toAmount( currentOption.cost ) : 0; } - /** - * Converts the provided value to a number with configurable precision. - * - * TODO - Move this to the PaymentButton base class - * - * @param {any} value - The value to convert. - * @param {number} [precision=2] - The number of decimal places. - * @return {number} Always a numeric value with the specified precision. - */ - toAmount( value, precision = 2 ) { - const number = Number( value ); - - if ( isNaN( number ) ) { - return 0; - } - - const multiplier = Math.pow( 10, precision ); - - return Math.round( number * multiplier ) / multiplier; - } - unserviceableShippingAddressError() { return { reason: 'SHIPPING_ADDRESS_UNSERVICEABLE', From 8f191c2d490d6b68bf790eca28c7203ca1d79e60 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 19:36:37 +0200 Subject: [PATCH 037/134] =?UTF-8?q?=F0=9F=90=9B=20Fix=20the=20price=20calc?= =?UTF-8?q?ulation=20on=20product=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/GooglepayButton.js | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 6ad65c6d5..b0272cc9b 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -3,6 +3,7 @@ import { setEnabled } from '../../../ppcp-button/resources/js/modules/Helper/But import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder'; import UpdatePaymentData from './Helper/UpdatePaymentData'; import { apmButtonsInit } from '../../../ppcp-button/resources/js/modules/Helper/ApmButtons'; +import TransactionInfo from './Helper/TransactionInfo'; class GooglepayButton { constructor( @@ -376,7 +377,7 @@ class GooglepayButton { const updatedData = await new UpdatePaymentData( this.buttonConfig.ajax.update_payment_data ).update( paymentData ); - const transactionInfo = this.transactionInfo.dataObject; + const transactionInfo = this.transactionInfo; this.log( 'onPaymentDataChanged:updatedData', updatedData ); this.log( @@ -404,12 +405,14 @@ class GooglepayButton { updatedData.shipping_options; } - paymentDataRequestUpdate.newTransactionInfo = - this.calculateNewTransactionInfo( - updatedData, - paymentData?.shippingOptionData?.id + transactionInfo.shippingFee = this.getShippingCosts( + paymentData?.shippingOptionData?.id, + updatedData.shipping_options ); + paymentDataRequestUpdate.newTransactionInfo = + this.calculateNewTransactionInfo( transactionInfo ); + resolve( paymentDataRequestUpdate ); } catch ( error ) { console.error( 'Error during onPaymentDataChanged:', error ); @@ -457,7 +460,7 @@ class GooglepayButton { const currentOption = findOptionById( getValidShippingId() ); - return currentOption?.cost ? this.toAmount( currentOption.cost ) : 0; + return Number( currentOption?.cost ) || 0; } unserviceableShippingAddressError() { @@ -468,20 +471,14 @@ class GooglepayButton { }; } - calculateNewTransactionInfo( updatedData, shippingId ) { - const shippingCost = this.getShippingCosts( - shippingId, - updatedData.shipping_options - ); - const subTotal = this.toAmount( updatedData.total_str ); - const totalPrice = shippingCost + subTotal; - - return { - countryCode: updatedData.country_code, - currencyCode: updatedData.currency_code, - totalPriceStatus: 'FINAL', - totalPrice: totalPrice.toFixed( 2 ), - }; + /** + * Recalculates and returns the plain transaction info object. + * + * @param {TransactionInfo} transactionInfo - Internal transactionInfo instance. + * @return {{totalPrice: string, countryCode: string, totalPriceStatus: string, currencyCode: string}} Updated details. + */ + calculateNewTransactionInfo( transactionInfo ) { + return transactionInfo.dataObject; } //------------------------ From f2301a467478c60d0496ac0cea2d99a09dde3e4c Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 20:02:49 +0200 Subject: [PATCH 038/134] =?UTF-8?q?=F0=9F=90=9B=20Fix=20price=20calculatio?= =?UTF-8?q?n=20on=20pages=20with=20cart?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This covers: Mini-Cart, Classic Cart, Block Cart, Classic Checkout, Block Checkout, Pay-Now page --- .../resources/js/GooglepayButton.js | 28 +++++++++-- .../resources/js/Helper/TransactionInfo.js | 47 +++++++++++++++---- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index b0272cc9b..9f8524997 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -6,6 +6,11 @@ import { apmButtonsInit } from '../../../ppcp-button/resources/js/modules/Helper import TransactionInfo from './Helper/TransactionInfo'; class GooglepayButton { + /** + * @type {TransactionInfo} + */ + transactionInfo; + constructor( context, externalHandler, @@ -379,6 +384,16 @@ class GooglepayButton { ).update( paymentData ); const transactionInfo = this.transactionInfo; + // Check, if the current context uses the WC cart. + const hasRealCart = [ + 'checkout-block', + 'checkout', + 'cart-block', + 'cart', + 'mini-cart', + 'pay-now', + ].includes( this.context ); + this.log( 'onPaymentDataChanged:updatedData', updatedData ); this.log( 'onPaymentDataChanged:transactionInfo', @@ -405,10 +420,17 @@ class GooglepayButton { updatedData.shipping_options; } - transactionInfo.shippingFee = this.getShippingCosts( - paymentData?.shippingOptionData?.id, - updatedData.shipping_options + if ( updatedData.total && hasRealCart ) { + transactionInfo.setTotal( + updatedData.total, + updatedData.shipping_fee ); + } else { + transactionInfo.shippingFee = this.getShippingCosts( + paymentData?.shippingOptionData?.id, + updatedData.shipping_options + ); + } paymentDataRequestUpdate.newTransactionInfo = this.calculateNewTransactionInfo( transactionInfo ); diff --git a/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js index 012b024b5..93ffe2e6e 100644 --- a/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js +++ b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js @@ -15,21 +15,19 @@ export default class TransactionInfo { } set amount( newAmount ) { - this.#amount = Number( newAmount ) || 0; + this.#amount = this.toAmount( newAmount ); + } + + get amount() { + return this.#amount; } set shippingFee( newCost ) { - this.#shippingFee = Number( newCost ) || 0; + this.#shippingFee = this.toAmount( newCost ); } - set total( newTotal ) { - newTotal = Number( newTotal ) || 0; - - if ( ! newTotal ) { - return; - } - - this.#amount = newTotal - this.#shippingFee; + get shippingFee() { + return this.#shippingFee; } get currencyCode() { @@ -58,4 +56,33 @@ export default class TransactionInfo { totalPrice: this.totalPrice, }; } + + /** + * Converts the value to a number and rounds to a precision of 2 digits. + * + * @param {any} value - The value to sanitize. + * @return {number} Numeric value. + */ + toAmount( value ) { + value = Number( value ) || 0; + return Math.round( value * 100 ) / 100; + } + + setTotal( totalPrice, shippingFee ) { + totalPrice = this.toAmount( totalPrice ); + + if ( totalPrice ) { + this.shippingFee = shippingFee; + this.amount = totalPrice - this.shippingFee; + + console.log( + 'New Total Price:', + totalPrice, + '=', + this.amount, + '+', + this.shippingFee + ); + } + } } From ac98600b8fc085e468ed157afc2be16efa958601 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 20:23:51 +0200 Subject: [PATCH 039/134] =?UTF-8?q?=F0=9F=94=A5=20Simplify=20code,=20remov?= =?UTF-8?q?e=20console=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/Context/BaseHandler.js | 3 +-- .../resources/js/Context/PayNowHandler.js | 3 +-- .../js/Context/SingleProductHandler.js | 3 +-- .../resources/js/GooglepayButton.js | 4 ++-- .../resources/js/Helper/TransactionInfo.js | 21 +++---------------- 5 files changed, 8 insertions(+), 26 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js b/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js index a9297fca6..d49bee615 100644 --- a/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/BaseHandler.js @@ -39,8 +39,7 @@ class BaseHandler { data.total, data.shipping_fee, data.currency_code, - data.country_code, - true + data.country_code ); resolve( transaction ); diff --git a/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js b/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js index 8516d8809..81d60b078 100644 --- a/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js @@ -19,8 +19,7 @@ class PayNowHandler extends BaseHandler { data.total, data.shipping_fee, data.currency_code, - data.country_code, - true + data.country_code ); resolve( transaction ); diff --git a/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js b/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js index 3502e7701..670b9a7c0 100644 --- a/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js +++ b/modules/ppcp-googlepay/resources/js/Context/SingleProductHandler.js @@ -47,8 +47,7 @@ class SingleProductHandler extends BaseHandler { data.total, data.shipping_fee, data.currency_code, - data.country_code, - true + data.country_code ); resolve( transaction ); diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 9f8524997..d626a172b 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -337,7 +337,7 @@ class GooglepayButton { const paymentDataRequest = Object.assign( {}, baseRequest ); paymentDataRequest.allowedPaymentMethods = googlePayConfig.allowedPaymentMethods; - paymentDataRequest.transactionInfo = this.transactionInfo.dataObject; + paymentDataRequest.transactionInfo = this.transactionInfo.finalObject; paymentDataRequest.merchantInfo = googlePayConfig.merchantInfo; if ( @@ -500,7 +500,7 @@ class GooglepayButton { * @return {{totalPrice: string, countryCode: string, totalPriceStatus: string, currencyCode: string}} Updated details. */ calculateNewTransactionInfo( transactionInfo ) { - return transactionInfo.dataObject; + return transactionInfo.finalObject; } //------------------------ diff --git a/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js index 93ffe2e6e..9216ad7c9 100644 --- a/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js +++ b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js @@ -1,14 +1,12 @@ export default class TransactionInfo { #country = ''; #currency = ''; - #isFinal = false; #amount = 0; #shippingFee = 0; - constructor( total, shippingFee, currency, country, isFinal ) { + constructor( total, shippingFee, currency, country ) { this.#country = country; this.#currency = currency; - this.#isFinal = isFinal; this.shippingFee = shippingFee; this.amount = total - shippingFee; @@ -38,21 +36,17 @@ export default class TransactionInfo { return this.#country; } - get totalPriceStatus() { - return this.#isFinal ? 'FINAL' : 'DRAFT'; - } - get totalPrice() { const total = this.#amount + this.#shippingFee; return total.toFixed( 2 ); } - get dataObject() { + get finalObject() { return { countryCode: this.countryCode, currencyCode: this.currencyCode, - totalPriceStatus: this.totalPriceStatus, + totalPriceStatus: 'FINAL', totalPrice: this.totalPrice, }; } @@ -74,15 +68,6 @@ export default class TransactionInfo { if ( totalPrice ) { this.shippingFee = shippingFee; this.amount = totalPrice - this.shippingFee; - - console.log( - 'New Total Price:', - totalPrice, - '=', - this.amount, - '+', - this.shippingFee - ); } } } From 00e29597002c7aed3add7b863a97b0e7e392ab69 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Fri, 16 Aug 2024 15:41:05 +0200 Subject: [PATCH 040/134] =?UTF-8?q?=E2=9C=A8=20Get=20payee=20details=20wit?= =?UTF-8?q?hout=20shipping=20callback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/modules/Helper/PayerData.js | 168 +++++++++---- .../resources/js/GooglepayButton.js | 230 ++++++++++-------- 2 files changed, 257 insertions(+), 141 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js index b9b84d14f..da7eca4d6 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js +++ b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js @@ -1,59 +1,135 @@ +/** + * Name details. + * + * @typedef {Object} NameDetails + * @property {?string} given_name - First name, e.g. "John". + * @property {?string} surname - Last name, e.g. "Doe". + */ + +/** + * Postal address details. + * + * @typedef {Object} AddressDetails + * @property {?string} country_code - Country code (2-letter). + * @property {?string} address_line_1 - Address details, line 1 (street, house number). + * @property {?string} address_line_2 - Address details, line 2. + * @property {?string} admin_area_1 - State or region. + * @property {?string} admin_area_2 - State or region. + * @property {?string} postal_code - Zip code. + */ + +/** + * Phone details. + * + * @typedef {Object} PhoneDetails + * @property {?string} phone_type - Type, usually 'HOME' + * @property {?{national_number: string}} phone_number - Phone number details. + */ + +/** + * Payer details. + * + * @typedef {Object} PayerDetails + * @property {?string} email_address - Email address for billing communication. + * @property {?PhoneDetails} phone - Phone number for billing communication. + * @property {?NameDetails} name - Payer's name. + * @property {?AddressDetails} address - Postal billing address. + */ + +// Map checkout fields to PayerData object properties. +const FIELD_MAP = { + '#billing_email': [ 'email_address' ], + '#billing_last_name': [ 'name', 'surname' ], + '#billing_first_name': [ 'name', 'given_name' ], + '#billing_country': [ 'address', 'country_code' ], + '#billing_address_1': [ 'address', 'address_line_1' ], + '#billing_address_2': [ 'address', 'address_line_2' ], + '#billing_state': [ 'address', 'admin_area_1' ], + '#billing_city': [ 'address', 'admin_area_2' ], + '#billing_postcode': [ 'address', 'postal_code' ], + '#billing_phone': [ 'phone' ], +}; + +/** + * Returns billing details from the checkout form or global JS object. + * + * @return {?PayerDetails} Full billing details, or null on failure. + */ export const payerData = () => { - const payer = PayPalCommerceGateway.payer; + const payer = window.PayPalCommerceGateway?.payer; if ( ! payer ) { return null; } - const phone = - document.querySelector( '#billing_phone' ) || - typeof payer.phone !== 'undefined' - ? { - phone_type: 'HOME', - phone_number: { - national_number: document.querySelector( - '#billing_phone' - ) - ? document.querySelector( '#billing_phone' ).value - : payer.phone.phone_number.national_number, - }, - } - : null; - const payerData = { - email_address: document.querySelector( '#billing_email' ) - ? document.querySelector( '#billing_email' ).value - : payer.email_address, + const getElementValue = ( selector ) => + document.querySelector( selector )?.value; + + // Initialize data with existing payer values. + const data = { + email_address: payer.email_address, + phone: payer.phone, name: { - surname: document.querySelector( '#billing_last_name' ) - ? document.querySelector( '#billing_last_name' ).value - : payer.name.surname, - given_name: document.querySelector( '#billing_first_name' ) - ? document.querySelector( '#billing_first_name' ).value - : payer.name.given_name, + surname: payer.name?.surname, + given_name: payer.name?.given_name, }, address: { - country_code: document.querySelector( '#billing_country' ) - ? document.querySelector( '#billing_country' ).value - : payer.address.country_code, - address_line_1: document.querySelector( '#billing_address_1' ) - ? document.querySelector( '#billing_address_1' ).value - : payer.address.address_line_1, - address_line_2: document.querySelector( '#billing_address_2' ) - ? document.querySelector( '#billing_address_2' ).value - : payer.address.address_line_2, - admin_area_1: document.querySelector( '#billing_state' ) - ? document.querySelector( '#billing_state' ).value - : payer.address.admin_area_1, - admin_area_2: document.querySelector( '#billing_city' ) - ? document.querySelector( '#billing_city' ).value - : payer.address.admin_area_2, - postal_code: document.querySelector( '#billing_postcode' ) - ? document.querySelector( '#billing_postcode' ).value - : payer.address.postal_code, + country_code: payer.address?.country_code, + address_line_1: payer.address?.address_line_1, + address_line_2: payer.address?.address_line_2, + admin_area_1: payer.address?.admin_area_1, + admin_area_2: payer.address?.admin_area_2, + postal_code: payer.address?.postal_code, }, }; - if ( phone ) { - payerData.phone = phone; + // Update data with DOM values where they exist. + Object.entries( FIELD_MAP ).forEach( ( [ selector, path ] ) => { + const value = getElementValue( selector ); + if ( value ) { + let current = data; + path.slice( 0, -1 ).forEach( ( key ) => { + current = current[ key ] = current[ key ] || {}; + } ); + current[ path[ path.length - 1 ] ] = value; + } + } ); + + // Handle phone separately due to its nested structure. + const phoneNumber = data.phone; + if ( phoneNumber && typeof phoneNumber === 'string' ) { + data.phone = { + phone_type: 'HOME', + phone_number: { national_number: phoneNumber }, + }; } - return payerData; + + return data; +}; + +/** + * Updates the DOM with specific payer details. + * + * @param {PayerDetails} newData - New payer details. + */ +export const setPayerData = ( newData ) => { + const setValue = ( path, field, value ) => { + if ( null === value || undefined === value || ! field ) { + return; + } + + if ( path[ 0 ] === 'phone' && typeof value === 'object' ) { + value = value.phone_number?.national_number; + } + + if ( field.value !== value ) { + field.value = value; + } + }; + + Object.entries( FIELD_MAP ).forEach( ( [ selector, path ] ) => { + const value = path.reduce( ( obj, key ) => obj?.[ key ], newData ); + const element = document.querySelector( selector ); + + setValue( path, element, value ); + } ); }; diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 4b267c4e7..a9bfd693e 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -6,6 +6,7 @@ import PaymentButton from '../../../ppcp-button/resources/js/modules/Renderer/Pa import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder'; import UpdatePaymentData from './Helper/UpdatePaymentData'; import { PaymentMethods } from '../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState'; +import { setPayerData } from '../../../ppcp-button/resources/js/modules/Helper/PayerData'; /** * Plugin-specific styling. @@ -39,11 +40,17 @@ import { PaymentMethods } from '../../../ppcp-button/resources/js/modules/Helper * * @see https://developers.google.com/pay/api/web/reference/client * @typedef {Object} PaymentsClient - * @property {Function} createButton - The convenience method is used to generate a Google Pay payment button styled with the latest Google Pay branding for insertion into a webpage. - * @property {Function} isReadyToPay - Use the isReadyToPay(isReadyToPayRequest) method to determine a user's ability to return a form of payment from the Google Pay API. - * @property {Function} loadPaymentData - This method presents a Google Pay payment sheet that allows selection of a payment method and optionally configured parameters - * @property {Function} onPaymentAuthorized - This method is called when a payment is authorized in the payment sheet. - * @property {Function} onPaymentDataChanged - This method handles payment data changes in the payment sheet such as shipping address and shipping options. + * @property {Function} createButton - The convenience method is used to + * generate a Google Pay payment button styled with the latest Google Pay branding for + * insertion into a webpage. + * @property {Function} isReadyToPay - Use the isReadyToPay(isReadyToPayRequest) + * method to determine a user's ability to return a form of payment from the Google Pay API. + * @property {(Object) => Promise} loadPaymentData - This method presents a Google Pay payment + * sheet that allows selection of a payment method and optionally configured parameters + * @property {Function} onPaymentAuthorized - This method is called when a payment is + * authorized in the payment sheet. + * @property {Function} onPaymentDataChanged - This method handles payment data changes + * in the payment sheet such as shipping address and shipping options. */ /** @@ -53,12 +60,18 @@ import { PaymentMethods } from '../../../ppcp-button/resources/js/modules/Helper * @typedef {Object} TransactionInfo * @property {string} currencyCode - Required. The ISO 4217 alphabetic currency code. * @property {string} countryCode - Optional. required for EEA countries, - * @property {string} transactionId - Optional. A unique ID that identifies a facilitation attempt. Highly encouraged for troubleshooting. - * @property {string} totalPriceStatus - Required. [ESTIMATED|FINAL] The status of the total price used: - * @property {string} totalPrice - Required. Total monetary value of the transaction with an optional decimal precision of two decimal places. - * @property {Array} displayItems - Optional. A list of cart items shown in the payment sheet (e.g. subtotals, sales taxes, shipping charges, discounts etc.). - * @property {string} totalPriceLabel - Optional. Custom label for the total price within the display items. - * @property {string} checkoutOption - Optional. Affects the submit button text displayed in the Google Pay payment sheet. + * @property {string} transactionId - Optional. A unique ID that identifies a facilitation + * attempt. Highly encouraged for troubleshooting. + * @property {string} totalPriceStatus - Required. [ESTIMATED|FINAL] The status of the total price + * used: + * @property {string} totalPrice - Required. Total monetary value of the transaction with an + * optional decimal precision of two decimal places. + * @property {Array} displayItems - Optional. A list of cart items shown in the payment sheet + * (e.g. subtotals, sales taxes, shipping charges, discounts etc.). + * @property {string} totalPriceLabel - Optional. Custom label for the total price within the + * display items. + * @property {string} checkoutOption - Optional. Affects the submit button text displayed in the + * Google Pay payment sheet. */ class GooglepayButton extends PaymentButton { @@ -78,7 +91,7 @@ class GooglepayButton extends PaymentButton { #paymentsClient = null; /** - * Details about the processed transaction. + * Details about the processed transaction, provided to the Google SDK. * * @type {?TransactionInfo} */ @@ -388,12 +401,14 @@ class GooglepayButton extends PaymentButton { const initiatePaymentRequest = () => { window.ppcpFundingSource = 'googlepay'; const paymentDataRequest = this.paymentDataRequest(); + this.log( 'onButtonClick: paymentDataRequest', paymentDataRequest, this.context ); - this.paymentsClient.loadPaymentData( paymentDataRequest ); + + return this.paymentsClient.loadPaymentData( paymentDataRequest ); }; const validateForm = () => { @@ -434,28 +449,24 @@ class GooglepayButton extends PaymentButton { apiVersionMinor: 0, }; - const googlePayConfig = this.googlePayConfig; - const paymentDataRequest = Object.assign( {}, baseRequest ); - paymentDataRequest.allowedPaymentMethods = - googlePayConfig.allowedPaymentMethods; - paymentDataRequest.transactionInfo = this.transactionInfo; - paymentDataRequest.merchantInfo = googlePayConfig.merchantInfo; + const useShippingCallback = this.requiresShipping; + const callbackIntents = [ 'PAYMENT_AUTHORIZATION' ]; - if ( this.requiresShipping ) { - paymentDataRequest.callbackIntents = [ - 'SHIPPING_ADDRESS', - 'SHIPPING_OPTION', - 'PAYMENT_AUTHORIZATION', - ]; - paymentDataRequest.shippingAddressRequired = true; - paymentDataRequest.shippingAddressParameters = - this.shippingAddressParameters(); - paymentDataRequest.shippingOptionRequired = true; - } else { - paymentDataRequest.callbackIntents = [ 'PAYMENT_AUTHORIZATION' ]; + if ( useShippingCallback ) { + callbackIntents.push( 'SHIPPING_ADDRESS', 'SHIPPING_OPTION' ); } - return paymentDataRequest; + return { + ...baseRequest, + allowedPaymentMethods: this.googlePayConfig.allowedPaymentMethods, + transactionInfo: this.transactionInfo, + merchantInfo: this.googlePayConfig.merchantInfo, + callbackIntents, + emailRequired: true, + shippingAddressRequired: useShippingCallback, + shippingOptionRequired: useShippingCallback, + shippingAddressParameters: this.shippingAddressParameters(), + }; } //------------------------ @@ -543,82 +554,111 @@ class GooglepayButton extends PaymentButton { //------------------------ onPaymentAuthorized( paymentData ) { - this.log( 'onPaymentAuthorized' ); + this.log( 'onPaymentAuthorized', paymentData ); + return this.processPayment( paymentData ); } async processPayment( paymentData ) { this.log( 'processPayment' ); - return new Promise( async ( resolve, reject ) => { - try { - const id = await this.contextHandler.createOrder(); + const paymentError = ( reason ) => { + this.error( reason ); - this.log( 'processPayment: createOrder', id ); + return this.processPaymentResponse( + 'ERROR', + 'PAYMENT_AUTHORIZATION', + reason + ); + }; - const confirmOrderResponse = await widgetBuilder.paypal - .Googlepay() - .confirmOrder( { - orderId: id, - paymentMethodData: paymentData.paymentMethodData, - } ); + const checkPayPalApproval = async ( orderId ) => { + const confirmOrderResponse = await widgetBuilder.paypal + .Googlepay() + .confirmOrder( { + orderId, + paymentMethodData: paymentData.paymentMethodData, + } ); - this.log( - 'processPayment: confirmOrder', - confirmOrderResponse - ); + this.log( 'confirmOrder', confirmOrderResponse ); - /** Capture the Order on the Server */ - if ( confirmOrderResponse.status === 'APPROVED' ) { - let approveFailed = false; - await this.contextHandler.approveOrder( - { - orderID: id, - }, - { - // actions mock object. - restart: () => - new Promise( ( resolve, reject ) => { - approveFailed = true; - resolve(); - } ), - order: { - get: () => - new Promise( ( resolve, reject ) => { - resolve( null ); - } ), - }, - } - ); + return 'APPROVE' === confirmOrderResponse?.status; + }; - if ( ! approveFailed ) { - resolve( this.processPaymentResponse( 'SUCCESS' ) ); - } else { - resolve( - this.processPaymentResponse( - 'ERROR', - 'PAYMENT_AUTHORIZATION', - 'FAILED TO APPROVE' - ) - ); - } - } else { - resolve( - this.processPaymentResponse( - 'ERROR', - 'PAYMENT_AUTHORIZATION', - 'TRANSACTION FAILED' - ) - ); + const approveOrderServerSide = async ( orderID ) => { + let isApproved = true; + + this.log( 'approveOrder', orderID ); + + await this.contextHandler.approveOrder( + { orderID }, + { + restart: () => + new Promise( ( resolve ) => { + isApproved = false; + resolve(); + } ), + order: { + get: () => + new Promise( ( resolve ) => { + resolve( null ); + } ), + }, } + ); + + return isApproved; + }; + + const processPaymentPromise = async ( resolve ) => { + const id = await this.contextHandler.createOrder(); + + this.log( 'createOrder', id ); + + const isApprovedByPayPal = await checkPayPalApproval( id ); + + if ( ! isApprovedByPayPal ) { + resolve( paymentError( 'TRANSACTION FAILED' ) ); + + return; + } + + const success = await approveOrderServerSide( id ); + + if ( success ) { + resolve( this.processPaymentResponse( 'SUCCESS' ) ); + } else { + resolve( paymentError( 'FAILED TO APPROVE' ) ); + } + }; + + const propagatePayerDataToForm = () => { + const raw = paymentData?.paymentMethodData?.info?.billingAddress; + + const payer = { + name: { + given_name: raw.name.split( ' ' )[ 0 ], // Assuming first name is the first part + surname: raw.name.split( ' ' ).slice( 1 ).join( ' ' ), // Assuming last name is the rest + }, + address: { + country_code: raw.countryCode, + address_line_1: raw.address1, + address_line_2: raw.address2, + admin_area_1: raw.administrativeArea, + admin_area_2: raw.locality, + postal_code: raw.postalCode, + }, + }; + + setPayerData( payer ); + }; + + return new Promise( async ( resolve ) => { + try { + propagatePayerDataToForm(); + await processPaymentPromise( resolve ); } catch ( err ) { - resolve( - this.processPaymentResponse( - 'ERROR', - 'PAYMENT_AUTHORIZATION', - err.message - ) - ); + resolve( paymentError( err.message ) ); } } ); } From 63e9c8bf27729d0616f2f8249130d0c107adb274 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Fri, 16 Aug 2024 18:15:59 +0200 Subject: [PATCH 041/134] =?UTF-8?q?=E2=9C=A8=20New=20ConsoleLogger=20`grou?= =?UTF-8?q?p`=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Groups subsequent console.log output, for cleaner console output --- .../js/modules/Renderer/PaymentButton.js | 9 ++++++ .../resources/js/GooglepayButton.js | 16 +++++----- .../resources/js/helper/ConsoleLogger.js | 31 +++++++++++++++++++ 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js b/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js index 11fe31f79..143265bfb 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js @@ -599,6 +599,15 @@ export default class PaymentButton { this.#logger.error( ...args ); } + /** + * Open or close a log-group + * + * @param {?string} [label=null] Group label. + */ + logGroup( label = null ) { + this.#logger.group( label ); + } + /** * Determines if the current button instance has valid and complete configuration details. * Used during initialization to decide if the button can be initialized or should be skipped. diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index a9bfd693e..cfd5d4b07 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -560,7 +560,7 @@ class GooglepayButton extends PaymentButton { } async processPayment( paymentData ) { - this.log( 'processPayment' ); + this.logGroup( 'processPayment' ); const paymentError = ( reason ) => { this.error( reason ); @@ -623,13 +623,13 @@ class GooglepayButton extends PaymentButton { return; } - const success = await approveOrderServerSide( id ); + const success = await approveOrderServerSide( id ); - if ( success ) { - resolve( this.processPaymentResponse( 'SUCCESS' ) ); - } else { - resolve( paymentError( 'FAILED TO APPROVE' ) ); - } + if ( success ) { + resolve( this.processPaymentResponse( 'SUCCESS' ) ); + } else { + resolve( paymentError( 'FAILED TO APPROVE' ) ); + } }; const propagatePayerDataToForm = () => { @@ -660,6 +660,8 @@ class GooglepayButton extends PaymentButton { } catch ( err ) { resolve( paymentError( err.message ) ); } + + this.logGroup(); } ); } diff --git a/modules/ppcp-wc-gateway/resources/js/helper/ConsoleLogger.js b/modules/ppcp-wc-gateway/resources/js/helper/ConsoleLogger.js index c76aa8960..a7b61b32a 100644 --- a/modules/ppcp-wc-gateway/resources/js/helper/ConsoleLogger.js +++ b/modules/ppcp-wc-gateway/resources/js/helper/ConsoleLogger.js @@ -18,6 +18,13 @@ export default class ConsoleLogger { */ #enabled = false; + /** + * Tracks the current log-group that was started using `this.group()` + * + * @type {?string} + */ + #openGroup = null; + constructor( ...prefixes ) { if ( prefixes.length ) { this.#prefix = `[${ prefixes.join( ' | ' ) }]`; @@ -55,4 +62,28 @@ export default class ConsoleLogger { error( ...args ) { console.error( this.#prefix, ...args ); } + + /** + * Starts or ends a group in the browser console. + * + * @param {string} [label=null] - The group label. Omit to end the current group. + */ + group( label = null ) { + if ( ! this.#enabled ) { + return; + } + + if ( ! label || this.#openGroup ) { + // eslint-disable-next-line + console.groupEnd(); + this.#openGroup = null; + } + + if ( label ) { + // eslint-disable-next-line + console.group( label ); + + this.#openGroup = label; + } + } } From c007d7909c2793b266eb733c565a7ec52b87af4b Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Fri, 16 Aug 2024 18:45:49 +0200 Subject: [PATCH 042/134] =?UTF-8?q?=E2=9C=A8=20Option=20to=20only=20set=20?= =?UTF-8?q?missing=20billing=20details?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/modules/Helper/PayerData.js | 10 +++++++--- modules/ppcp-googlepay/resources/js/GooglepayButton.js | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js index da7eca4d6..1f97309c1 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js +++ b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js @@ -109,9 +109,13 @@ export const payerData = () => { /** * Updates the DOM with specific payer details. * - * @param {PayerDetails} newData - New payer details. + * @param {PayerDetails} newData - New payer details. + * @param {boolean} [overwriteExisting=false] - If set to true, all provided values will replace existing details. If false, or omitted, only undefined fields are updated. */ -export const setPayerData = ( newData ) => { +export const setPayerData = ( newData, overwriteExisting = false ) => { + // TODO: Check if we can add some kind of "filter" to allow customization of the data. + // Or add JS flags like "onlyUpdateMissing". + const setValue = ( path, field, value ) => { if ( null === value || undefined === value || ! field ) { return; @@ -121,7 +125,7 @@ export const setPayerData = ( newData ) => { value = value.phone_number?.national_number; } - if ( field.value !== value ) { + if ( overwriteExisting || ! field.value ) { field.value = value; } }; diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index cfd5d4b07..d518c1850 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -634,8 +634,8 @@ class GooglepayButton extends PaymentButton { const propagatePayerDataToForm = () => { const raw = paymentData?.paymentMethodData?.info?.billingAddress; - const payer = { + email_address: paymentData?.email, name: { given_name: raw.name.split( ' ' )[ 0 ], // Assuming first name is the first part surname: raw.name.split( ' ' ).slice( 1 ).join( ' ' ), // Assuming last name is the rest From cf83d2ba6efa6e254ba508939f675121f4cf2401 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Fri, 16 Aug 2024 18:54:55 +0200 Subject: [PATCH 043/134] =?UTF-8?q?=F0=9F=90=9B=20Fix=20critical=20typo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ppcp-googlepay/resources/js/GooglepayButton.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index d518c1850..d8a910f34 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -573,16 +573,18 @@ class GooglepayButton extends PaymentButton { }; const checkPayPalApproval = async ( orderId ) => { + const confirmationData = { + orderId, + paymentMethodData: paymentData.paymentMethodData, + }; + const confirmOrderResponse = await widgetBuilder.paypal .Googlepay() - .confirmOrder( { - orderId, - paymentMethodData: paymentData.paymentMethodData, - } ); + .confirmOrder( confirmationData ); this.log( 'confirmOrder', confirmOrderResponse ); - return 'APPROVE' === confirmOrderResponse?.status; + return 'APPROVED' === confirmOrderResponse?.status; }; const approveOrderServerSide = async ( orderID ) => { From 451dc842ed506fe6b48b10e7fad4e128fe050fef Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 20 Aug 2024 13:47:00 +0200 Subject: [PATCH 044/134] =?UTF-8?q?=E2=9C=A8=20New=20LocalStorage=20module?= =?UTF-8?q?=20for=20Google=20Pay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../js/modules/Helper/LocalStorage.js | 179 ++++++++++++++++++ .../resources/js/Helper/GooglePayStorage.js | 31 +++ 2 files changed, 210 insertions(+) create mode 100644 modules/ppcp-button/resources/js/modules/Helper/LocalStorage.js create mode 100644 modules/ppcp-googlepay/resources/js/Helper/GooglePayStorage.js diff --git a/modules/ppcp-button/resources/js/modules/Helper/LocalStorage.js b/modules/ppcp-button/resources/js/modules/Helper/LocalStorage.js new file mode 100644 index 000000000..65494369e --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Helper/LocalStorage.js @@ -0,0 +1,179 @@ +/* global localStorage */ + +function checkLocalStorageAvailability() { + try { + const testKey = '__ppcp_test__'; + localStorage.setItem( testKey, 'test' ); + localStorage.removeItem( testKey ); + return true; + } catch ( e ) { + return false; + } +} + +function sanitizeKey( name ) { + return name + .toLowerCase() + .trim() + .replace( /[^a-z0-9_-]/g, '_' ); +} + +function deserializeEntry( serialized ) { + try { + const payload = JSON.parse( serialized ); + + return { + data: payload.data, + expires: payload.expires || 0, + }; + } catch ( e ) { + return null; + } +} + +function serializeEntry( data, timeToLive ) { + const payload = { + data, + expires: calculateExpiration( timeToLive ), + }; + + return JSON.stringify( payload ); +} + +function calculateExpiration( timeToLive ) { + return timeToLive ? Date.now() + timeToLive * 1000 : 0; +} + +/** + * A reusable class for handling data storage in the browser's local storage, + * with optional expiration. + * + * Can be extended for module specific logic. + * + * @see GooglePaySession + */ +export class LocalStorage { + /** + * @type {string} + */ + #group = ''; + + /** + * @type {null|boolean} + */ + #canUseLocalStorage = null; + + /** + * @param {string} group - Group name for all storage keys managed by this instance. + */ + constructor( group ) { + this.#group = sanitizeKey( group ) + ':'; + this.#removeExpired(); + } + + /** + * Removes all items in the current group that have reached the expiry date. + */ + #removeExpired() { + if ( ! this.canUseLocalStorage ) { + return; + } + + Object.keys( localStorage ).forEach( ( key ) => { + if ( ! key.startsWith( this.#group ) ) { + return; + } + + const entry = deserializeEntry( localStorage.getItem( key ) ); + if ( entry && entry.expires > 0 && entry.expires < Date.now() ) { + localStorage.removeItem( key ); + } + } ); + } + + /** + * Sanitizes the given entry name and adds the group prefix. + * + * @throws {Error} If the name is empty after sanitization. + * @param {string} name - Entry name. + * @return {string} Prefixed and sanitized entry name. + */ + #entryKey( name ) { + const sanitizedName = sanitizeKey( name ); + + if ( sanitizedName.length === 0 ) { + throw new Error( 'Name cannot be empty after sanitization' ); + } + + return `${ this.#group }${ sanitizedName }`; + } + + /** + * Indicates, whether localStorage is available. + * + * @return {boolean} True means the localStorage API is available. + */ + get canUseLocalStorage() { + if ( null === this.#canUseLocalStorage ) { + this.#canUseLocalStorage = checkLocalStorageAvailability(); + } + + return this.#canUseLocalStorage; + } + + /** + * Stores data in the browser's local storage, with an optional timeout. + * + * @param {string} name - Name of the item in the storage. + * @param {any} data - The data to store. + * @param {number} [timeToLive=0] - Lifespan in seconds. 0 means the data won't expire. + * @throws {Error} If local storage is not available. + */ + set( name, data, timeToLive = 0 ) { + if ( ! this.canUseLocalStorage ) { + throw new Error( 'Local storage is not available' ); + } + + const entry = serializeEntry( data, timeToLive ); + const entryKey = this.#entryKey( name ); + + localStorage.setItem( entryKey, entry ); + } + + /** + * Retrieves previously stored data from the browser's local storage. + * + * @param {string} name - Name of the stored item. + * @return {any|null} The stored data, or null when no valid entry is found or it has expired. + * @throws {Error} If local storage is not available. + */ + get( name ) { + if ( ! this.canUseLocalStorage ) { + throw new Error( 'Local storage is not available' ); + } + + const itemKey = this.#entryKey( name ); + const entry = deserializeEntry( localStorage.getItem( itemKey ) ); + + if ( ! entry ) { + return null; + } + + return entry.data; + } + + /** + * Removes the specified entry from the browser's local storage. + * + * @param {string} name - Name of the stored item. + * @throws {Error} If local storage is not available. + */ + clear( name ) { + if ( ! this.canUseLocalStorage ) { + throw new Error( 'Local storage is not available' ); + } + + const itemKey = this.#entryKey( name ); + localStorage.removeItem( itemKey ); + } +} diff --git a/modules/ppcp-googlepay/resources/js/Helper/GooglePayStorage.js b/modules/ppcp-googlepay/resources/js/Helper/GooglePayStorage.js new file mode 100644 index 000000000..faa2520e5 --- /dev/null +++ b/modules/ppcp-googlepay/resources/js/Helper/GooglePayStorage.js @@ -0,0 +1,31 @@ +import { LocalStorage } from '../../../../ppcp-button/resources/js/modules/Helper/LocalStorage'; + +export class GooglePayStorage extends LocalStorage { + static PAYER = 'payer'; + static PAYER_TTL = 900; // 15 minutes in seconds + + constructor() { + super( 'ppcp-googlepay' ); + } + + getPayer() { + return this.get( GooglePayStorage.PAYER ); + } + + setPayer( data ) { + /* + * The payer details are deleted on successful checkout, or after the TTL is reached. + * This helps to remove stale data from the browser, in case the customer chooses to + * use a different method to complete the purchase. + */ + this.set( GooglePayStorage.PAYER, data, GooglePayStorage.PAYER_TTL ); + } + + clearPayer() { + this.clear( GooglePayStorage.PAYER ); + } +} + +const moduleStorage = new GooglePayStorage(); + +export default moduleStorage; From 63b505590326c10174c0e0c54db12e82cb57b33d Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 20 Aug 2024 14:14:30 +0200 Subject: [PATCH 045/134] =?UTF-8?q?=F0=9F=92=A1=20Document=20payment=20wor?= =?UTF-8?q?kflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OnApproveHandler/onApproveForContinue.js | 16 ++++++++++++---- .../resources/js/GooglepayButton.js | 9 +++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue.js b/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue.js index c60c163fd..0d699c170 100644 --- a/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue.js +++ b/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue.js @@ -18,17 +18,25 @@ const onApprove = ( context, errorHandler ) => { .then( ( res ) => { return res.json(); } ) - .then( ( data ) => { - if ( ! data.success ) { + .then( ( approveData ) => { + if ( ! approveData.success ) { errorHandler.genericError(); return actions.restart().catch( ( err ) => { errorHandler.genericError(); } ); } - const orderReceivedUrl = data.data?.order_received_url; + const orderReceivedUrl = approveData.data?.order_received_url; - location.href = orderReceivedUrl + /** + * Notice how this step initiates a redirect to a new page using a plain + * URL as new location. This process does not send any details about the + * approved order or billed customer. + * Also, due to the redirect starting _instantly_ there should be no other + * logic scheduled after calling `await onApprove()`; + */ + + window.location.href = orderReceivedUrl ? orderReceivedUrl : context.config.redirect; } ); diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index d8a910f34..a68e22f4a 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -587,6 +587,14 @@ class GooglepayButton extends PaymentButton { return 'APPROVED' === confirmOrderResponse?.status; }; + /** + * This approval mainly confirms that the orderID is valid. + * + * It's still needed because this handler redirects to the checkout page if the server-side + * approval was successful. + * + * @param {string} orderID + */ const approveOrderServerSide = async ( orderID ) => { let isApproved = true; @@ -625,6 +633,7 @@ class GooglepayButton extends PaymentButton { return; } + // This must be the last step in the process, as it initiates a redirect. const success = await approveOrderServerSide( id ); if ( success ) { From a51748f805416b51828c38f6600b38401d75dd7e Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 20 Aug 2024 14:18:30 +0200 Subject: [PATCH 046/134] =?UTF-8?q?=F0=9F=92=A1=20Improve=20comments=20in?= =?UTF-8?q?=20PayerData=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/modules/Helper/PayerData.js | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js index 1f97309c1..59af8dc85 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js +++ b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js @@ -10,30 +10,30 @@ * Postal address details. * * @typedef {Object} AddressDetails - * @property {?string} country_code - Country code (2-letter). - * @property {?string} address_line_1 - Address details, line 1 (street, house number). - * @property {?string} address_line_2 - Address details, line 2. - * @property {?string} admin_area_1 - State or region. - * @property {?string} admin_area_2 - State or region. - * @property {?string} postal_code - Zip code. + * @property {undefined|string} country_code - Country code (2-letter). + * @property {undefined|string} address_line_1 - Address details, line 1 (street, house number). + * @property {undefined|string} address_line_2 - Address details, line 2. + * @property {undefined|string} admin_area_1 - State or region. + * @property {undefined|string} admin_area_2 - State or region. + * @property {undefined|string} postal_code - Zip code. */ /** * Phone details. * * @typedef {Object} PhoneDetails - * @property {?string} phone_type - Type, usually 'HOME' - * @property {?{national_number: string}} phone_number - Phone number details. + * @property {undefined|string} phone_type - Type, usually 'HOME' + * @property {undefined|{national_number: string}} phone_number - Phone number details. */ /** * Payer details. * * @typedef {Object} PayerDetails - * @property {?string} email_address - Email address for billing communication. - * @property {?PhoneDetails} phone - Phone number for billing communication. - * @property {?NameDetails} name - Payer's name. - * @property {?AddressDetails} address - Postal billing address. + * @property {undefined|string} email_address - Email address for billing communication. + * @property {undefined|PhoneDetails} phone - Phone number for billing communication. + * @property {undefined|NameDetails} name - Payer's name. + * @property {undefined|AddressDetails} address - Postal billing address. */ // Map checkout fields to PayerData object properties. @@ -55,7 +55,14 @@ const FIELD_MAP = { * * @return {?PayerDetails} Full billing details, or null on failure. */ -export const payerData = () => { +export function payerData() { + /** + * PayPalCommerceGateway.payer can be set from server-side or via JS: + * - Server-side: Set by PHP when a WC customer is known. + * - Dynamic JS: When a payment method provided billing data. + * + * @see {setPayerData} + */ const payer = window.PayPalCommerceGateway?.payer; if ( ! payer ) { return null; @@ -104,18 +111,20 @@ export const payerData = () => { } return data; -}; +} /** * Updates the DOM with specific payer details. * + * Used by payment method callbacks that provide dedicated billing details, like Google Pay. + * Note: This code only works on classic checkout + * * @param {PayerDetails} newData - New payer details. - * @param {boolean} [overwriteExisting=false] - If set to true, all provided values will replace existing details. If false, or omitted, only undefined fields are updated. + * @param {boolean} [overwriteExisting=false] - If set to true, all provided values will + * replace existing details. If false, or omitted, + * only undefined fields are updated. */ -export const setPayerData = ( newData, overwriteExisting = false ) => { - // TODO: Check if we can add some kind of "filter" to allow customization of the data. - // Or add JS flags like "onlyUpdateMissing". - +export function setPayerData( newData, overwriteExisting = false ) { const setValue = ( path, field, value ) => { if ( null === value || undefined === value || ! field ) { return; @@ -136,4 +145,4 @@ export const setPayerData = ( newData, overwriteExisting = false ) => { setValue( path, element, value ); } ); -}; +} From c48c94e09d7030d86a4dfc6b3afc1fad25cd6596 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 20 Aug 2024 14:19:41 +0200 Subject: [PATCH 047/134] =?UTF-8?q?=E2=9C=A8=20New=20CheckoutBootstrap=20f?= =?UTF-8?q?or=20GooglePay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new module uses previously stored payer details to populate the checkout form on the classic checkout page. --- .../js/ContextBootstrap/CheckoutBootstrap.js | 64 +++++++++++++++++++ .../resources/js/GooglepayButton.js | 43 +++++++------ modules/ppcp-googlepay/resources/js/boot.js | 18 ++++-- 3 files changed, 101 insertions(+), 24 deletions(-) create mode 100644 modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js diff --git a/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js b/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js new file mode 100644 index 000000000..b5e0c1a48 --- /dev/null +++ b/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js @@ -0,0 +1,64 @@ +import { GooglePayStorage } from '../Helper/GooglePayStorage'; +import { setPayerData } from '../../../../ppcp-button/resources/js/modules/Helper/PayerData'; + +const CHECKOUT_FORM_SELECTOR = 'form.woocommerce-checkout'; + +export class CheckoutBootstrap { + /** + * @type {GooglePayStorage} + */ + #storage; + + /** + * @type {null|HTMLFormElement} + */ + #checkoutForm = null; + + constructor( storage ) { + this.#storage = storage; + + this.onFormSubmit = this.onFormSubmit.bind( this ); + } + + /** + * Returns the WooCommerce checkout form element. + * + * @return {HTMLFormElement|null} The form, or null if not a checkout page. + */ + get checkoutForm() { + if ( null === this.#checkoutForm ) { + this.#checkoutForm = document.querySelector( + CHECKOUT_FORM_SELECTOR + ); + } + + return this.#checkoutForm; + } + + /** + * Indicates, if the current page contains a checkout form. + * + * @return {boolean} True, if a checkout form is present. + */ + get isPageWithCheckoutForm() { + return this.checkoutForm instanceof HTMLElement; + } + + init() { + if ( ! this.isPageWithCheckoutForm ) { + return; + } + + const billingData = this.#storage.getPayer(); + + if ( billingData ) { + setPayerData( billingData ); + + this.checkoutForm.addEventListener( 'submit', this.onFormSubmit ); + } + } + + onFormSubmit() { + this.#storage.clearPayer(); + } +} diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index a68e22f4a..26acd0139 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -7,6 +7,7 @@ import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/Wi import UpdatePaymentData from './Helper/UpdatePaymentData'; import { PaymentMethods } from '../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState'; import { setPayerData } from '../../../ppcp-button/resources/js/modules/Helper/PayerData'; +import moduleStorage from './Helper/GooglePayStorage'; /** * Plugin-specific styling. @@ -74,6 +75,26 @@ import { setPayerData } from '../../../ppcp-button/resources/js/modules/Helper/P * Google Pay payment sheet. */ +function payerDataFromPaymentResponse( response ) { + const raw = response?.paymentMethodData?.info?.billingAddress; + + return { + email_address: response?.email, + name: { + given_name: raw.name.split( ' ' )[ 0 ], // Assuming first name is the first part + surname: raw.name.split( ' ' ).slice( 1 ).join( ' ' ), // Assuming last name is the rest + }, + address: { + country_code: raw.countryCode, + address_line_1: raw.address1, + address_line_2: raw.address2, + admin_area_1: raw.administrativeArea, + admin_area_2: raw.locality, + postal_code: raw.postalCode, + }, + }; +} + class GooglepayButton extends PaymentButton { /** * @inheritDoc @@ -643,30 +664,16 @@ class GooglepayButton extends PaymentButton { } }; - const propagatePayerDataToForm = () => { - const raw = paymentData?.paymentMethodData?.info?.billingAddress; - const payer = { - email_address: paymentData?.email, - name: { - given_name: raw.name.split( ' ' )[ 0 ], // Assuming first name is the first part - surname: raw.name.split( ' ' ).slice( 1 ).join( ' ' ), // Assuming last name is the rest - }, - address: { - country_code: raw.countryCode, - address_line_1: raw.address1, - address_line_2: raw.address2, - admin_area_1: raw.administrativeArea, - admin_area_2: raw.locality, - postal_code: raw.postalCode, - }, - }; + const addBillingDataToSession = () => { + const payer = payerDataFromPaymentResponse( paymentData ); + moduleStorage.setPayer( payer ); setPayerData( payer ); }; return new Promise( async ( resolve ) => { try { - propagatePayerDataToForm(); + addBillingDataToSession(); await processPaymentPromise( resolve ); } catch ( err ) { resolve( paymentError( err.message ) ); diff --git a/modules/ppcp-googlepay/resources/js/boot.js b/modules/ppcp-googlepay/resources/js/boot.js index 99dd414f5..3071998a9 100644 --- a/modules/ppcp-googlepay/resources/js/boot.js +++ b/modules/ppcp-googlepay/resources/js/boot.js @@ -2,13 +2,23 @@ import { loadCustomScript } from '@paypal/paypal-js'; import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading'; import GooglepayManager from './GooglepayManager'; import { setupButtonEvents } from '../../../ppcp-button/resources/js/modules/Helper/ButtonRefreshHelper'; +import { CheckoutBootstrap } from './ContextBootstrap/CheckoutBootstrap'; +import moduleStorage from './Helper/GooglePayStorage'; + +( function ( { buttonConfig, ppcpConfig } ) { + const context = ppcpConfig.context; -( function ( { buttonConfig, ppcpConfig, jQuery } ) { let manager; const bootstrap = function () { manager = new GooglepayManager( buttonConfig, ppcpConfig ); manager.init(); + + if ( 'continuation' === context || 'checkout' === context ) { + const checkoutBootstap = new CheckoutBootstrap( moduleStorage ); + + checkoutBootstap.init(); + } }; setupButtonEvents( function () { @@ -18,10 +28,7 @@ import { setupButtonEvents } from '../../../ppcp-button/resources/js/modules/Hel } ); document.addEventListener( 'DOMContentLoaded', () => { - if ( - typeof buttonConfig === 'undefined' || - typeof ppcpConfig === 'undefined' - ) { + if ( ! buttonConfig || ! ppcpConfig ) { // No PayPal buttons present on this page. return; } @@ -52,5 +59,4 @@ import { setupButtonEvents } from '../../../ppcp-button/resources/js/modules/Hel } )( { buttonConfig: window.wc_ppcp_googlepay, ppcpConfig: window.PayPalCommerceGateway, - jQuery: window.jQuery, } ); From 97379628d441602c3ca3425b7f6df253765b09f8 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 20 Aug 2024 15:37:26 +0200 Subject: [PATCH 048/134] =?UTF-8?q?=E2=9C=A8=20Send=20payer=20details=20wi?= =?UTF-8?q?th=20order=20approval=20request?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First step to integrate payer details in the payment flow without final confirmation. --- .../resources/js/modules/Helper/PayerData.js | 24 +++++++++++++++++++ .../OnApproveHandler/onApproveForContinue.js | 23 +++++++++++------- .../resources/js/GooglepayButton.js | 6 ++--- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js index 59af8dc85..358b1587f 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js +++ b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js @@ -145,4 +145,28 @@ export function setPayerData( newData, overwriteExisting = false ) { setValue( path, element, value ); } ); + + /* + * Persist the payer details to the global JS object, to make it available in other modules + * via tha `payerData()` accessor. + */ + window.PayPalCommerceGateway.payer = + window.PayPalCommerceGateway.payer || {}; + const currentPayerData = payerData(); + + if ( currentPayerData ) { + Object.entries( newData ).forEach( ( [ key, value ] ) => { + if ( + overwriteExisting || + null !== currentPayerData[ key ] || + undefined !== currentPayerData[ key ] + ) { + currentPayerData[ key ] = value; + } + } ); + + window.PayPalCommerceGateway.payer = currentPayerData; + } else { + window.PayPalCommerceGateway.payer = newData; + } } diff --git a/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue.js b/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue.js index 0d699c170..d492802f1 100644 --- a/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue.js +++ b/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue.js @@ -1,19 +1,26 @@ const onApprove = ( context, errorHandler ) => { return ( data, actions ) => { + const canCreateOrder = + ! context.config.vaultingEnabled || data.paymentSource !== 'venmo'; + + const payload = { + nonce: context.config.ajax.approve_order.nonce, + order_id: data.orderID, + funding_source: window.ppcpFundingSource, + should_create_wc_order: canCreateOrder, + }; + + if ( canCreateOrder && data.payer ) { + payload.payer = data.payer; + } + return fetch( context.config.ajax.approve_order.endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'same-origin', - body: JSON.stringify( { - nonce: context.config.ajax.approve_order.nonce, - order_id: data.orderID, - funding_source: window.ppcpFundingSource, - should_create_wc_order: - ! context.config.vaultingEnabled || - data.paymentSource !== 'venmo', - } ), + body: JSON.stringify( payload ), } ) .then( ( res ) => { return res.json(); diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 26acd0139..e9ca1bcc8 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -583,6 +583,8 @@ class GooglepayButton extends PaymentButton { async processPayment( paymentData ) { this.logGroup( 'processPayment' ); + const payer = payerDataFromPaymentResponse( paymentData ); + const paymentError = ( reason ) => { this.error( reason ); @@ -622,7 +624,7 @@ class GooglepayButton extends PaymentButton { this.log( 'approveOrder', orderID ); await this.contextHandler.approveOrder( - { orderID }, + { orderID, payer }, { restart: () => new Promise( ( resolve ) => { @@ -665,8 +667,6 @@ class GooglepayButton extends PaymentButton { }; const addBillingDataToSession = () => { - const payer = payerDataFromPaymentResponse( paymentData ); - moduleStorage.setPayer( payer ); setPayerData( payer ); }; From 915754799371e7e919289e4a547be8196377df55 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 21 Aug 2024 13:51:40 +0200 Subject: [PATCH 049/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Improve=20PayerDat?= =?UTF-8?q?a=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/modules/Helper/PayerData.js | 212 ++++++++++-------- 1 file changed, 118 insertions(+), 94 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js index 358b1587f..6b899bc9e 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js +++ b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js @@ -2,38 +2,38 @@ * Name details. * * @typedef {Object} NameDetails - * @property {?string} given_name - First name, e.g. "John". - * @property {?string} surname - Last name, e.g. "Doe". + * @property {string} [given_name] - First name, e.g. "John". + * @property {string} [surname] - Last name, e.g. "Doe". */ /** * Postal address details. * * @typedef {Object} AddressDetails - * @property {undefined|string} country_code - Country code (2-letter). - * @property {undefined|string} address_line_1 - Address details, line 1 (street, house number). - * @property {undefined|string} address_line_2 - Address details, line 2. - * @property {undefined|string} admin_area_1 - State or region. - * @property {undefined|string} admin_area_2 - State or region. - * @property {undefined|string} postal_code - Zip code. + * @property {string} [country_code] - Country code (2-letter). + * @property {string} [address_line_1] - Address details, line 1 (street, house number). + * @property {string} [address_line_2] - Address details, line 2. + * @property {string} [admin_area_1] - State or region. + * @property {string} [admin_area_2] - State or region. + * @property {string} [postal_code] - Zip code. */ /** * Phone details. * * @typedef {Object} PhoneDetails - * @property {undefined|string} phone_type - Type, usually 'HOME' - * @property {undefined|{national_number: string}} phone_number - Phone number details. + * @property {string} [phone_type] - Type, usually 'HOME' + * @property {{national_number: string}} [phone_number] - Phone number details. */ /** * Payer details. * * @typedef {Object} PayerDetails - * @property {undefined|string} email_address - Email address for billing communication. - * @property {undefined|PhoneDetails} phone - Phone number for billing communication. - * @property {undefined|NameDetails} name - Payer's name. - * @property {undefined|AddressDetails} address - Postal billing address. + * @property {string} [email_address] - Email address for billing communication. + * @property {PhoneDetails} [phone] - Phone number for billing communication. + * @property {NameDetails} [name] - Payer's name. + * @property {AddressDetails} [address] - Postal billing address. */ // Map checkout fields to PayerData object properties. @@ -50,123 +50,147 @@ const FIELD_MAP = { '#billing_phone': [ 'phone' ], }; -/** - * Returns billing details from the checkout form or global JS object. - * - * @return {?PayerDetails} Full billing details, or null on failure. - */ -export function payerData() { - /** - * PayPalCommerceGateway.payer can be set from server-side or via JS: - * - Server-side: Set by PHP when a WC customer is known. - * - Dynamic JS: When a payment method provided billing data. - * - * @see {setPayerData} - */ - const payer = window.PayPalCommerceGateway?.payer; - if ( ! payer ) { - return null; - } +function normalizePayerDetails( details ) { + return { + email_address: details.email_address, + phone: details.phone, + name: { + surname: details.name?.surname, + given_name: details.name?.given_name, + }, + address: { + country_code: details.address?.country_code, + address_line_1: details.address?.address_line_1, + address_line_2: details.address?.address_line_2, + admin_area_1: details.address?.admin_area_1, + admin_area_2: details.address?.admin_area_2, + postal_code: details.address?.postal_code, + }, + }; +} +function mergePayerDetails( firstPayer, secondPayer ) { + const mergeNestedObjects = ( target, source ) => { + for ( const [ key, value ] of Object.entries( source ) ) { + if ( null !== value && undefined !== value ) { + if ( 'object' === typeof value ) { + target[ key ] = mergeNestedObjects( + target[ key ] || {}, + value + ); + } else { + target[ key ] = value; + } + } + } + return target; + }; + + return mergeNestedObjects( + normalizePayerDetails( firstPayer ), + normalizePayerDetails( secondPayer ) + ); +} + +function getCheckoutBillingDetails() { const getElementValue = ( selector ) => document.querySelector( selector )?.value; - // Initialize data with existing payer values. - const data = { - email_address: payer.email_address, - phone: payer.phone, - name: { - surname: payer.name?.surname, - given_name: payer.name?.given_name, - }, - address: { - country_code: payer.address?.country_code, - address_line_1: payer.address?.address_line_1, - address_line_2: payer.address?.address_line_2, - admin_area_1: payer.address?.admin_area_1, - admin_area_2: payer.address?.admin_area_2, - postal_code: payer.address?.postal_code, - }, + const setNestedValue = ( obj, path, value ) => { + let current = obj; + for ( let i = 0; i < path.length - 1; i++ ) { + current = current[ path[ i ] ] = current[ path[ i ] ] || {}; + } + current[ path[ path.length - 1 ] ] = value; }; - // Update data with DOM values where they exist. + const data = {}; + Object.entries( FIELD_MAP ).forEach( ( [ selector, path ] ) => { const value = getElementValue( selector ); if ( value ) { - let current = data; - path.slice( 0, -1 ).forEach( ( key ) => { - current = current[ key ] = current[ key ] || {}; - } ); - current[ path[ path.length - 1 ] ] = value; + setNestedValue( data, path, value ); } } ); - // Handle phone separately due to its nested structure. - const phoneNumber = data.phone; - if ( phoneNumber && typeof phoneNumber === 'string' ) { + if ( data.phone && 'string' === typeof data.phone ) { data.phone = { phone_type: 'HOME', - phone_number: { national_number: phoneNumber }, + phone_number: { national_number: data.phone }, }; } return data; } -/** - * Updates the DOM with specific payer details. - * - * Used by payment method callbacks that provide dedicated billing details, like Google Pay. - * Note: This code only works on classic checkout - * - * @param {PayerDetails} newData - New payer details. - * @param {boolean} [overwriteExisting=false] - If set to true, all provided values will - * replace existing details. If false, or omitted, - * only undefined fields are updated. - */ -export function setPayerData( newData, overwriteExisting = false ) { +function setCheckoutBillingDetails( payer ) { const setValue = ( path, field, value ) => { if ( null === value || undefined === value || ! field ) { return; } - if ( path[ 0 ] === 'phone' && typeof value === 'object' ) { + if ( 'phone' === path[ 0 ] && 'object' === typeof value ) { value = value.phone_number?.national_number; } - if ( overwriteExisting || ! field.value ) { - field.value = value; - } + field.value = value; }; + const getNestedValue = ( obj, path ) => + path.reduce( ( current, key ) => current?.[ key ], obj ); + Object.entries( FIELD_MAP ).forEach( ( [ selector, path ] ) => { - const value = path.reduce( ( obj, key ) => obj?.[ key ], newData ); + const value = getNestedValue( payer, path ); const element = document.querySelector( selector ); setValue( path, element, value ); } ); +} - /* - * Persist the payer details to the global JS object, to make it available in other modules - * via tha `payerData()` accessor. - */ - window.PayPalCommerceGateway.payer = - window.PayPalCommerceGateway.payer || {}; - const currentPayerData = payerData(); +export function getWooCommerceCustomerDetails() { + // Populated on server-side with details about the current WooCommerce customer. + return window.PayPalCommerceGateway?.payer ?? null; +} - if ( currentPayerData ) { - Object.entries( newData ).forEach( ( [ key, value ] ) => { - if ( - overwriteExisting || - null !== currentPayerData[ key ] || - undefined !== currentPayerData[ key ] - ) { - currentPayerData[ key ] = value; - } - } ); +export function getSessionCustomerDetails() { + // Populated by JS via `setSessionCustomerDetails()` + return window.PayPalCommerceGateway?.sessionPayer ?? null; +} - window.PayPalCommerceGateway.payer = currentPayerData; - } else { - window.PayPalCommerceGateway.payer = newData; +/** + * Stores customer details in the current JS context for use in the same request. + * Details that are set are not persisted during navigation. + * + * @param {unknown} details - New payer details + */ +export function setSessionCustomerDetails( details ) { + if ( details && 'object' === typeof details ) { + window.PayPalCommerceGateway.sessionPayer = + normalizePayerDetails( details ); + } +} + +export function payerData() { + const payer = + getWooCommerceCustomerDetails() ?? getSessionCustomerDetails(); + + if ( ! payer ) { + return null; + } + + const formData = getCheckoutBillingDetails(); + + if ( formData ) { + return mergePayerDetails( payer, formData ); + } + + return normalizePayerDetails( payer ); +} + +export function setPayerData( newData, updateCheckout = false ) { + setSessionCustomerDetails( newData ); + + if ( updateCheckout ) { + setCheckoutBillingDetails( newData ); } } From eba92e6b81c48b1745d4ffbf68623ea878f976e1 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 21 Aug 2024 13:52:11 +0200 Subject: [PATCH 050/134] =?UTF-8?q?=E2=9C=A8=20Detect=20logged=20in=20cust?= =?UTF-8?q?omer=20in=20checkout=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../js/ContextBootstrap/CheckoutBootstrap.js | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js b/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js index b5e0c1a48..d913b0b3f 100644 --- a/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js +++ b/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js @@ -1,5 +1,8 @@ import { GooglePayStorage } from '../Helper/GooglePayStorage'; -import { setPayerData } from '../../../../ppcp-button/resources/js/modules/Helper/PayerData'; +import { + getWooCommerceCustomerDetails, + setPayerData, +} from '../../../../ppcp-button/resources/js/modules/Helper/PayerData'; const CHECKOUT_FORM_SELECTOR = 'form.woocommerce-checkout'; @@ -49,16 +52,29 @@ export class CheckoutBootstrap { return; } + this.#populateCheckoutFields(); + } + + #populateCheckoutFields() { + const loggedInData = getWooCommerceCustomerDetails(); + + // If customer is logged in, we use the details from the customer profile. + if ( loggedInData ) { + return; + } + const billingData = this.#storage.getPayer(); if ( billingData ) { setPayerData( billingData ); - this.checkoutForm.addEventListener( 'submit', this.onFormSubmit ); + this.checkoutForm.addEventListener( 'submit', () => + this.#onFormSubmit() + ); } } - onFormSubmit() { + #onFormSubmit() { this.#storage.clearPayer(); } } From 734951adcb2d5250d5c768d29d6eb34936193350 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 21 Aug 2024 14:21:45 +0200 Subject: [PATCH 051/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Minor=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/modules/Helper/PayerData.js | 28 +++++++++---------- .../js/ContextBootstrap/CheckoutBootstrap.js | 17 ++++++----- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js index 6b899bc9e..df13ef92f 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js +++ b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js @@ -149,12 +149,12 @@ function setCheckoutBillingDetails( payer ) { export function getWooCommerceCustomerDetails() { // Populated on server-side with details about the current WooCommerce customer. - return window.PayPalCommerceGateway?.payer ?? null; + return window.PayPalCommerceGateway?.payer; } -export function getSessionCustomerDetails() { - // Populated by JS via `setSessionCustomerDetails()` - return window.PayPalCommerceGateway?.sessionPayer ?? null; +export function getSessionBillingDetails() { + // Populated by JS via `setSessionBillingDetails()` + return window.PayPalCommerceGateway?.tempPayer; } /** @@ -163,16 +163,16 @@ export function getSessionCustomerDetails() { * * @param {unknown} details - New payer details */ -export function setSessionCustomerDetails( details ) { - if ( details && 'object' === typeof details ) { - window.PayPalCommerceGateway.sessionPayer = - normalizePayerDetails( details ); +export function setSessionBillingDetails( details ) { + if ( ! details || 'object' !== typeof details ) { + return; } + + window.PayPalCommerceGateway.tempPayer = normalizePayerDetails( details ); } export function payerData() { - const payer = - getWooCommerceCustomerDetails() ?? getSessionCustomerDetails(); + const payer = getWooCommerceCustomerDetails() ?? getSessionBillingDetails(); if ( ! payer ) { return null; @@ -187,10 +187,10 @@ export function payerData() { return normalizePayerDetails( payer ); } -export function setPayerData( newData, updateCheckout = false ) { - setSessionCustomerDetails( newData ); +export function setPayerData( payerDetails, updateCheckoutForm = false ) { + setSessionBillingDetails( payerDetails ); - if ( updateCheckout ) { - setCheckoutBillingDetails( newData ); + if ( updateCheckoutForm ) { + setCheckoutBillingDetails( payerDetails ); } } diff --git a/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js b/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js index d913b0b3f..9e1c30e9f 100644 --- a/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js +++ b/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js @@ -19,8 +19,6 @@ export class CheckoutBootstrap { constructor( storage ) { this.#storage = storage; - - this.onFormSubmit = this.onFormSubmit.bind( this ); } /** @@ -44,7 +42,7 @@ export class CheckoutBootstrap { * @return {boolean} True, if a checkout form is present. */ get isPageWithCheckoutForm() { - return this.checkoutForm instanceof HTMLElement; + return null !== this.checkoutForm; } init() { @@ -65,13 +63,14 @@ export class CheckoutBootstrap { const billingData = this.#storage.getPayer(); - if ( billingData ) { - setPayerData( billingData ); - - this.checkoutForm.addEventListener( 'submit', () => - this.#onFormSubmit() - ); + if ( ! billingData ) { + return; } + + setPayerData( billingData, true ); + this.checkoutForm.addEventListener( 'submit', () => + this.#onFormSubmit() + ); } #onFormSubmit() { From b4cd6bb121e0041c1a91d57bcd840309d89deb04 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Fri, 23 Aug 2024 11:52:00 +0200 Subject: [PATCH 052/134] =?UTF-8?q?=F0=9F=90=9B=20Fix=20critical=20Google?= =?UTF-8?q?=20Pay=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/GooglepayButton.js | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index f6ceafc61..6b67dab72 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -515,7 +515,9 @@ class GooglepayButton extends PaymentButton { ) ) { paymentDataRequestUpdate.newShippingOptionParameters = - updatedData.shipping_options; + this.sanitizeShippingOptions( + updatedData.shipping_options + ); } if ( updatedData.total && hasRealCart ) { @@ -541,6 +543,30 @@ class GooglepayButton extends PaymentButton { } ); } + /** + * Google Pay throws an error, when the shippingOptions entries contain + * custom properties. This function strips unsupported properties from the + * provided ajax response. + * + * @param {Object} responseData Data returned from the ajax endpoint. + * @return {Object} Sanitized object. + */ + sanitizeShippingOptions( responseData ) { + const cleanOptions = []; + + responseData.shippingOptions.forEach( ( item ) => { + cleanOptions.push( { + id: item.id, + label: item.label, + description: item.description, + } ); + } ); + + responseData.shippingOptions = cleanOptions; + + return { ...responseData, shippingOptions: cleanOptions }; + } + /** * Returns the shipping costs as numeric value. * From c76fcb91ba6f90c620560cfc8cf5b5760008415f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20Mei=C3=9Felbach?= Date: Fri, 23 Aug 2024 15:04:28 +0200 Subject: [PATCH 053/134] Remove (apparently) dead getKey methods --- modules/ppcp-axo/src/AxoModule.php | 8 -------- modules/ppcp-blocks/src/BlocksModule.php | 9 --------- modules/ppcp-paylater-block/src/PayLaterBlockModule.php | 8 -------- .../src/PayLaterConfiguratorModule.php | 8 -------- .../src/PayLaterWCBlocksModule.php | 8 -------- 5 files changed, 41 deletions(-) diff --git a/modules/ppcp-axo/src/AxoModule.php b/modules/ppcp-axo/src/AxoModule.php index cd4ad7639..15a685c0f 100644 --- a/modules/ppcp-axo/src/AxoModule.php +++ b/modules/ppcp-axo/src/AxoModule.php @@ -325,14 +325,6 @@ class AxoModule implements ServiceModule, ExtendingModule, ExecutableModule { return $localized_script_data; } - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { - } - /** * Condition to evaluate if Credit Card gateway should be hidden. * diff --git a/modules/ppcp-blocks/src/BlocksModule.php b/modules/ppcp-blocks/src/BlocksModule.php index 3e7b5503e..d8363e415 100644 --- a/modules/ppcp-blocks/src/BlocksModule.php +++ b/modules/ppcp-blocks/src/BlocksModule.php @@ -127,13 +127,4 @@ class BlocksModule implements ServiceModule, ExtendingModule, ExecutableModule { ); return true; } - - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { - - } } diff --git a/modules/ppcp-paylater-block/src/PayLaterBlockModule.php b/modules/ppcp-paylater-block/src/PayLaterBlockModule.php index 2b9dd0810..896d98027 100644 --- a/modules/ppcp-paylater-block/src/PayLaterBlockModule.php +++ b/modules/ppcp-paylater-block/src/PayLaterBlockModule.php @@ -129,12 +129,4 @@ class PayLaterBlockModule implements ServiceModule, ExtendingModule, ExecutableM return true; } - - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { - } } diff --git a/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php b/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php index 2178690f1..9bb757401 100644 --- a/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php +++ b/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php @@ -150,12 +150,4 @@ class PayLaterConfiguratorModule implements ServiceModule, ExtendingModule, Exec return true; } - - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { - } } diff --git a/modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php b/modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php index 70e6afe88..5c811d778 100644 --- a/modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php +++ b/modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php @@ -282,12 +282,4 @@ class PayLaterWCBlocksModule implements ModuleInterface { ); } } - - /** - * Returns the key for the module. - * - * @return void - */ - public function getKey() { - } } From 41d13be3eacf9b31bcc6e0a93bf4f24468b9b38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20Mei=C3=9Felbach?= Date: Fri, 23 Aug 2024 15:16:31 +0200 Subject: [PATCH 054/134] Refactor PayLaterWCBlocksModule to Modularity --- .../src/PayLaterWCBlocksModule.php | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php b/modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php index 5c811d778..fe547ea17 100644 --- a/modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php +++ b/modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php @@ -11,19 +11,35 @@ namespace WooCommerce\PayPalCommerce\PayLaterWCBlocks; use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Factory\ConfigFactory; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; -use WooCommerce\PayPalCommerce\PayLaterWCBlocks\PayLaterWCBlocksUtils; /** * Class PayLaterWCBlocksModule */ -class PayLaterWCBlocksModule implements ModuleInterface { +class PayLaterWCBlocksModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; + + /** + * {@inheritDoc} + */ + public function services(): array { + return require __DIR__ . '/../services.php'; + } + + /** + * {@inheritDoc} + */ + public function extensions(): array { + return require __DIR__ . '/../extensions.php'; + } + /** * Returns whether the block module should be loaded. * @@ -75,22 +91,12 @@ class PayLaterWCBlocksModule implements ModuleInterface { /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); - } - - /** - * {@inheritDoc} - */ - public function run( ContainerInterface $c ): void { + public function run( ContainerInterface $c ): bool { $messages_apply = $c->get( 'button.helper.messages-apply' ); assert( $messages_apply instanceof MessagesApply ); if ( ! $messages_apply->for_country() ) { - return; + return true; } $settings = $c->get( 'wcgateway.settings' ); @@ -281,5 +287,6 @@ class PayLaterWCBlocksModule implements ModuleInterface { } ); } + return true; } } From 49150cec0cd7b82be5e7518db9f098b19202a931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20Mei=C3=9Felbach?= Date: Fri, 23 Aug 2024 15:46:09 +0200 Subject: [PATCH 055/134] Update lockfile --- composer.lock | 1298 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 880 insertions(+), 418 deletions(-) diff --git a/composer.lock b/composer.lock index 528b9224e..75c1a506e 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": "8d6d274f3742efb3f1278eee713257b4", + "content-hash": "32091557d24f28a797316afa4bf9c97c", "packages": [ { "name": "container-interop/service-provider", @@ -296,20 +296,20 @@ }, { "name": "psr/container", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=7.4.0" }, "type": "library", "autoload": { @@ -338,9 +338,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" + "source": "https://github.com/php-fig/container/tree/1.1.2" }, - "time": "2021-03-05T17:36:06+00:00" + "time": "2021-11-05T16:50:12+00:00" }, { "name": "psr/log", @@ -438,16 +438,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", "shasum": "" }, "require": { @@ -498,7 +498,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" }, "funding": [ { @@ -514,7 +514,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "wikimedia/composer-merge-plugin", @@ -979,30 +979,38 @@ }, { "name": "composer/pcre", - "version": "2.1.3", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "540af382c97b83c628227d5f87cf56466d476191" + "reference": "1637e067347a0c40bbb1e3cd786b20dcab556a81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/540af382c97b83c628227d5f87cf56466d476191", - "reference": "540af382c97b83c628227d5f87cf56466d476191", + "url": "https://api.github.com/repos/composer/pcre/zipball/1637e067347a0c40bbb1e3cd786b20dcab556a81", + "reference": "1637e067347a0c40bbb1e3cd786b20dcab556a81", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" }, "require-dev": { - "phpstan/phpstan": "^1.3", + "phpstan/phpstan": "^1.11.10", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" + "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.x-dev" + "dev-main": "3.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "autoload": { @@ -1030,7 +1038,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/2.1.3" + "source": "https://github.com/composer/pcre/tree/3.3.0" }, "funding": [ { @@ -1046,20 +1054,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T09:03:05+00:00" + "time": "2024-08-19T19:43:53+00:00" }, { "name": "composer/semver", - "version": "3.4.0", + "version": "3.4.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", "shasum": "" }, "require": { @@ -1111,7 +1119,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.0" + "source": "https://github.com/composer/semver/tree/3.4.2" }, "funding": [ { @@ -1127,7 +1135,7 @@ "type": "tidelift" } ], - "time": "2023-08-31T09:50:34+00:00" + "time": "2024-07-12T11:35:52+00:00" }, { "name": "composer/xdebug-handler", @@ -1327,30 +1335,30 @@ }, { "name": "dhii/containers", - "version": "v0.1.4", + "version": "v0.1.5", "source": { "type": "git", "url": "https://github.com/Dhii/containers.git", - "reference": "42ab24683183fa0dc155f26c6a470ef697bbdc9a" + "reference": "1568cb2def9dee213c5846c4618f9d6b2cebbdef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Dhii/containers/zipball/42ab24683183fa0dc155f26c6a470ef697bbdc9a", - "reference": "42ab24683183fa0dc155f26c6a470ef697bbdc9a", + "url": "https://api.github.com/repos/Dhii/containers/zipball/1568cb2def9dee213c5846c4618f9d6b2cebbdef", + "reference": "1568cb2def9dee213c5846c4618f9d6b2cebbdef", "shasum": "" }, "require": { "container-interop/service-provider": "^0.4", "dhii/collections-interface": "^0.3.0-alpha4", - "php": "^7.1 | ^8.0" + "php": "^7.4 | ^8.0" }, "require-dev": { "gmazzap/andrew": "^1.1", - "phpunit/phpunit": "^7.0 | ^8.0 | ^9.0", + "phpunit/phpunit": "^9.0", "psr/container": "^1.0", "psr/simple-cache": "^1.0", "slevomat/coding-standard": "^6.0", - "vimeo/psalm": "^4.0", + "vimeo/psalm": "^5.0", "wildwolf/psr-memory-cache": "^1.0" }, "type": "library", @@ -1381,9 +1389,9 @@ ], "support": { "issues": "https://github.com/Dhii/containers/issues", - "source": "https://github.com/Dhii/containers/tree/v0.1.4" + "source": "https://github.com/Dhii/containers/tree/v0.1.5" }, - "time": "2021-10-06T11:13:51+00:00" + "time": "2024-04-27T01:55:40+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -1422,6 +1430,53 @@ }, "time": "2019-12-04T15:06:13+00:00" }, + { + "name": "doctrine/deprecations", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + }, + "time": "2024-01-30T19:34:25+00:00" + }, { "name": "doctrine/instantiator", "version": "1.5.0", @@ -1595,24 +1650,24 @@ }, { "name": "graham-campbell/result-type", - "version": "v1.1.2", + "version": "v1.1.3", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862" + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862", - "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.2" + "phpoption/phpoption": "^1.9.3" }, "require-dev": { - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "autoload": { @@ -1641,7 +1696,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" }, "funding": [ { @@ -1653,7 +1708,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T22:16:48+00:00" + "time": "2024-07-20T21:45:45+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -1707,36 +1762,107 @@ "time": "2020-07-09T08:09:16+00:00" }, { - "name": "mockery/mockery", - "version": "1.3.6", + "name": "inpsyde/modularity", + "version": "1.8.0", "source": { "type": "git", - "url": "https://github.com/mockery/mockery.git", - "reference": "dc206df4fa314a50bbb81cf72239a305c5bbd5c0" + "url": "https://github.com/inpsyde/modularity.git", + "reference": "c6855a6d9c4ce6f090d031e820f176bddf2a0b1c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/dc206df4fa314a50bbb81cf72239a305c5bbd5c0", - "reference": "dc206df4fa314a50bbb81cf72239a305c5bbd5c0", + "url": "https://api.github.com/repos/inpsyde/modularity/zipball/c6855a6d9c4ce6f090d031e820f176bddf2a0b1c", + "reference": "c6855a6d9c4ce6f090d031e820f176bddf2a0b1c", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2", + "psr/container": "^1.1.0 || ^2" + }, + "require-dev": { + "brain/monkey": "^2.6.1", + "inpsyde/php-coding-standards": "^1", + "johnpbloch/wordpress-core": ">=5.8", + "mikey179/vfsstream": "^v1.6.10", + "php-stubs/wordpress-stubs": ">=5.8@stable", + "phpunit/phpunit": "^8.5.21 || ^9.6.7", + "vimeo/psalm": "^4.13.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Inpsyde\\Modularity\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Inpsyde GmbH", + "email": "hello@inpsyde.com", + "homepage": "https://inpsyde.com/", + "role": "Company" + }, + { + "name": "Christian Leucht", + "email": "c.leucht@inpsyde.com", + "role": "Developer" + }, + { + "name": "Giuseppe Mazzapica", + "email": "g.mazzapica@inpsyde.com", + "role": "Developer" + } + ], + "description": "Modular PSR-11 implementation for WordPress plugins, themes or libraries.", + "support": { + "issues": "https://github.com/inpsyde/modularity/issues", + "source": "https://github.com/inpsyde/modularity/tree/1.8.0" + }, + "time": "2024-05-14T06:07:35+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", "shasum": "" }, "require": { "hamcrest/hamcrest-php": "^2.0.1", "lib-pcre": ">=7.0", - "php": ">=5.6.0" + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^5.7.10|^6.5|^7.5|^8.5|^9.3" + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, "autoload": { - "psr-0": { - "Mockery": "library/" + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" } }, "notification-url": "https://packagist.org/downloads/", @@ -1747,12 +1873,20 @@ { "name": "Pádraic Brady", "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" + "homepage": "https://github.com/padraic", + "role": "Author" }, { "name": "Dave Marshall", "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "http://davedevelopment.co.uk" + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" } ], "description": "Mockery is a simple yet flexible PHP mock object framework", @@ -1770,23 +1904,26 @@ "testing" ], "support": { + "docs": "https://docs.mockery.io/", "issues": "https://github.com/mockery/mockery/issues", - "source": "https://github.com/mockery/mockery/tree/1.3.6" + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" }, - "time": "2022-09-07T15:05:49+00:00" + "time": "2024-05-16T03:13:13+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -1794,11 +1931,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -1824,7 +1962,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -1832,7 +1970,7 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "netresearch/jsonmapper", @@ -2114,16 +2252,16 @@ }, { "name": "php-stubs/woocommerce-stubs", - "version": "v8.9.0", + "version": "v8.9.1", "source": { "type": "git", "url": "https://github.com/php-stubs/woocommerce-stubs.git", - "reference": "2c0bb50a76a703206151fac3123faec6ba7d5879" + "reference": "2f5be3f363ff3d02b4e29404c7895d9d15fd3e73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/2c0bb50a76a703206151fac3123faec6ba7d5879", - "reference": "2c0bb50a76a703206151fac3123faec6ba7d5879", + "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/2f5be3f363ff3d02b4e29404c7895d9d15fd3e73", + "reference": "2f5be3f363ff3d02b4e29404c7895d9d15fd3e73", "shasum": "" }, "require": { @@ -2152,9 +2290,9 @@ ], "support": { "issues": "https://github.com/php-stubs/woocommerce-stubs/issues", - "source": "https://github.com/php-stubs/woocommerce-stubs/tree/v8.9.0" + "source": "https://github.com/php-stubs/woocommerce-stubs/tree/v8.9.1" }, - "time": "2024-05-14T16:07:36+00:00" + "time": "2024-05-21T11:47:54+00:00" }, { "name": "php-stubs/wordpress-stubs", @@ -2462,28 +2600,35 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", + "version": "5.4.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.1", "ext-filter": "*", - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" }, "type": "library", "extra": { @@ -2507,37 +2652,45 @@ }, { "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" + "email": "opensource@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" }, - "time": "2021-10-19T17:43:47+00:00" + "time": "2024-05-21T05:55:05+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.6.1", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" + "reference": "153ae662783729388a584b4361f2545e4d841e3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" }, "require-dev": { "ext-tokenizer": "*", - "psalm/phar": "^4.8" + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" }, "type": "library", "extra": { @@ -2563,22 +2716,22 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" }, - "time": "2022-03-15T21:29:03+00:00" + "time": "2024-02-23T11:10:43+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.2", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", "shasum": "" }, "require": { @@ -2586,13 +2739,13 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "1.9-dev" @@ -2628,7 +2781,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" }, "funding": [ { @@ -2640,44 +2793,95 @@ "type": "tidelift" } ], - "time": "2023-11-12T21:59:55+00:00" + "time": "2024-07-20T21:41:07+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "7.0.17", + "name": "phpstan/phpdoc-parser", + "version": "1.29.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66" + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", - "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fcaefacf2d5c417e928405b71b400d4ce10daaf4", + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.1" + }, + "time": "2024-05-31T08:52:43+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.32", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-xmlwriter": "*", - "php": ">=7.2", - "phpunit/php-file-iterator": "^2.0.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.1.3 || ^4.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^4.2.2", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1.3" + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^8.2.2" + "phpunit/phpunit": "^9.6" }, "suggest": { - "ext-xdebug": "^2.7.2" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "7.0-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -2705,7 +2909,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.17" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -2713,32 +2918,32 @@ "type": "github" } ], - "time": "2024-03-02T06:09:37+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "2.0.6", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "69deeb8664f611f156a924154985fbd4911eb36b" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/69deeb8664f611f156a924154985fbd4911eb36b", - "reference": "69deeb8664f611f156a924154985fbd4911eb36b", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2765,7 +2970,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.6" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, "funding": [ { @@ -2773,26 +2978,97 @@ "type": "github" } ], - "time": "2024-03-01T13:39:50+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "phpunit/php-invoker", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -2816,34 +3092,40 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" }, - "time": "2015-06-21T13:50:34+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" }, { "name": "phpunit/php-timer", - "version": "2.1.4", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb" + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a691211e94ff39a34811abd521c31bd5b305b0bb", - "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2869,7 +3151,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.4" + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" }, "funding": [ { @@ -2877,112 +3159,54 @@ "type": "github" } ], - "time": "2024-03-01T13:42:41+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "3.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9c1da83261628cb24b6a6df371b6e312b3954768", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", - "source": "https://github.com/sebastianbergmann/php-token-stream/tree/3.1.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "abandoned": true, - "time": "2021-07-26T12:15:06+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/phpunit", - "version": "8.5.38", + "version": "9.6.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1ecad678646c817a29e55a32c930f3601c3f5a8c" + "reference": "49d7820565836236411f5dc002d16dd689cde42f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1ecad678646c817a29e55a32c930f3601c3f5a8c", - "reference": "1ecad678646c817a29e55a32c930f3601c3f5a8c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/49d7820565836236411f5dc002d16dd689cde42f", + "reference": "49d7820565836236411f5dc002d16dd689cde42f", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.0", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.2", - "phpunit/php-code-coverage": "^7.0.12", - "phpunit/php-file-iterator": "^2.0.4", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1.2", - "sebastian/comparator": "^3.0.5", - "sebastian/diff": "^3.0.2", - "sebastian/environment": "^4.2.3", - "sebastian/exporter": "^3.1.5", - "sebastian/global-state": "^3.0.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0.1", - "sebastian/type": "^1.1.3", - "sebastian/version": "^2.0.1" + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.31", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", + "sebastian/version": "^3.0.2" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage", - "phpunit/php-invoker": "To allow enforcing time limits" + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -2990,10 +3214,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "8.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -3019,7 +3246,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.38" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.20" }, "funding": [ { @@ -3035,32 +3262,144 @@ "type": "tidelift" } ], - "time": "2024-04-05T04:31:23+00:00" + "time": "2024-07-10T11:45:39+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.3", + "name": "sebastian/cli-parser", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", - "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:27:43+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" } }, "autoload": { @@ -3082,7 +3421,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.3" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" }, "funding": [ { @@ -3090,34 +3429,34 @@ "type": "github" } ], - "time": "2024-03-01T13:45:45+00:00" + "time": "2020-09-28T05:30:19+00:00" }, { "name": "sebastian/comparator", - "version": "3.0.5", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { - "php": ">=7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3156,7 +3495,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -3164,33 +3503,90 @@ "type": "github" } ], - "time": "2022-09-14T12:31:48+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { - "name": "sebastian/diff", - "version": "3.0.6", + "name": "sebastian/complexity", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/98ff311ca519c3aa73ccd3de053bdb377171d7b6", - "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", "shasum": "" }, "require": { - "php": ">=7.1" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -3222,7 +3618,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/3.0.6" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -3230,27 +3626,27 @@ "type": "github" } ], - "time": "2024-03-02T06:16:36+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", - "version": "4.2.5", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "56932f6049a0482853056ffd617c91ffcc754205" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/56932f6049a0482853056ffd617c91ffcc754205", - "reference": "56932f6049a0482853056ffd617c91ffcc754205", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.5" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-posix": "*" @@ -3258,7 +3654,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -3285,7 +3681,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/4.2.5" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -3293,34 +3689,34 @@ "type": "github" } ], - "time": "2024-03-01T13:49:59+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.6", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56" + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1939bc8fd1d39adcfa88c5b35335910869214c56", - "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { - "php": ">=7.2", - "sebastian/recursion-context": "^3.0" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3355,14 +3751,14 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" }, "funding": [ { @@ -3370,30 +3766,30 @@ "type": "github" } ], - "time": "2024-03-02T06:21:38+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { "name": "sebastian/global-state", - "version": "3.0.5", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9" + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/91c7c47047a971f02de57ed6f040087ef110c5d9", - "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { - "php": ">=7.2", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^8.0" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-uopz": "*" @@ -3401,7 +3797,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -3426,7 +3822,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" }, "funding": [ { @@ -3434,34 +3830,91 @@ "type": "github" } ], - "time": "2024-03-02T06:13:16+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "3.0.5", + "name": "sebastian/lines-of-code", + "version": "1.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "ac5b293dba925751b808e02923399fb44ff0d541" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/ac5b293dba925751b808e02923399fb44ff0d541", - "reference": "ac5b293dba925751b808e02923399fb44ff0d541", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", "shasum": "" }, "require": { - "php": ">=7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -3483,7 +3936,7 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" }, "funding": [ { @@ -3491,32 +3944,32 @@ "type": "github" } ], - "time": "2024-03-01T13:54:02+00:00" + "time": "2020-10-26T13:12:34+00:00" }, { "name": "sebastian/object-reflector", - "version": "1.1.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "1d439c229e61f244ff1f211e5c99737f90c67def" + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/1d439c229e61f244ff1f211e5c99737f90c67def", - "reference": "1d439c229e61f244ff1f211e5c99737f90c67def", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { - "php": ">=7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -3538,7 +3991,7 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.3" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" }, "funding": [ { @@ -3546,32 +3999,32 @@ "type": "github" } ], - "time": "2024-03-01T13:56:04+00:00" + "time": "2020-10-26T13:14:26+00:00" }, { "name": "sebastian/recursion-context", - "version": "3.0.2", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/9bfd3c6f1f08c026f542032dfb42813544f7d64c", - "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { - "php": ">=7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3598,10 +4051,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -3609,29 +4062,32 @@ "type": "github" } ], - "time": "2024-03-01T14:07:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", - "version": "2.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/72a7f7674d053d548003b16ff5a106e7e0e06eee", - "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3652,7 +4108,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.3" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -3660,32 +4116,32 @@ "type": "github" } ], - "time": "2024-03-01T13:59:09+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", - "version": "1.1.5", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/18f071c3a29892b037d35e6b20ddf3ea39b42874", - "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.2" + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3708,7 +4164,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/1.1.5" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -3716,29 +4172,29 @@ "type": "github" } ], - "time": "2024-03-01T14:04:07+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3761,22 +4217,28 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/master" + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" }, - "time": "2016-10-03T07:35:21+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.9.2", + "version": "3.10.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480" + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/aac1f6f347a5c5ac6bc98ad395007df00990f480", - "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017", + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017", "shasum": "" }, "require": { @@ -3843,20 +4305,20 @@ "type": "open_collective" } ], - "time": "2024-04-23T20:25:34+00:00" + "time": "2024-07-21T23:26:44+00:00" }, { "name": "symfony/console", - "version": "v5.4.39", + "version": "v5.4.42", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f3e591c48688a0cfa1a3296205926c05e84b22b1" + "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f3e591c48688a0cfa1a3296205926c05e84b22b1", - "reference": "f3e591c48688a0cfa1a3296205926c05e84b22b1", + "url": "https://api.github.com/repos/symfony/console/zipball/cef62396a0477e94fc52e87a17c6e5c32e226b7f", + "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f", "shasum": "" }, "require": { @@ -3926,7 +4388,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.39" + "source": "https://github.com/symfony/console/tree/v5.4.42" }, "funding": [ { @@ -3942,7 +4404,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T08:26:06+00:00" + "time": "2024-07-26T12:21:55+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4013,16 +4475,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "reference": "0424dff1c58f028c451efff2045f5d92410bd540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540", "shasum": "" }, "require": { @@ -4072,7 +4534,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" }, "funding": [ { @@ -4088,20 +4550,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", "shasum": "" }, "require": { @@ -4150,7 +4612,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" }, "funding": [ { @@ -4166,20 +4628,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", "shasum": "" }, "require": { @@ -4231,7 +4693,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" }, "funding": [ { @@ -4247,20 +4709,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", "shasum": "" }, "require": { @@ -4311,7 +4773,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" }, "funding": [ { @@ -4327,20 +4789,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/ec444d3f3f6505bb28d11afa41e75faadebc10a1", + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1", "shasum": "" }, "require": { @@ -4387,7 +4849,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.30.0" }, "funding": [ { @@ -4403,7 +4865,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/service-contracts", @@ -4490,16 +4952,16 @@ }, { "name": "symfony/string", - "version": "v5.4.39", + "version": "v5.4.42", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "495e71bae5862308051b9e63cc3e34078eed83ef" + "reference": "909cec913edea162a3b2836788228ad45fcab337" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/495e71bae5862308051b9e63cc3e34078eed83ef", - "reference": "495e71bae5862308051b9e63cc3e34078eed83ef", + "url": "https://api.github.com/repos/symfony/string/zipball/909cec913edea162a3b2836788228ad45fcab337", + "reference": "909cec913edea162a3b2836788228ad45fcab337", "shasum": "" }, "require": { @@ -4556,7 +5018,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.39" + "source": "https://github.com/symfony/string/tree/v5.4.42" }, "funding": [ { @@ -4572,7 +5034,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T08:26:06+00:00" + "time": "2024-07-20T18:38:32+00:00" }, { "name": "theseer/tokenizer", @@ -4734,23 +5196,23 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.6.0", + "version": "v5.6.1", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4" + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", - "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.2", + "graham-campbell/result-type": "^1.1.3", "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.2", + "phpoption/phpoption": "^1.9.3", "symfony/polyfill-ctype": "^1.24", "symfony/polyfill-mbstring": "^1.24", "symfony/polyfill-php80": "^1.24" @@ -4767,7 +5229,7 @@ "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "5.6-dev" @@ -4802,7 +5264,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" }, "funding": [ { @@ -4814,7 +5276,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T22:43:29+00:00" + "time": "2024-07-20T21:52:34+00:00" }, { "name": "webmozart/assert", From c088819e7c5a66aa4ffc646bd2498ea66f23e320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20Mei=C3=9Felbach?= Date: Fri, 23 Aug 2024 15:46:32 +0200 Subject: [PATCH 056/134] Use correct function signature --- modules/ppcp-paylater-wc-blocks/module.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/ppcp-paylater-wc-blocks/module.php b/modules/ppcp-paylater-wc-blocks/module.php index 51fabb1fd..6b4d37147 100644 --- a/modules/ppcp-paylater-wc-blocks/module.php +++ b/modules/ppcp-paylater-wc-blocks/module.php @@ -9,8 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\PayLaterWCBlocks; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -return static function (): ModuleInterface { +return static function (): PayLaterWCBlocksModule { return new PayLaterWCBlocksModule(); }; From 9152de2ef0541428155e919a3f320b3da7750510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20Mei=C3=9Felbach?= Date: Fri, 23 Aug 2024 15:52:56 +0200 Subject: [PATCH 057/134] Fix imports --- modules/ppcp-applepay/src/ApplepayModule.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index d9e5ed130..18b565544 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -18,9 +18,10 @@ use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice; use WooCommerce\PayPalCommerce\Onboarding\Environment; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; From fa36ff33ff3704d813186cd939a222086402ddb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20Mei=C3=9Felbach?= Date: Fri, 23 Aug 2024 16:01:28 +0200 Subject: [PATCH 058/134] Set platform requirement --- composer.json | 3 + composer.lock | 1485 +++++++++++++------------------------------------ 2 files changed, 386 insertions(+), 1102 deletions(-) diff --git a/composer.json b/composer.json index 3d9eaa309..bc1647be6 100644 --- a/composer.json +++ b/composer.json @@ -85,6 +85,9 @@ } }, "config": { + "platform": { + "php": "7.2" + }, "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true, "wikimedia/composer-merge-plugin": true diff --git a/composer.lock b/composer.lock index 75c1a506e..1eb53bf2c 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": "32091557d24f28a797316afa4bf9c97c", + "content-hash": "dc32884a51201e6beee788e0c860d088", "packages": [ { "name": "container-interop/service-provider", @@ -296,20 +296,20 @@ }, { "name": "psr/container", - "version": "1.1.2", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", "shasum": "" }, "require": { - "php": ">=7.4.0" + "php": ">=7.2.0" }, "type": "library", "autoload": { @@ -338,9 +338,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/1.1.1" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-03-05T17:36:06+00:00" }, { "name": "psr/log", @@ -979,38 +979,30 @@ }, { "name": "composer/pcre", - "version": "3.3.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "1637e067347a0c40bbb1e3cd786b20dcab556a81" + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/1637e067347a0c40bbb1e3cd786b20dcab556a81", - "reference": "1637e067347a0c40bbb1e3cd786b20dcab556a81", + "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<1.11.10" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.11.10", + "phpstan/phpstan": "^1.3", "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8 || ^9" + "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.x-dev" - }, - "phpstan": { - "includes": [ - "extension.neon" - ] + "dev-main": "1.x-dev" } }, "autoload": { @@ -1038,7 +1030,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.0" + "source": "https://github.com/composer/pcre/tree/1.0.1" }, "funding": [ { @@ -1054,7 +1046,7 @@ "type": "tidelift" } ], - "time": "2024-08-19T19:43:53+00:00" + "time": "2022-01-21T20:24:37+00:00" }, { "name": "composer/semver", @@ -1139,27 +1131,27 @@ }, { "name": "composer/xdebug-handler", - "version": "3.0.5", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", "shasum": "" }, "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", + "composer/pcre": "^1", + "php": "^5.3.2 || ^7.0 || ^8.0", "psr/log": "^1 || ^2 || ^3" }, "require-dev": { "phpstan/phpstan": "^1.0", "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" }, "type": "library", "autoload": { @@ -1183,9 +1175,9 @@ "performance" ], "support": { - "irc": "ircs://irc.libera.chat:6697/composer", + "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" }, "funding": [ { @@ -1201,7 +1193,7 @@ "type": "tidelift" } ], - "time": "2024-05-06T16:37:16+00:00" + "time": "2022-02-24T20:20:32+00:00" }, { "name": "dealerdirect/phpcodesniffer-composer-installer", @@ -1335,30 +1327,30 @@ }, { "name": "dhii/containers", - "version": "v0.1.5", + "version": "v0.1.4", "source": { "type": "git", "url": "https://github.com/Dhii/containers.git", - "reference": "1568cb2def9dee213c5846c4618f9d6b2cebbdef" + "reference": "42ab24683183fa0dc155f26c6a470ef697bbdc9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Dhii/containers/zipball/1568cb2def9dee213c5846c4618f9d6b2cebbdef", - "reference": "1568cb2def9dee213c5846c4618f9d6b2cebbdef", + "url": "https://api.github.com/repos/Dhii/containers/zipball/42ab24683183fa0dc155f26c6a470ef697bbdc9a", + "reference": "42ab24683183fa0dc155f26c6a470ef697bbdc9a", "shasum": "" }, "require": { "container-interop/service-provider": "^0.4", "dhii/collections-interface": "^0.3.0-alpha4", - "php": "^7.4 | ^8.0" + "php": "^7.1 | ^8.0" }, "require-dev": { "gmazzap/andrew": "^1.1", - "phpunit/phpunit": "^9.0", + "phpunit/phpunit": "^7.0 | ^8.0 | ^9.0", "psr/container": "^1.0", "psr/simple-cache": "^1.0", "slevomat/coding-standard": "^6.0", - "vimeo/psalm": "^5.0", + "vimeo/psalm": "^4.0", "wildwolf/psr-memory-cache": "^1.0" }, "type": "library", @@ -1389,9 +1381,9 @@ ], "support": { "issues": "https://github.com/Dhii/containers/issues", - "source": "https://github.com/Dhii/containers/tree/v0.1.5" + "source": "https://github.com/Dhii/containers/tree/v0.1.4" }, - "time": "2024-04-27T01:55:40+00:00" + "time": "2021-10-06T11:13:51+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -1430,53 +1422,6 @@ }, "time": "2019-12-04T15:06:13+00:00" }, - { - "name": "doctrine/deprecations", - "version": "1.1.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" - }, - "time": "2024-01-30T19:34:25+00:00" - }, { "name": "doctrine/instantiator", "version": "1.5.0", @@ -1650,24 +1595,24 @@ }, { "name": "graham-campbell/result-type", - "version": "v1.1.3", + "version": "v1.0.4", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + "reference": "0690bde05318336c7221785f2a932467f98b64ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/0690bde05318336c7221785f2a932467f98b64ca", + "reference": "0690bde05318336c7221785f2a932467f98b64ca", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3" + "php": "^7.0 || ^8.0", + "phpoption/phpoption": "^1.8" }, "require-dev": { - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8" }, "type": "library", "autoload": { @@ -1696,7 +1641,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.4" }, "funding": [ { @@ -1708,7 +1653,7 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:45:45+00:00" + "time": "2021-11-21T21:41:47+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -1831,38 +1776,35 @@ }, { "name": "mockery/mockery", - "version": "1.6.12", + "version": "1.3.6", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + "reference": "dc206df4fa314a50bbb81cf72239a305c5bbd5c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", - "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "url": "https://api.github.com/repos/mockery/mockery/zipball/dc206df4fa314a50bbb81cf72239a305c5bbd5c0", + "reference": "dc206df4fa314a50bbb81cf72239a305c5bbd5c0", "shasum": "" }, "require": { "hamcrest/hamcrest-php": "^2.0.1", "lib-pcre": ">=7.0", - "php": ">=7.3" - }, - "conflict": { - "phpunit/phpunit": "<8.0" + "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.6.17", - "symplify/easy-coding-standard": "^12.1.14" + "phpunit/phpunit": "^5.7.10|^6.5|^7.5|^8.5|^9.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, "autoload": { - "files": [ - "library/helpers.php", - "library/Mockery.php" - ], - "psr-4": { - "Mockery\\": "library/Mockery" + "psr-0": { + "Mockery": "library/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1873,20 +1815,12 @@ { "name": "Pádraic Brady", "email": "padraic.brady@gmail.com", - "homepage": "https://github.com/padraic", - "role": "Author" + "homepage": "http://blog.astrumfutura.com" }, { "name": "Dave Marshall", "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "https://davedevelopment.co.uk", - "role": "Developer" - }, - { - "name": "Nathanael Esayeas", - "email": "nathanael.esayeas@protonmail.com", - "homepage": "https://github.com/ghostwriter", - "role": "Lead Developer" + "homepage": "http://davedevelopment.co.uk" } ], "description": "Mockery is a simple yet flexible PHP mock object framework", @@ -1904,13 +1838,10 @@ "testing" ], "support": { - "docs": "https://docs.mockery.io/", "issues": "https://github.com/mockery/mockery/issues", - "rss": "https://github.com/mockery/mockery/releases.atom", - "security": "https://github.com/mockery/mockery/security/advisories", - "source": "https://github.com/mockery/mockery" + "source": "https://github.com/mockery/mockery/tree/1.3.6" }, - "time": "2024-05-16T03:13:13+00:00" + "time": "2022-09-07T15:05:49+00:00" }, { "name": "myclabs/deep-copy", @@ -2600,35 +2531,28 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.4.1", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", "shasum": "" }, "require": { - "doctrine/deprecations": "^1.1", "ext-filter": "*", - "php": "^7.4 || ^8.0", + "php": "^7.2 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7", + "phpdocumentor/type-resolver": "^1.3", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.5", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-webmozart-assert": "^1.2", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.13" + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -2652,45 +2576,37 @@ }, { "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" }, - "time": "2024-05-21T05:55:05+00:00" + "time": "2021-10-19T17:43:47+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.2", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "153ae662783729388a584b4361f2545e4d841e3c" + "reference": "77a32518733312af16a44300404e945338981de3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", - "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", + "reference": "77a32518733312af16a44300404e945338981de3", "shasum": "" }, "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -2716,39 +2632,35 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" }, - "time": "2024-02-23T11:10:43+00:00" + "time": "2022-03-15T21:29:03+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.3", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + "reference": "eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15", + "reference": "eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0" + "php": "^7.0 || ^8.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "bamarni/composer-bin-plugin": "^1.4.1", + "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8" }, "type": "library", "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - }, "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -2781,7 +2693,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + "source": "https://github.com/schmittjoh/php-option/tree/1.8.1" }, "funding": [ { @@ -2793,95 +2705,44 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:41:07+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "1.29.1", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fcaefacf2d5c417e928405b71b400d4ce10daaf4", - "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.1" - }, - "time": "2024-05-31T08:52:43+00:00" + "time": "2021-12-04T23:24:31+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.32", + "version": "7.0.17", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", + "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", "shasum": "" }, "require": { "ext-dom": "*", - "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-text-template": "^2.0.4", - "sebastian/code-unit-reverse-lookup": "^2.0.3", - "sebastian/complexity": "^2.0.3", - "sebastian/environment": "^5.1.5", - "sebastian/lines-of-code": "^1.0.4", - "sebastian/version": "^3.0.2", - "theseer/tokenizer": "^1.2.3" + "php": ">=7.2", + "phpunit/php-file-iterator": "^2.0.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.1.3 || ^4.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^4.2.2", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^9.6" + "phpunit/phpunit": "^8.2.2" }, "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "ext-xdebug": "^2.7.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "9.2.x-dev" + "dev-master": "7.0-dev" } }, "autoload": { @@ -2909,8 +2770,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.17" }, "funding": [ { @@ -2918,32 +2778,32 @@ "type": "github" } ], - "time": "2024-08-22T04:23:01+00:00" + "time": "2024-03-02T06:09:37+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "2.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "69deeb8664f611f156a924154985fbd4911eb36b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/69deeb8664f611f156a924154985fbd4911eb36b", + "reference": "69deeb8664f611f156a924154985fbd4911eb36b", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -2970,7 +2830,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.6" }, "funding": [ { @@ -2978,97 +2838,26 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2024-03-01T13:39:50+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "php": ">=5.3.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, "autoload": { "classmap": [ "src/" @@ -3092,40 +2881,34 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "2.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a691211e94ff39a34811abd521c31bd5b305b0bb", + "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -3151,7 +2934,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.4" }, "funding": [ { @@ -3159,24 +2942,84 @@ "type": "github" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2024-03-01T13:42:41+00:00" }, { - "name": "phpunit/phpunit", - "version": "9.6.20", + "name": "phpunit/php-token-stream", + "version": "3.1.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "49d7820565836236411f5dc002d16dd689cde42f" + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "9c1da83261628cb24b6a6df371b6e312b3954768" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/49d7820565836236411f5dc002d16dd689cde42f", - "reference": "49d7820565836236411f5dc002d16dd689cde42f", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9c1da83261628cb24b6a6df371b6e312b3954768", + "reference": "9c1da83261628cb24b6a6df371b6e312b3954768", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.5.0 || ^2", + "ext-tokenizer": "*", + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/3.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "abandoned": true, + "time": "2021-07-26T12:15:06+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "8.5.39", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "172ba97bcf97ae6ef86ca256adf77aece8a143fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/172ba97bcf97ae6ef86ca256adf77aece8a143fe", + "reference": "172ba97bcf97ae6ef86ca256adf77aece8a143fe", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.5.0", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -3186,27 +3029,25 @@ "myclabs/deep-copy": "^1.12.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.31", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.4", - "phpunit/php-timer": "^5.0.3", - "sebastian/cli-parser": "^1.0.2", - "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.6", - "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", - "sebastian/global-state": "^5.0.7", - "sebastian/object-enumerator": "^4.0.4", - "sebastian/resource-operations": "^3.0.4", - "sebastian/type": "^3.2.1", - "sebastian/version": "^3.0.2" + "php": ">=7.2", + "phpunit/php-code-coverage": "^7.0.17", + "phpunit/php-file-iterator": "^2.0.6", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.1.4", + "sebastian/comparator": "^3.0.5", + "sebastian/diff": "^3.0.6", + "sebastian/environment": "^4.2.5", + "sebastian/exporter": "^3.1.6", + "sebastian/global-state": "^3.0.5", + "sebastian/object-enumerator": "^3.0.5", + "sebastian/resource-operations": "^2.0.3", + "sebastian/type": "^1.1.5", + "sebastian/version": "^2.0.1" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage", + "phpunit/php-invoker": "To allow enforcing time limits" }, "bin": [ "phpunit" @@ -3214,13 +3055,10 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-master": "8.5-dev" } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], "classmap": [ "src/" ] @@ -3246,7 +3084,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.20" + "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.39" }, "funding": [ { @@ -3262,144 +3100,32 @@ "type": "tidelift" } ], - "time": "2024-07-10T11:45:39+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:27:43+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2024-07-10T11:43:00+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", + "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=5.6" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -3421,7 +3147,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.3" }, "funding": [ { @@ -3429,34 +3155,34 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2024-03-01T13:45:45+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770", + "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "php": ">=7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3495,7 +3221,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5" }, "funding": [ { @@ -3503,90 +3229,33 @@ "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:19:30+00:00" + "time": "2022-09-14T12:31:48+00:00" }, { "name": "sebastian/diff", - "version": "4.0.6", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/98ff311ca519c3aa73ccd3de053bdb377171d7b6", + "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^2 || ^3.3 || ^4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3618,7 +3287,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/diff/tree/3.0.6" }, "funding": [ { @@ -3626,27 +3295,27 @@ "type": "github" } ], - "time": "2024-03-02T06:30:58+00:00" + "time": "2024-03-02T06:16:36+00:00" }, { "name": "sebastian/environment", - "version": "5.1.5", + "version": "4.2.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "reference": "56932f6049a0482853056ffd617c91ffcc754205" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/56932f6049a0482853056ffd617c91ffcc754205", + "reference": "56932f6049a0482853056ffd617c91ffcc754205", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^7.5" }, "suggest": { "ext-posix": "*" @@ -3654,7 +3323,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3681,7 +3350,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "source": "https://github.com/sebastianbergmann/environment/tree/4.2.5" }, "funding": [ { @@ -3689,34 +3358,34 @@ "type": "github" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2024-03-01T13:49:59+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "3.1.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1939bc8fd1d39adcfa88c5b35335910869214c56", + "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "php": ">=7.2", + "sebastian/recursion-context": "^3.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -3751,14 +3420,14 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", + "homepage": "http://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.6" }, "funding": [ { @@ -3766,30 +3435,30 @@ "type": "github" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2024-03-02T06:21:38+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/91c7c47047a971f02de57ed6f040087ef110c5d9", + "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=7.2", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^8.0" }, "suggest": { "ext-uopz": "*" @@ -3797,7 +3466,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3822,7 +3491,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.5" }, "funding": [ { @@ -3830,91 +3499,34 @@ "type": "github" } ], - "time": "2024-03-02T06:35:11+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:20:34+00:00" + "time": "2024-03-02T06:13:16+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.4", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "reference": "ac5b293dba925751b808e02923399fb44ff0d541" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/ac5b293dba925751b808e02923399fb44ff0d541", + "reference": "ac5b293dba925751b808e02923399fb44ff0d541", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -3936,7 +3548,7 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.5" }, "funding": [ { @@ -3944,32 +3556,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2024-03-01T13:54:02+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.4", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "reference": "1d439c229e61f244ff1f211e5c99737f90c67def" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/1d439c229e61f244ff1f211e5c99737f90c67def", + "reference": "1d439c229e61f244ff1f211e5c99737f90c67def", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "1.1-dev" } }, "autoload": { @@ -3991,7 +3603,7 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.3" }, "funding": [ { @@ -3999,32 +3611,32 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2024-03-01T13:56:04+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/9bfd3c6f1f08c026f542032dfb42813544f7d64c", + "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -4051,10 +3663,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.2" }, "funding": [ { @@ -4062,32 +3674,29 @@ "type": "github" } ], - "time": "2023-02-03T06:07:39+00:00" + "time": "2024-03-01T14:07:30+00:00" }, { "name": "sebastian/resource-operations", - "version": "3.0.4", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/72a7f7674d053d548003b16ff5a106e7e0e06eee", + "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -4108,7 +3717,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.3" }, "funding": [ { @@ -4116,32 +3725,32 @@ "type": "github" } ], - "time": "2024-03-14T16:00:52+00:00" + "time": "2024-03-01T13:59:09+00:00" }, { "name": "sebastian/type", - "version": "3.2.1", + "version": "1.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/18f071c3a29892b037d35e6b20ddf3ea39b42874", + "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=7.2" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "1.1-dev" } }, "autoload": { @@ -4164,7 +3773,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "source": "https://github.com/sebastianbergmann/type/tree/1.1.5" }, "funding": [ { @@ -4172,29 +3781,29 @@ "type": "github" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2024-03-01T14:04:07+00:00" }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=5.6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4217,15 +3826,9 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/version/tree/master" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -4309,46 +3912,43 @@ }, { "name": "symfony/console", - "version": "v5.4.42", + "version": "v4.4.49", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f" + "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cef62396a0477e94fc52e87a17c6e5c32e226b7f", - "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f", + "url": "https://api.github.com/repos/symfony/console/zipball/33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", + "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=7.1.3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php73": "^1.8", "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" + "symfony/service-contracts": "^1.1|^2" }, "conflict": { "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3|>=5", "symfony/lock": "<4.4", - "symfony/process": "<4.4" + "symfony/process": "<3.3" }, "provide": { "psr/log-implementation": "1.0|2.0" }, "require-dev": { "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/event-dispatcher": "^4.3", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/var-dumper": "^4.3|^5.0" }, "suggest": { "psr/log": "For using the console logger", @@ -4381,14 +3981,8 @@ ], "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.42" + "source": "https://github.com/symfony/console/tree/v4.4.49" }, "funding": [ { @@ -4404,74 +3998,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:21:55+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "80d075412b557d41002320b96a096ca65aa2c98d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/80d075412b557d41002320b96a096ca65aa2c98d", - "reference": "80d075412b557d41002320b96a096ca65aa2c98d", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.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-01-24T14:02:46+00:00" + "time": "2022-11-05T17:10:16+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4552,165 +4079,6 @@ ], "time": "2024-05-31T15:07:36+00:00" }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.30.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" - }, - "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": "2024-05-31T15:07:36+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.30.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" - }, - "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": "2024-05-31T15:07:36+00:00" - }, { "name": "symfony/polyfill-mbstring", "version": "v1.30.0", @@ -4869,25 +4237,21 @@ }, { "name": "symfony/service-contracts", - "version": "v2.5.3", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3" + "reference": "afa00c500c2d6aea6e3b2f4862355f507bc5ebb4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a2329596ddc8fd568900e3fc76cba42489ecc7f3", - "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/afa00c500c2d6aea6e3b2f4862355f507bc5ebb4", + "reference": "afa00c500c2d6aea6e3b2f4862355f507bc5ebb4", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" + "php": ">=7.1.3", + "psr/container": "^1.0" }, "suggest": { "symfony/service-implementation": "" @@ -4895,7 +4259,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "1.1-dev" }, "thanks": { "name": "symfony/contracts", @@ -4932,7 +4296,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.3" + "source": "https://github.com/symfony/service-contracts/tree/v1.10.0" }, "funding": [ { @@ -4948,93 +4312,7 @@ "type": "tidelift" } ], - "time": "2023-04-21T15:04:16+00:00" - }, - { - "name": "symfony/string", - "version": "v5.4.42", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "909cec913edea162a3b2836788228ad45fcab337" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/909cec913edea162a3b2836788228ad45fcab337", - "reference": "909cec913edea162a3b2836788228ad45fcab337", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v5.4.42" - }, - "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": "2024-07-20T18:38:32+00:00" + "time": "2022-05-27T14:01:05+00:00" }, { "name": "theseer/tokenizer", @@ -5196,31 +4474,31 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.6.1", + "version": "v5.5.0", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" + "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.3", - "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3", - "symfony/polyfill-ctype": "^1.24", - "symfony/polyfill-mbstring": "^1.24", - "symfony/polyfill-php80": "^1.24" + "graham-campbell/result-type": "^1.0.2", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.8", + "symfony/polyfill-ctype": "^1.23", + "symfony/polyfill-mbstring": "^1.23.1", + "symfony/polyfill-php80": "^1.23.1" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", + "bamarni/composer-bin-plugin": "^1.4.1", "ext-filter": "*", - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25" }, "suggest": { "ext-filter": "Required to use the boolean validator." @@ -5229,10 +4507,10 @@ "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": false + "forward-command": true }, "branch-alias": { - "dev-master": "5.6-dev" + "dev-master": "5.5-dev" } }, "autoload": { @@ -5264,7 +4542,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0" }, "funding": [ { @@ -5276,7 +4554,7 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:52:34+00:00" + "time": "2022-10-16T01:01:54+00:00" }, { "name": "webmozart/assert", @@ -5496,5 +4774,8 @@ "ext-json": "*" }, "platform-dev": [], + "platform-overrides": { + "php": "7.2" + }, "plugin-api-version": "2.6.0" } From a467533ba65a40992db6156345e17e34c6172b40 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 26 Aug 2024 17:10:51 +0200 Subject: [PATCH 059/134] =?UTF-8?q?=F0=9F=90=9B=20Sync=20WC=20shipping=20d?= =?UTF-8?q?etails=20with=20Google=20Pay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change keeps the checkout & cart forms in-sync with the Google Pay form, to ensure the form submits the same details that the user can see inside Google Pay --- .../resources/js/GooglepayButton.js | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 6b67dab72..3e1fc2eb4 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -525,6 +525,11 @@ class GooglepayButton extends PaymentButton { updatedData.total, updatedData.shipping_fee ); + + // This page contains a real cart and potentially a form for shipping options. + this.syncShippingOptionWithForm( + paymentData?.shippingOptionData?.id + ); } else { transactionInfo.shippingFee = this.getShippingCosts( paymentData?.shippingOptionData?.id, @@ -728,6 +733,55 @@ class GooglepayButton extends PaymentButton { return response; } + + /** + * Updates the shipping option in the checkout form, if a form with shipping options is + * detected. + * + * @param {string} shippingOption - The shipping option ID, e.g. "flat_rate:4". + * @return {boolean} - True if a shipping option was found and selected, false otherwise. + */ + syncShippingOptionWithForm( shippingOption ) { + const wrappers = [ + // Classic checkout, Classic cart. + '.woocommerce-shipping-methods', + // Block checkout. + '.wc-block-components-shipping-rates-control', + // Block cart. + '.wc-block-components-totals-shipping', + ]; + + const sanitizedShippingOption = shippingOption.replace( /"/g, '' ); + + // Check for radio buttons with shipping options. + for ( const wrapper of wrappers ) { + const selector = `${ wrapper } input[type="radio"][value="${ sanitizedShippingOption }"]`; + const radioInput = document.querySelector( selector ); + + if ( radioInput ) { + radioInput.click(); + return true; + } + } + + // Check for select list with shipping options. + for ( const wrapper of wrappers ) { + const selector = `${ wrapper } select option[value="${ sanitizedShippingOption }"]`; + const selectOption = document.querySelector( selector ); + + if ( selectOption ) { + const selectElement = selectOption.closest( 'select' ); + + if ( selectElement ) { + selectElement.value = sanitizedShippingOption; + selectElement.dispatchEvent( new Event( 'change' ) ); + return true; + } + } + } + + return false; + } } export default GooglepayButton; From 3e0a44ca1f57b7a954ed1702cfc8a03bd0a0c411 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 26 Aug 2024 18:22:42 +0200 Subject: [PATCH 060/134] =?UTF-8?q?=F0=9F=9A=A7=20Enqueue=20missing=20scri?= =?UTF-8?q?pt=20for=20billing=20data=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When PayLater is disabled and we're in "continuation" context, then the new billing data logic is not working: The relevant JS script is not enqueued. --- modules/ppcp-googlepay/src/GooglepayModule.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/ppcp-googlepay/src/GooglepayModule.php b/modules/ppcp-googlepay/src/GooglepayModule.php index b7feedc07..9079a4b9a 100644 --- a/modules/ppcp-googlepay/src/GooglepayModule.php +++ b/modules/ppcp-googlepay/src/GooglepayModule.php @@ -93,6 +93,12 @@ class GooglepayModule implements ModuleInterface { static function () use ( $c, $button ) { $smart_button = $c->get( 'button.smart-button' ); assert( $smart_button instanceof SmartButtonInterface ); + + /* + * TODO: When PayLater is disabled and we're in "continuation" context, then no JS is enqueued. + * Find a solution to enqueue the CheckoutBootstrap module in that situation. + */ + if ( $smart_button->should_load_ppcp_script() ) { $button->enqueue(); return; From 15a09d9722f8f9d1e1a862d110bed61d768373fb Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 27 Aug 2024 12:32:00 +0200 Subject: [PATCH 061/134] =?UTF-8?q?=E2=9C=A8=20Decouple=20PayerData=20from?= =?UTF-8?q?=20global=20PPCP=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ppcp-button/resources/js/modules/Helper/PayerData.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js index df13ef92f..5695facb0 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/PayerData.js +++ b/modules/ppcp-button/resources/js/modules/Helper/PayerData.js @@ -149,12 +149,12 @@ function setCheckoutBillingDetails( payer ) { export function getWooCommerceCustomerDetails() { // Populated on server-side with details about the current WooCommerce customer. - return window.PayPalCommerceGateway?.payer; + return window?.PayPalCommerceGateway?.payer; } export function getSessionBillingDetails() { // Populated by JS via `setSessionBillingDetails()` - return window.PayPalCommerceGateway?.tempPayer; + return window._PpcpPayerSessionDetails; } /** @@ -168,7 +168,7 @@ export function setSessionBillingDetails( details ) { return; } - window.PayPalCommerceGateway.tempPayer = normalizePayerDetails( details ); + window._PpcpPayerSessionDetails = normalizePayerDetails( details ); } export function payerData() { From 07c73985e3ece321284e271138822c7b0c9fdb40 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 27 Aug 2024 12:32:53 +0200 Subject: [PATCH 062/134] =?UTF-8?q?=E2=9C=A8=20Always=20load=20GooglePay?= =?UTF-8?q?=20scripts=20on=20checkout=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-googlepay/src/GooglepayModule.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-googlepay/src/GooglepayModule.php b/modules/ppcp-googlepay/src/GooglepayModule.php index 9079a4b9a..114fe7f3d 100644 --- a/modules/ppcp-googlepay/src/GooglepayModule.php +++ b/modules/ppcp-googlepay/src/GooglepayModule.php @@ -94,16 +94,20 @@ class GooglepayModule implements ModuleInterface { $smart_button = $c->get( 'button.smart-button' ); assert( $smart_button instanceof SmartButtonInterface ); - /* - * TODO: When PayLater is disabled and we're in "continuation" context, then no JS is enqueued. - * Find a solution to enqueue the CheckoutBootstrap module in that situation. - */ - if ( $smart_button->should_load_ppcp_script() ) { $button->enqueue(); return; } + /* + * Checkout page, but no PPCP scripts were loaded. Most likely in continuation mode. + * Need to enqueue some Google Pay scripts to populate the billing form with details + * provided by Google Pay. + */ + if ( is_checkout() ) { + $button->enqueue(); + } + if ( has_block( 'woocommerce/checkout' ) || has_block( 'woocommerce/cart' ) ) { /** * Should add this to the ButtonInterface. From 5b054581036fab0486bf08ac9cf00f84d23671ae Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 27 Aug 2024 12:34:50 +0200 Subject: [PATCH 063/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Decouple=20init=20?= =?UTF-8?q?logic=20from=20global=20PPCP=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow Google Pay logic to initialize on pages that do not provide a global PayPalCommerceGateway object. Required to use CheckoutBootstrap to popuplate billing fields in continuation mode. --- .../js/ContextBootstrap/CheckoutBootstrap.js | 61 +++++++++++++------ modules/ppcp-googlepay/resources/js/boot.js | 56 ++++++++++++----- 2 files changed, 83 insertions(+), 34 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js b/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js index 9e1c30e9f..1e1933a10 100644 --- a/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js +++ b/modules/ppcp-googlepay/resources/js/ContextBootstrap/CheckoutBootstrap.js @@ -13,12 +13,34 @@ export class CheckoutBootstrap { #storage; /** - * @type {null|HTMLFormElement} + * @type {HTMLFormElement|null} */ - #checkoutForm = null; + #checkoutForm; + /** + * @param {GooglePayStorage} storage + */ constructor( storage ) { this.#storage = storage; + this.#checkoutForm = CheckoutBootstrap.getCheckoutForm(); + } + + /** + * Indicates if the current page contains a checkout form. + * + * @return {boolean} True if a checkout form is present. + */ + static isPageWithCheckoutForm() { + return null !== CheckoutBootstrap.getCheckoutForm(); + } + + /** + * Retrieves the WooCommerce checkout form element. + * + * @return {HTMLFormElement|null} The form, or null if not a checkout page. + */ + static getCheckoutForm() { + return document.querySelector( CHECKOUT_FORM_SELECTOR ); } /** @@ -27,37 +49,32 @@ export class CheckoutBootstrap { * @return {HTMLFormElement|null} The form, or null if not a checkout page. */ get checkoutForm() { - if ( null === this.#checkoutForm ) { - this.#checkoutForm = document.querySelector( - CHECKOUT_FORM_SELECTOR - ); - } - return this.#checkoutForm; } /** - * Indicates, if the current page contains a checkout form. + * Initializes the checkout process. * - * @return {boolean} True, if a checkout form is present. + * @throws {Error} If called on a page without a checkout form. */ - get isPageWithCheckoutForm() { - return null !== this.checkoutForm; - } - init() { - if ( ! this.isPageWithCheckoutForm ) { - return; + if ( ! this.#checkoutForm ) { + throw new Error( + 'Checkout form not found. Cannot initialize CheckoutBootstrap.' + ); } this.#populateCheckoutFields(); } + /** + * Populates checkout fields with stored or customer data. + */ #populateCheckoutFields() { const loggedInData = getWooCommerceCustomerDetails(); - // If customer is logged in, we use the details from the customer profile. if ( loggedInData ) { + // If customer is logged in, we use the details from the customer profile. return; } @@ -68,11 +85,17 @@ export class CheckoutBootstrap { } setPayerData( billingData, true ); - this.checkoutForm.addEventListener( 'submit', () => - this.#onFormSubmit() + this.checkoutForm.addEventListener( + 'submit', + this.#onFormSubmit.bind( this ) ); } + /** + * Clean-up when checkout form is submitted. + * + * Immediately removes the payer details from the localStorage. + */ #onFormSubmit() { this.#storage.clearPayer(); } diff --git a/modules/ppcp-googlepay/resources/js/boot.js b/modules/ppcp-googlepay/resources/js/boot.js index 3071998a9..666286ed4 100644 --- a/modules/ppcp-googlepay/resources/js/boot.js +++ b/modules/ppcp-googlepay/resources/js/boot.js @@ -1,3 +1,12 @@ +/** + * Initialize the GooglePay module in the front end. + * In some cases, this module is loaded when the `window.PayPalCommerceGateway` object is not + * present. In that case, the page does not contain a Google Pay button, but some other logic + * that is related to Google Pay (e.g., the CheckoutBootstrap module) + * + * @file + */ + import { loadCustomScript } from '@paypal/paypal-js'; import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading'; import GooglepayManager from './GooglepayManager'; @@ -5,31 +14,48 @@ import { setupButtonEvents } from '../../../ppcp-button/resources/js/modules/Hel import { CheckoutBootstrap } from './ContextBootstrap/CheckoutBootstrap'; import moduleStorage from './Helper/GooglePayStorage'; -( function ( { buttonConfig, ppcpConfig } ) { +( function ( { buttonConfig, ppcpConfig = {} } ) { const context = ppcpConfig.context; - let manager; + function bootstrapPayButton() { + if ( ! buttonConfig || ! ppcpConfig ) { + return; + } - const bootstrap = function () { - manager = new GooglepayManager( buttonConfig, ppcpConfig ); + const manager = new GooglepayManager( buttonConfig, ppcpConfig ); manager.init(); - if ( 'continuation' === context || 'checkout' === context ) { - const checkoutBootstap = new CheckoutBootstrap( moduleStorage ); - - checkoutBootstap.init(); - } - }; - - setupButtonEvents( function () { - if ( manager ) { + setupButtonEvents( function () { manager.reinit(); + } ); + } + + function bootstrapCheckout() { + if ( context && ! [ 'continuation', 'checkout' ].includes( context ) ) { + // Context must be missing/empty, or "continuation"/"checkout" to proceed. + return; } - } ); + if ( ! CheckoutBootstrap.isPageWithCheckoutForm() ) { + return; + } + + const checkoutBootstrap = new CheckoutBootstrap( moduleStorage ); + checkoutBootstrap.init(); + } + + function bootstrap() { + bootstrapPayButton(); + bootstrapCheckout(); + } document.addEventListener( 'DOMContentLoaded', () => { if ( ! buttonConfig || ! ppcpConfig ) { - // No PayPal buttons present on this page. + /* + * No PayPal buttons present on this page, but maybe a bootstrap module needs to be + * initialized. Run bootstrap without trying to load an SDK or payment configuration. + */ + bootstrap(); + return; } From 813f24da1cc717f09bf4a7437bb0c4b42d46a1e8 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 27 Aug 2024 12:46:15 +0200 Subject: [PATCH 064/134] =?UTF-8?q?=F0=9F=92=A1=20Update=20comment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-googlepay/resources/js/boot.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-googlepay/resources/js/boot.js b/modules/ppcp-googlepay/resources/js/boot.js index 666286ed4..fb9e8e313 100644 --- a/modules/ppcp-googlepay/resources/js/boot.js +++ b/modules/ppcp-googlepay/resources/js/boot.js @@ -52,7 +52,8 @@ import moduleStorage from './Helper/GooglePayStorage'; if ( ! buttonConfig || ! ppcpConfig ) { /* * No PayPal buttons present on this page, but maybe a bootstrap module needs to be - * initialized. Run bootstrap without trying to load an SDK or payment configuration. + * initialized. Skip loading the SDK or gateway configuration, and directly initialize + * the module. */ bootstrap(); From 3f1b9981183ae2292c86f97eae6bebea9ae36bdb Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 28 Aug 2024 16:52:17 +0400 Subject: [PATCH 065/134] Only remove the gateway on the WooCommerce Settings Payments tab. Additionally introduce the function to check if is WooCommerce Settings Payments tab screen (/wp-admin/admin.php?page=wc-settings&tab=checkout). --- modules/ppcp-axo/src/AxoModule.php | 8 +++++++- modules/ppcp-button/src/Helper/ContextTrait.php | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-axo/src/AxoModule.php b/modules/ppcp-axo/src/AxoModule.php index 9b5a6985d..827918e14 100644 --- a/modules/ppcp-axo/src/AxoModule.php +++ b/modules/ppcp-axo/src/AxoModule.php @@ -16,6 +16,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\Axo\Assets\AxoManager; use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; +use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; @@ -30,6 +31,9 @@ use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; * Class AxoModule */ class AxoModule implements ModuleInterface { + + use ContextTrait; + /** * {@inheritDoc} */ @@ -66,7 +70,9 @@ class AxoModule implements ModuleInterface { // Add the gateway in admin area. if ( is_admin() ) { - // $methods[] = $gateway; - Temporarily remove Fastlane from the payment gateway list in admin area. + if ( ! $this->is_wc_settings_payments_tab() ) { + $methods[] = $gateway; + } return $methods; } diff --git a/modules/ppcp-button/src/Helper/ContextTrait.php b/modules/ppcp-button/src/Helper/ContextTrait.php index 0c1bb4201..ec583c2f7 100644 --- a/modules/ppcp-button/src/Helper/ContextTrait.php +++ b/modules/ppcp-button/src/Helper/ContextTrait.php @@ -243,4 +243,20 @@ trait ContextTrait { $screen = get_current_screen(); return $screen && $screen->is_block_editor(); } + + /** + * Checks if is WooCommerce Settings Payments tab screen (/wp-admin/admin.php?page=wc-settings&tab=checkout). + * + * @return bool + */ + protected function is_wc_settings_payments_tab(): bool { + if ( ! is_admin() || isset( $_GET['section'] ) ) { + return false; + } + + $page = $_GET['page'] ?? ''; + $tab = $_GET['tab'] ?? ''; + + return $page === 'wc-settings' && $tab === 'checkout'; + } } From 1e9d9ec29e60923404ed614b5971a51797908b7b Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 28 Aug 2024 17:07:50 +0400 Subject: [PATCH 066/134] Fix the coding styles --- modules/ppcp-button/src/Helper/ContextTrait.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-button/src/Helper/ContextTrait.php b/modules/ppcp-button/src/Helper/ContextTrait.php index ec583c2f7..9f58cbcdf 100644 --- a/modules/ppcp-button/src/Helper/ContextTrait.php +++ b/modules/ppcp-button/src/Helper/ContextTrait.php @@ -250,12 +250,12 @@ trait ContextTrait { * @return bool */ protected function is_wc_settings_payments_tab(): bool { - if ( ! is_admin() || isset( $_GET['section'] ) ) { + if ( ! is_admin() || isset( $_GET['section'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification return false; } - $page = $_GET['page'] ?? ''; - $tab = $_GET['tab'] ?? ''; + $page = wc_clean( wp_unslash( $_GET['page'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification + $tab = wc_clean( wp_unslash( $_GET['tab'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification return $page === 'wc-settings' && $tab === 'checkout'; } From ac31cfe47621bbff61842e946629531ee0f03724 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 28 Aug 2024 17:32:59 +0400 Subject: [PATCH 067/134] Fix the coding styles --- modules/ppcp-axo/src/AxoModule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-axo/src/AxoModule.php b/modules/ppcp-axo/src/AxoModule.php index 827918e14..cce8fbd14 100644 --- a/modules/ppcp-axo/src/AxoModule.php +++ b/modules/ppcp-axo/src/AxoModule.php @@ -84,7 +84,7 @@ class AxoModule implements ModuleInterface { assert( $settings instanceof Settings ); $is_paypal_enabled = $settings->has( 'enabled' ) && $settings->get( 'enabled' ) ?? false; - $is_dcc_enabled = $settings->has( 'dcc_enabled' ) && $settings->get( 'dcc_enabled' ) ?? false; + $is_dcc_enabled = $settings->has( 'dcc_enabled' ) && $settings->get( 'dcc_enabled' ) ?? false; if ( ! $is_paypal_enabled || ! $is_dcc_enabled ) { return $methods; From ac1e97e4e6152534b8be88098a2fbadbef009a09 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 29 Aug 2024 18:52:38 +0200 Subject: [PATCH 068/134] Refactor LocalAlternativePaymentMethodsModule --- .../module.php | 4 +-- .../LocalAlternativePaymentMethodsModule.php | 31 ++++++++++++------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/module.php b/modules/ppcp-local-alternative-payment-methods/module.php index 9b69c59b1..ef3a095f8 100644 --- a/modules/ppcp-local-alternative-payment-methods/module.php +++ b/modules/ppcp-local-alternative-payment-methods/module.php @@ -9,8 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; - -return static function (): ModuleInterface { +return static function (): LocalAlternativePaymentMethodsModule { return new LocalAlternativePaymentMethodsModule(); }; diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 88edf6b31..ea55d4b0b 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -9,32 +9,39 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; -use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry; use WC_Order; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; -use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; +use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; /** * Class LocalAlternativePaymentMethodsModule */ -class LocalAlternativePaymentMethodsModule implements ModuleInterface { +class LocalAlternativePaymentMethodsModule implements ServiceModule, ExtendingModule, ExecutableModule { + use ModuleClassNameIdTrait; /** * {@inheritDoc} */ - public function setup(): ServiceProviderInterface { - return new ServiceProvider( - require __DIR__ . '/../services.php', - require __DIR__ . '/../extensions.php' - ); + public function services() : array { + return require __DIR__ . '/../services.php'; } /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { + public function extensions() : array { + return require __DIR__ . '/../extensions.php'; + } + + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ) : bool { add_filter( 'woocommerce_payment_gateways', /** @@ -150,6 +157,8 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { } } ); + + return true; } /** From 381041138c9b741e95d56a9cda348c30c76b1ab5 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Sat, 31 Aug 2024 14:03:04 +0300 Subject: [PATCH 069/134] Allow to override the list of Pay Later supported countries --- modules/ppcp-api-client/services.php | 15 +++++++++++++ modules/ppcp-button/services.php | 1 + .../ppcp-button/src/Helper/MessagesApply.php | 22 +++++++------------ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index 6049b050b..8b2ff9af0 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -1642,6 +1642,21 @@ return array( 'SE', ); }, + + 'api.paylater-countries' => static function ( ContainerInterface $container ) : array { + return apply_filters( + 'woocommerce_paypal_payments_supported_paylater_countries', + array( + 'US', + 'DE', + 'GB', + 'FR', + 'AU', + 'IT', + 'ES', + ) + ); + }, 'api.order-helper' => static function( ContainerInterface $container ): OrderHelper { return new OrderHelper(); }, diff --git a/modules/ppcp-button/services.php b/modules/ppcp-button/services.php index 069355da6..891d4c0a9 100644 --- a/modules/ppcp-button/services.php +++ b/modules/ppcp-button/services.php @@ -320,6 +320,7 @@ return array( }, 'button.helper.messages-apply' => static function ( ContainerInterface $container ): MessagesApply { return new MessagesApply( + $container->get( 'api.paylater-countries' ), $container->get( 'api.shop.country' ) ); }, diff --git a/modules/ppcp-button/src/Helper/MessagesApply.php b/modules/ppcp-button/src/Helper/MessagesApply.php index c0d0b1d6b..4f4a3d9f6 100644 --- a/modules/ppcp-button/src/Helper/MessagesApply.php +++ b/modules/ppcp-button/src/Helper/MessagesApply.php @@ -18,17 +18,9 @@ class MessagesApply { /** * In which countries credit messaging is available. * - * @var array + * @var string[] */ - private $countries = array( - 'US', - 'DE', - 'GB', - 'FR', - 'AU', - 'IT', - 'ES', - ); + private $allowed_countries; /** * 2-letter country code of the shop. @@ -40,10 +32,12 @@ class MessagesApply { /** * MessagesApply constructor. * - * @param string $country 2-letter country code of the shop. + * @param string[] $allowed_countries In which countries credit messaging is available. + * @param string $country 2-letter country code of the shop. */ - public function __construct( string $country ) { - $this->country = $country; + public function __construct( array $allowed_countries, string $country ) { + $this->allowed_countries = $allowed_countries; + $this->country = $country; } /** @@ -52,6 +46,6 @@ class MessagesApply { * @return bool */ public function for_country(): bool { - return in_array( $this->country, $this->countries, true ); + return in_array( $this->country, $this->allowed_countries, true ); } } From 65a4837935343992fdebab5b420712557827fa75 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Mon, 2 Sep 2024 12:03:08 +0300 Subject: [PATCH 070/134] Add more feature statuses into system report --- .../src/StatusReportModule.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index a7e810abe..eea23a9e9 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -175,6 +175,38 @@ class StatusReportModule implements ModuleInterface { $subscriptions_mode_settings ), ), + array( + 'label' => esc_html__( 'PayPal Shipping Callback', 'woocommerce-paypal-payments' ), + 'exported_label' => 'PayPal Shipping Callback', + 'description' => esc_html__( 'Whether the "Require final confirmation on checkout" setting is enabled.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_html( + $settings->has( 'blocks_final_review_enabled' ) && $settings->get( 'blocks_final_review_enabled' ) + ), + ), + array( + 'label' => esc_html__( 'Apple Pay', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Apple Pay', + 'description' => esc_html__( 'Whether Apple Pay is enabled.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_html( + $settings->has( 'applepay_button_enabled' ) && $settings->get( 'applepay_button_enabled' ) + ), + ), + array( + 'label' => esc_html__( 'Google Pay', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Google Pay', + 'description' => esc_html__( 'Whether Google Pay is enabled.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_html( + $settings->has( 'googlepay_button_enabled' ) && $settings->get( 'googlepay_button_enabled' ) + ), + ), + array( + 'label' => esc_html__( 'Fastlane', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Fastlane', + 'description' => esc_html__( 'Whether Fastlane is enabled.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_html( + $settings->has( 'axo_enabled' ) && $settings->get( 'axo_enabled' ) + ), + ), ); echo wp_kses_post( From c3c9beb7223404d0454325a178f84f4f598c27da Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 2 Sep 2024 16:24:01 +0400 Subject: [PATCH 071/134] Extend list of fastlane incompatible plugins. --- .../src/Helper/SettingsNoticeGenerator.php | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php b/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php index 503e135cb..713c9bc2d 100644 --- a/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php +++ b/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php @@ -117,9 +117,24 @@ class SettingsNoticeGenerator { * @return string */ public function generate_incompatible_plugins_notice(): string { - $incompatible_plugins = array( - 'Elementor' => did_action( 'elementor/loaded' ), - 'CheckoutWC' => defined( 'CFW_NAME' ), + /** + * Filters the list of Fastlane incompatible plugins. + */ + $incompatible_plugins = apply_filters( + 'woocommerce_paypal_payments_fastlane_incompatible_plugins', + array( + 'Elementor' => did_action( 'elementor/loaded' ), + 'CheckoutWC' => defined( 'CFW_NAME' ), + 'WCDirectCheckout' => defined( 'QLWCDC_PLUGIN_NAME' ), + 'WPMultiStepCheckout' => class_exists( 'WPMultiStepCheckout' ), + 'FluidCheckout' => class_exists( 'FluidCheckout' ), + 'THWMSCF_Multistep_Checkout' => class_exists( 'THWMSCF_Multistep_Checkout' ), + 'WC_Subscriptions' => class_exists( 'WC_Subscriptions' ), + 'Cartflows' => class_exists( 'Cartflows_Loader' ), + 'FunnelKitFunnelBuilder' => class_exists( 'WFFN_Core' ), + 'WCAllProductsForSubscriptions' => class_exists( 'WCS_ATT' ), + 'WCOnePageCheckout' => class_exists( 'PP_One_Page_Checkout' ), + ) ); $active_plugins_list = array_filter( $incompatible_plugins ); From 901774b8cc0a574b9a37d6ced5d82d6afea5bd7c Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 2 Sep 2024 16:40:14 +0200 Subject: [PATCH 072/134] =?UTF-8?q?=E2=9C=A8=20Add=20phone-observer=20for?= =?UTF-8?q?=20Gary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Push the phone number from the Woo checkout form to the Fastlane component. --- modules/ppcp-axo/resources/js/AxoManager.js | 82 +++++++++++++++++++-- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index 34b8d24c5..a195dc71e 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -11,7 +11,23 @@ import { } from '../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler'; import { getCurrentPaymentMethod } from '../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState'; +/** + * Internal customer details. + * + * @typedef {Object} CustomerDetails + * @property {null|string} email - Customer email. + * @property {null|string} phone - Fastlane phone number. + * @property {null|Object} billing - Billing details object. + * @property {null|Object} shipping - Shipping details object. + * @property {null|Object} card - Payment details object. + */ + class AxoManager { + /** + * @type {CustomerDetails} + */ + data = {}; + constructor( axoConfig, ppcpConfig ) { this.axoConfig = axoConfig; this.ppcpConfig = ppcpConfig; @@ -30,12 +46,7 @@ class AxoManager { hasCard: false, }; - this.data = { - email: null, - billing: null, - shipping: null, - card: null, - }; + this.clearData(); this.states = this.axoConfig.woocommerce.states; @@ -104,6 +115,17 @@ class AxoManager { this.triggerGatewayChange(); } + /** + * Checks if the current flow is the "Ryan flow": Ryan is a known customer who created a + * Fastlane profile before. Ryan can leverage all benefits of the accelerated 1-click checkout. + * + * @return {boolean} True means, the Fastlane could link the customer's email to an existing + * account. + */ + get isRyanFlow() { + return !! this.data.card; + } + registerEventHandlers() { this.$( document ).on( 'change', @@ -860,6 +882,8 @@ class AxoManager { ) ).render( this.el.paymentContainer.selector + '-form' ); } + + this.syncPhoneFromWooToFastlane(); } disableGatewaySelection() { @@ -873,6 +897,7 @@ class AxoManager { clearData() { this.data = { email: null, + phone: null, billing: null, shipping: null, card: null, @@ -935,7 +960,7 @@ class AxoManager { } cardComponentData() { - return { + const config = { fields: { cardholderName: { enabled: this.axoConfig.name_on_card === '1', @@ -945,6 +970,28 @@ class AxoManager { this.axoConfig.style_options ), }; + + if ( this.data.phone ) { + config.fields.phoneNumber = { + placeholder: this.data.phone, + prefill: this.data.phone, + }; + } + + return config; + } + + /** + * Refreshes the Fastlane UI component, using configuration provided by the `cardComponentData()` method. + * + * @return {Promise<*>} Resolves when the component was refreshed. + */ + async refreshFastlaneComponent() { + const elem = this.el.paymentContainer.selector + '-form'; + const config = this.cardComponentData(); + + const component = await this.fastlane.FastlaneCardComponent( config ); + return component.render( elem ); } tokenizeData() { @@ -1169,6 +1216,27 @@ class AxoManager { this.$( '#billing_email_field input' ).on( 'input', reEnableInput ); this.$( '#billing_email_field input' ).on( 'click', reEnableInput ); } + + syncPhoneFromWooToFastlane() { + // Ryan is a known customer, we do not need his phone number. + if ( this.isRyanFlow ) { + return; + } + + const phoneEl = document.querySelector( '#billing_phone' ); + + if ( ! phoneEl ) { + return; + } + + const onWooPhoneChanged = async ( ev ) => { + this.data.phone = ev.target.value; + + await this.refreshFastlaneComponent(); + }; + + phoneEl.addEventListener( 'change', onWooPhoneChanged ); + } } export default AxoManager; From b0359c9de81d29abf6cf8ac079cbcdb4a432356b Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 2 Sep 2024 16:42:04 +0200 Subject: [PATCH 073/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Minor=20code=20cle?= =?UTF-8?q?anup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Define all properties on class level (instead of implicit declaration in constructor) - Use the new `isRyanFlow` check - Use the new `this.refreshFastlaneComponent()` method --- modules/ppcp-axo/resources/js/AxoManager.js | 48 +++++++++++---------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index a195dc71e..8fb2f3e4d 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -23,21 +23,36 @@ import { getCurrentPaymentMethod } from '../../../ppcp-button/resources/js/modul */ class AxoManager { + axoConfig = null; + ppcpConfig = null; + $ = null; + + initialized = false; + hideGatewaySelection = false; + fastlane = null; + phoneNumber = null; + /** * @type {CustomerDetails} */ data = {}; + status = {}; + styles = {}; + locale = 'en_us'; + + el = null; + emailInput = null; + shippingView = null; + billingView = null; + cardView = null; constructor( axoConfig, ppcpConfig ) { this.axoConfig = axoConfig; this.ppcpConfig = ppcpConfig; - this.initialized = false; this.fastlane = new Fastlane(); this.$ = jQuery; - this.hideGatewaySelection = false; - this.status = { active: false, validEmail: false, @@ -48,6 +63,7 @@ class AxoManager { this.clearData(); + // TODO - Do we need a public `states` property for this? this.states = this.axoConfig.woocommerce.states; this.el = new DomElementCollection(); @@ -62,8 +78,6 @@ class AxoManager { }, }; - this.locale = 'en_us'; - this.registerEventHandlers(); this.shippingView = new ShippingView( @@ -814,11 +828,7 @@ class AxoManager { if ( authResponse.profileData.card ) { this.setStatus( 'hasCard', true ); } else { - this.cardComponent = ( - await this.fastlane.FastlaneCardComponent( - this.cardComponentData() - ) - ).render( this.el.paymentContainer.selector + '-form' ); + this.cardComponent = await this.refreshFastlaneComponent(); } const cardBillingAddress = @@ -860,11 +870,7 @@ class AxoManager { await this.renderWatermark( true ); - this.cardComponent = ( - await this.fastlane.FastlaneCardComponent( - this.cardComponentData() - ) - ).render( this.el.paymentContainer.selector + '-form' ); + this.cardComponent = await this.refreshFastlaneComponent(); } } else { // No profile found with this email address. @@ -876,11 +882,7 @@ class AxoManager { await this.renderWatermark( true ); - this.cardComponent = ( - await this.fastlane.FastlaneCardComponent( - this.cardComponentData() - ) - ).render( this.el.paymentContainer.selector + '-form' ); + this.cardComponent = await this.refreshFastlaneComponent(); } this.syncPhoneFromWooToFastlane(); @@ -922,7 +924,7 @@ class AxoManager { onClickSubmitButton() { // TODO: validate data. - if ( this.data.card ) { + if ( this.isRyanFlow ) { // Ryan flow log( 'Starting Ryan flow.' ); @@ -1128,8 +1130,8 @@ class AxoManager { ensureBillingPhoneNumber( data ) { if ( data.billing_phone === '' ) { let phone = ''; - const cc = this.data?.shipping?.phoneNumber?.countryCode; - const number = this.data?.shipping?.phoneNumber?.nationalNumber; + const cc = this.data.shipping?.phoneNumber?.countryCode; + const number = this.data.shipping?.phoneNumber?.nationalNumber; if ( cc ) { phone = `+${ cc } `; From a4c2569a87b671d1bd3a567d243258767fe7b2f6 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 2 Sep 2024 18:27:29 +0200 Subject: [PATCH 074/134] =?UTF-8?q?=E2=9C=A8=20Sanitize=20number,=20only?= =?UTF-8?q?=20sync=20valid=20US=20numbers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Invalid phone numbers do not trigger a Fastlane refresh --- modules/ppcp-axo/resources/js/AxoManager.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index 8fb2f3e4d..8f2e4afc6 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -975,7 +975,6 @@ class AxoManager { if ( this.data.phone ) { config.fields.phoneNumber = { - placeholder: this.data.phone, prefill: this.data.phone, }; } @@ -1231,9 +1230,22 @@ class AxoManager { return; } - const onWooPhoneChanged = async ( ev ) => { - this.data.phone = ev.target.value; + const sanitizePhoneNumber = ( number ) => { + const localNumber = number.replace( /^\+1/, '' ); + const cleanNumber = localNumber.replace( /\D/g, '' ); + // All valid US mobile numbers have exactly 10 digits. + return cleanNumber.length === 10 ? cleanNumber : null; + }; + + const onWooPhoneChanged = async ( ev ) => { + const cleanPhoneNumber = sanitizePhoneNumber( ev.target.value ); + + if ( ! cleanPhoneNumber ) { + return; + } + + this.data.phone = cleanPhoneNumber; await this.refreshFastlaneComponent(); }; From c2400429cdb1226fd5397af0569d14e379f10156 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Tue, 3 Sep 2024 08:33:17 +0300 Subject: [PATCH 075/134] Remove 3.0 upgrade notice no longer needed --- woocommerce-paypal-payments.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index afae61309..9514f9f04 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -223,22 +223,6 @@ define( 'PPCP_PAYPAL_BN_CODE', 'Woo_PPCP' ); } ); - add_action( - 'in_plugin_update_message-woocommerce-paypal-payments/woocommerce-paypal-payments.php', - static function( array $plugin_data, \stdClass $new_data ) { - if ( version_compare( $plugin_data['Version'], '3.0.0', '<' ) && - version_compare( $new_data->new_version, '3.0.0', '>=' ) ) { - printf( - '
%s: %s', - esc_html__( 'Warning', 'woocommerce-paypal-payments' ), - esc_html__( 'WooCommerce PayPal Payments version 3.0.0 contains significant changes that may impact your website. We strongly recommend reviewing the changes and testing the update on a staging site before updating it on your production environment.', 'woocommerce-paypal-payments' ) - ); - } - }, - 10, - 2 - ); - /** * Check if WooCommerce is active. * From f538ea2ef21ec1a41021479af927f7226c432655 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Tue, 3 Sep 2024 09:07:12 +0300 Subject: [PATCH 076/134] Require PHP 7.4+ --- .ddev/config.yaml | 2 +- .github/workflows/php.yml | 2 +- README.md | 2 +- composer.json | 2 +- composer.lock | 1039 +++++++++++------ modules/ppcp-admin-notices/composer.json | 2 +- modules/ppcp-api-client/composer.json | 2 +- modules/ppcp-applepay/composer.json | 2 +- modules/ppcp-axo/composer.json | 2 +- modules/ppcp-blocks/composer.json | 2 +- modules/ppcp-button/composer.json | 2 +- modules/ppcp-card-fields/composer.json | 2 +- modules/ppcp-compat/composer.json | 2 +- modules/ppcp-googlepay/composer.json | 2 +- .../composer.json | 2 +- modules/ppcp-onboarding/composer.json | 2 +- modules/ppcp-order-tracking/composer.json | 2 +- modules/ppcp-paylater-block/composer.json | 2 +- .../ppcp-paylater-configurator/composer.json | 2 +- modules/ppcp-paylater-wc-blocks/composer.json | 2 +- .../ppcp-paypal-subscriptions/composer.json | 2 +- .../ppcp-save-payment-methods/composer.json | 2 +- .../ppcp-saved-payment-checker/composer.json | 2 +- modules/ppcp-session/composer.json | 2 +- modules/ppcp-status-report/composer.json | 2 +- modules/ppcp-uninstall/composer.json | 2 +- modules/ppcp-vaulting/composer.json | 2 +- modules/ppcp-wc-gateway/composer.json | 2 +- modules/ppcp-wc-subscriptions/composer.json | 2 +- modules/ppcp-webhooks/composer.json | 2 +- modules/woocommerce-logging/composer.json | 2 +- readme.txt | 4 +- woocommerce-paypal-payments.php | 6 +- 33 files changed, 747 insertions(+), 362 deletions(-) diff --git a/.ddev/config.yaml b/.ddev/config.yaml index d65593b7c..55fa91b0a 100644 --- a/.ddev/config.yaml +++ b/.ddev/config.yaml @@ -1,7 +1,7 @@ name: woocommerce-paypal-payments type: php docroot: .ddev/wordpress -php_version: "7.2" +php_version: "7.4" webserver_type: apache-fpm router_http_port: "80" router_https_port: "443" diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index f4967e186..9bf4f02b0 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] + php-versions: ['7.4', '8.0', '8.1', '8.2', '8.3'] name: PHP ${{ matrix.php-versions }} steps: diff --git a/README.md b/README.md index 0b5c5c3fe..58227342d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, ## Dependencies -* PHP >= 7.2 +* PHP >= 7.4 * WordPress >=5.3 * WooCommerce >=4.5 diff --git a/composer.json b/composer.json index 1bba16f04..4da49f72d 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "description": "PayPal Commerce Platform for WooCommerce", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "ext-json": "*", "psr/log": "^1.1", "ralouphie/getallheaders": "^3.0", diff --git a/composer.lock b/composer.lock index 86ea6d5e7..c8f8de78d 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": "53a82a4045af3ab9f83e4e4cde7aa5bf", + "content-hash": "e5ceffcd56bfaade6fac7c5f8b279616", "packages": [ { "name": "container-interop/service-provider", @@ -296,20 +296,20 @@ }, { "name": "psr/container", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=7.4.0" }, "type": "library", "autoload": { @@ -338,9 +338,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" + "source": "https://github.com/php-fig/container/tree/1.1.2" }, - "time": "2021-03-05T17:36:06+00:00" + "time": "2021-11-05T16:50:12+00:00" }, { "name": "psr/log", @@ -979,20 +979,20 @@ }, { "name": "composer/pcre", - "version": "2.3.0", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "06d0e49d6e136e4521c6bad18598bf0f6062ae37" + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/06d0e49d6e136e4521c6bad18598bf0f6062ae37", - "reference": "06d0e49d6e136e4521c6bad18598bf0f6062ae37", + "url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "conflict": { "phpstan/phpstan": "<1.11.10" @@ -1005,7 +1005,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.x-dev" + "dev-main": "3.x-dev" }, "phpstan": { "includes": [ @@ -1038,7 +1038,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/2.3.0" + "source": "https://github.com/composer/pcre/tree/3.3.1" }, "funding": [ { @@ -1054,7 +1054,7 @@ "type": "tidelift" } ], - "time": "2024-08-19T19:14:31+00:00" + "time": "2024-08-27T18:44:43+00:00" }, { "name": "composer/semver", @@ -1335,30 +1335,30 @@ }, { "name": "dhii/containers", - "version": "v0.1.4", + "version": "v0.1.5", "source": { "type": "git", "url": "https://github.com/Dhii/containers.git", - "reference": "42ab24683183fa0dc155f26c6a470ef697bbdc9a" + "reference": "1568cb2def9dee213c5846c4618f9d6b2cebbdef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Dhii/containers/zipball/42ab24683183fa0dc155f26c6a470ef697bbdc9a", - "reference": "42ab24683183fa0dc155f26c6a470ef697bbdc9a", + "url": "https://api.github.com/repos/Dhii/containers/zipball/1568cb2def9dee213c5846c4618f9d6b2cebbdef", + "reference": "1568cb2def9dee213c5846c4618f9d6b2cebbdef", "shasum": "" }, "require": { "container-interop/service-provider": "^0.4", "dhii/collections-interface": "^0.3.0-alpha4", - "php": "^7.1 | ^8.0" + "php": "^7.4 | ^8.0" }, "require-dev": { "gmazzap/andrew": "^1.1", - "phpunit/phpunit": "^7.0 | ^8.0 | ^9.0", + "phpunit/phpunit": "^9.0", "psr/container": "^1.0", "psr/simple-cache": "^1.0", "slevomat/coding-standard": "^6.0", - "vimeo/psalm": "^4.0", + "vimeo/psalm": "^5.0", "wildwolf/psr-memory-cache": "^1.0" }, "type": "library", @@ -1389,9 +1389,9 @@ ], "support": { "issues": "https://github.com/Dhii/containers/issues", - "source": "https://github.com/Dhii/containers/tree/v0.1.4" + "source": "https://github.com/Dhii/containers/tree/v0.1.5" }, - "time": "2021-10-06T11:13:51+00:00" + "time": "2024-04-27T01:55:40+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -1430,6 +1430,53 @@ }, "time": "2019-12-04T15:06:13+00:00" }, + { + "name": "doctrine/deprecations", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + }, + "time": "2024-01-30T19:34:25+00:00" + }, { "name": "doctrine/instantiator", "version": "1.5.0", @@ -1781,35 +1828,38 @@ }, { "name": "mockery/mockery", - "version": "1.3.6", + "version": "1.6.12", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "dc206df4fa314a50bbb81cf72239a305c5bbd5c0" + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/dc206df4fa314a50bbb81cf72239a305c5bbd5c0", - "reference": "dc206df4fa314a50bbb81cf72239a305c5bbd5c0", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", "shasum": "" }, "require": { "hamcrest/hamcrest-php": "^2.0.1", "lib-pcre": ">=7.0", - "php": ">=5.6.0" + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^5.7.10|^6.5|^7.5|^8.5|^9.3" + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, "autoload": { - "psr-0": { - "Mockery": "library/" + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" } }, "notification-url": "https://packagist.org/downloads/", @@ -1820,12 +1870,20 @@ { "name": "Pádraic Brady", "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" + "homepage": "https://github.com/padraic", + "role": "Author" }, { "name": "Dave Marshall", "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "http://davedevelopment.co.uk" + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" } ], "description": "Mockery is a simple yet flexible PHP mock object framework", @@ -1843,10 +1901,13 @@ "testing" ], "support": { + "docs": "https://docs.mockery.io/", "issues": "https://github.com/mockery/mockery/issues", - "source": "https://github.com/mockery/mockery/tree/1.3.6" + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" }, - "time": "2022-09-07T15:05:49+00:00" + "time": "2024-05-16T03:13:13+00:00" }, { "name": "myclabs/deep-copy", @@ -2536,28 +2597,35 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", + "version": "5.4.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.1", "ext-filter": "*", - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" }, "type": "library", "extra": { @@ -2581,37 +2649,45 @@ }, { "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" + "email": "opensource@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" }, - "time": "2021-10-19T17:43:47+00:00" + "time": "2024-05-21T05:55:05+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.6.1", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" + "reference": "153ae662783729388a584b4361f2545e4d841e3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" }, "require-dev": { "ext-tokenizer": "*", - "psalm/phar": "^4.8" + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" }, "type": "library", "extra": { @@ -2637,9 +2713,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" }, - "time": "2022-03-15T21:29:03+00:00" + "time": "2024-02-23T11:10:43+00:00" }, { "name": "phpoption/phpoption", @@ -2717,41 +2793,92 @@ "time": "2024-07-20T21:41:07+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "7.0.17", + "name": "phpstan/phpdoc-parser", + "version": "1.30.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66" + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", - "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/5ceb0e384997db59f38774bf79c2a6134252c08f", + "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.30.0" + }, + "time": "2024-08-29T09:54:52+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.32", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-xmlwriter": "*", - "php": ">=7.2", - "phpunit/php-file-iterator": "^2.0.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.1.3 || ^4.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^4.2.2", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1.3" + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^8.2.2" + "phpunit/phpunit": "^9.6" }, "suggest": { - "ext-xdebug": "^2.7.2" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "7.0-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -2779,7 +2906,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.17" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -2787,32 +2915,32 @@ "type": "github" } ], - "time": "2024-03-02T06:09:37+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "2.0.6", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "69deeb8664f611f156a924154985fbd4911eb36b" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/69deeb8664f611f156a924154985fbd4911eb36b", - "reference": "69deeb8664f611f156a924154985fbd4911eb36b", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2839,7 +2967,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.6" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, "funding": [ { @@ -2847,26 +2975,97 @@ "type": "github" } ], - "time": "2024-03-01T13:39:50+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "phpunit/php-invoker", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -2890,34 +3089,40 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" }, - "time": "2015-06-21T13:50:34+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" }, { "name": "phpunit/php-timer", - "version": "2.1.4", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb" + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a691211e94ff39a34811abd521c31bd5b305b0bb", - "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2943,7 +3148,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.4" + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" }, "funding": [ { @@ -2951,84 +3156,24 @@ "type": "github" } ], - "time": "2024-03-01T13:42:41+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "3.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9c1da83261628cb24b6a6df371b6e312b3954768", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", - "source": "https://github.com/sebastianbergmann/php-token-stream/tree/3.1.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "abandoned": true, - "time": "2021-07-26T12:15:06+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/phpunit", - "version": "8.5.39", + "version": "9.6.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "172ba97bcf97ae6ef86ca256adf77aece8a143fe" + "reference": "49d7820565836236411f5dc002d16dd689cde42f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/172ba97bcf97ae6ef86ca256adf77aece8a143fe", - "reference": "172ba97bcf97ae6ef86ca256adf77aece8a143fe", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/49d7820565836236411f5dc002d16dd689cde42f", + "reference": "49d7820565836236411f5dc002d16dd689cde42f", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.5.0", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -3038,25 +3183,27 @@ "myclabs/deep-copy": "^1.12.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=7.2", - "phpunit/php-code-coverage": "^7.0.17", - "phpunit/php-file-iterator": "^2.0.6", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1.4", - "sebastian/comparator": "^3.0.5", - "sebastian/diff": "^3.0.6", - "sebastian/environment": "^4.2.5", - "sebastian/exporter": "^3.1.6", - "sebastian/global-state": "^3.0.5", - "sebastian/object-enumerator": "^3.0.5", - "sebastian/resource-operations": "^2.0.3", - "sebastian/type": "^1.1.5", - "sebastian/version": "^2.0.1" + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.31", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", + "sebastian/version": "^3.0.2" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage", - "phpunit/php-invoker": "To allow enforcing time limits" + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -3064,10 +3211,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "8.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -3093,7 +3243,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.39" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.20" }, "funding": [ { @@ -3109,32 +3259,144 @@ "type": "tidelift" } ], - "time": "2024-07-10T11:43:00+00:00" + "time": "2024-07-10T11:45:39+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.3", + "name": "sebastian/cli-parser", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", - "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:27:43+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" } }, "autoload": { @@ -3156,7 +3418,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.3" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" }, "funding": [ { @@ -3164,34 +3426,34 @@ "type": "github" } ], - "time": "2024-03-01T13:45:45+00:00" + "time": "2020-09-28T05:30:19+00:00" }, { "name": "sebastian/comparator", - "version": "3.0.5", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { - "php": ">=7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3230,7 +3492,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -3238,33 +3500,90 @@ "type": "github" } ], - "time": "2022-09-14T12:31:48+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { - "name": "sebastian/diff", - "version": "3.0.6", + "name": "sebastian/complexity", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/98ff311ca519c3aa73ccd3de053bdb377171d7b6", - "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", "shasum": "" }, "require": { - "php": ">=7.1" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -3296,7 +3615,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/3.0.6" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -3304,27 +3623,27 @@ "type": "github" } ], - "time": "2024-03-02T06:16:36+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", - "version": "4.2.5", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "56932f6049a0482853056ffd617c91ffcc754205" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/56932f6049a0482853056ffd617c91ffcc754205", - "reference": "56932f6049a0482853056ffd617c91ffcc754205", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.5" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-posix": "*" @@ -3332,7 +3651,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -3359,7 +3678,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/4.2.5" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -3367,34 +3686,34 @@ "type": "github" } ], - "time": "2024-03-01T13:49:59+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.6", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56" + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1939bc8fd1d39adcfa88c5b35335910869214c56", - "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { - "php": ">=7.2", - "sebastian/recursion-context": "^3.0" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3429,14 +3748,14 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" }, "funding": [ { @@ -3444,30 +3763,30 @@ "type": "github" } ], - "time": "2024-03-02T06:21:38+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { "name": "sebastian/global-state", - "version": "3.0.5", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9" + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/91c7c47047a971f02de57ed6f040087ef110c5d9", - "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { - "php": ">=7.2", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^8.0" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-uopz": "*" @@ -3475,7 +3794,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -3500,7 +3819,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" }, "funding": [ { @@ -3508,34 +3827,91 @@ "type": "github" } ], - "time": "2024-03-02T06:13:16+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "3.0.5", + "name": "sebastian/lines-of-code", + "version": "1.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "ac5b293dba925751b808e02923399fb44ff0d541" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/ac5b293dba925751b808e02923399fb44ff0d541", - "reference": "ac5b293dba925751b808e02923399fb44ff0d541", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", "shasum": "" }, "require": { - "php": ">=7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -3557,7 +3933,7 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" }, "funding": [ { @@ -3565,32 +3941,32 @@ "type": "github" } ], - "time": "2024-03-01T13:54:02+00:00" + "time": "2020-10-26T13:12:34+00:00" }, { "name": "sebastian/object-reflector", - "version": "1.1.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "1d439c229e61f244ff1f211e5c99737f90c67def" + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/1d439c229e61f244ff1f211e5c99737f90c67def", - "reference": "1d439c229e61f244ff1f211e5c99737f90c67def", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { - "php": ">=7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -3612,7 +3988,7 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.3" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" }, "funding": [ { @@ -3620,32 +3996,32 @@ "type": "github" } ], - "time": "2024-03-01T13:56:04+00:00" + "time": "2020-10-26T13:14:26+00:00" }, { "name": "sebastian/recursion-context", - "version": "3.0.2", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/9bfd3c6f1f08c026f542032dfb42813544f7d64c", - "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { - "php": ">=7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3672,10 +4048,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -3683,29 +4059,32 @@ "type": "github" } ], - "time": "2024-03-01T14:07:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", - "version": "2.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/72a7f7674d053d548003b16ff5a106e7e0e06eee", - "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3726,7 +4105,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.3" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -3734,32 +4113,32 @@ "type": "github" } ], - "time": "2024-03-01T13:59:09+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", - "version": "1.1.5", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/18f071c3a29892b037d35e6b20ddf3ea39b42874", - "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.2" + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3782,7 +4161,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/1.1.5" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -3790,29 +4169,29 @@ "type": "github" } ], - "time": "2024-03-01T14:04:07+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3835,9 +4214,15 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/master" + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" }, - "time": "2016-10-03T07:35:21+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -3921,16 +4306,16 @@ }, { "name": "symfony/console", - "version": "v5.4.42", + "version": "v5.4.43", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f" + "reference": "e86f8554de667c16dde8aeb89a3990cfde924df9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cef62396a0477e94fc52e87a17c6e5c32e226b7f", - "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f", + "url": "https://api.github.com/repos/symfony/console/zipball/e86f8554de667c16dde8aeb89a3990cfde924df9", + "reference": "e86f8554de667c16dde8aeb89a3990cfde924df9", "shasum": "" }, "require": { @@ -4000,7 +4385,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.42" + "source": "https://github.com/symfony/console/tree/v5.4.43" }, "funding": [ { @@ -4016,7 +4401,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:21:55+00:00" + "time": "2024-08-13T16:31:56+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4564,16 +4949,16 @@ }, { "name": "symfony/string", - "version": "v5.4.42", + "version": "v5.4.43", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "909cec913edea162a3b2836788228ad45fcab337" + "reference": "8be1d484951ff5ca995eaf8edcbcb8b9a5888450" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/909cec913edea162a3b2836788228ad45fcab337", - "reference": "909cec913edea162a3b2836788228ad45fcab337", + "url": "https://api.github.com/repos/symfony/string/zipball/8be1d484951ff5ca995eaf8edcbcb8b9a5888450", + "reference": "8be1d484951ff5ca995eaf8edcbcb8b9a5888450", "shasum": "" }, "require": { @@ -4630,7 +5015,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.42" + "source": "https://github.com/symfony/string/tree/v5.4.43" }, "funding": [ { @@ -4646,7 +5031,7 @@ "type": "tidelift" } ], - "time": "2024-07-20T18:38:32+00:00" + "time": "2024-08-01T10:24:28+00:00" }, { "name": "theseer/tokenizer", @@ -5104,7 +5489,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "ext-json": "*" }, "platform-dev": [], diff --git a/modules/ppcp-admin-notices/composer.json b/modules/ppcp-admin-notices/composer.json index 04697e844..780cadb66 100644 --- a/modules/ppcp-admin-notices/composer.json +++ b/modules/ppcp-admin-notices/composer.json @@ -4,7 +4,7 @@ "description": "Admin notices module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-api-client/composer.json b/modules/ppcp-api-client/composer.json index 1dca85992..1f4627383 100644 --- a/modules/ppcp-api-client/composer.json +++ b/modules/ppcp-api-client/composer.json @@ -4,7 +4,7 @@ "description": "API client module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-applepay/composer.json b/modules/ppcp-applepay/composer.json index d22092e7d..29eb00a9e 100644 --- a/modules/ppcp-applepay/composer.json +++ b/modules/ppcp-applepay/composer.json @@ -4,7 +4,7 @@ "description": "Applepay module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-axo/composer.json b/modules/ppcp-axo/composer.json index 352c30523..976a4a272 100644 --- a/modules/ppcp-axo/composer.json +++ b/modules/ppcp-axo/composer.json @@ -4,7 +4,7 @@ "description": "Axo module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-blocks/composer.json b/modules/ppcp-blocks/composer.json index f71b084a2..1811a6aee 100644 --- a/modules/ppcp-blocks/composer.json +++ b/modules/ppcp-blocks/composer.json @@ -4,7 +4,7 @@ "description": "Blocks module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-button/composer.json b/modules/ppcp-button/composer.json index db97aad22..ef2a9fcf9 100644 --- a/modules/ppcp-button/composer.json +++ b/modules/ppcp-button/composer.json @@ -4,7 +4,7 @@ "description": "Button module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-card-fields/composer.json b/modules/ppcp-card-fields/composer.json index ad57a2296..bb63b27e7 100644 --- a/modules/ppcp-card-fields/composer.json +++ b/modules/ppcp-card-fields/composer.json @@ -4,7 +4,7 @@ "description": "Advanced Checkout Card Fields module", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-compat/composer.json b/modules/ppcp-compat/composer.json index eb3c1d35f..1ee2832ab 100644 --- a/modules/ppcp-compat/composer.json +++ b/modules/ppcp-compat/composer.json @@ -4,7 +4,7 @@ "description": "Compatibility module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-googlepay/composer.json b/modules/ppcp-googlepay/composer.json index 81698b434..5a4502b0b 100644 --- a/modules/ppcp-googlepay/composer.json +++ b/modules/ppcp-googlepay/composer.json @@ -4,7 +4,7 @@ "description": "Googlepay module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-local-alternative-payment-methods/composer.json b/modules/ppcp-local-alternative-payment-methods/composer.json index 278244301..d49279693 100644 --- a/modules/ppcp-local-alternative-payment-methods/composer.json +++ b/modules/ppcp-local-alternative-payment-methods/composer.json @@ -4,7 +4,7 @@ "description": "Country based Alternative Payment Methods module", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-onboarding/composer.json b/modules/ppcp-onboarding/composer.json index 27886d3b7..805a1bb1f 100644 --- a/modules/ppcp-onboarding/composer.json +++ b/modules/ppcp-onboarding/composer.json @@ -4,7 +4,7 @@ "description": "Onboarding module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-order-tracking/composer.json b/modules/ppcp-order-tracking/composer.json index 3e4a60b56..f901b6657 100644 --- a/modules/ppcp-order-tracking/composer.json +++ b/modules/ppcp-order-tracking/composer.json @@ -4,7 +4,7 @@ "description": "Order tracking module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-paylater-block/composer.json b/modules/ppcp-paylater-block/composer.json index 58b7a5545..2be488dda 100644 --- a/modules/ppcp-paylater-block/composer.json +++ b/modules/ppcp-paylater-block/composer.json @@ -4,7 +4,7 @@ "description": "Pay Later Block module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-paylater-configurator/composer.json b/modules/ppcp-paylater-configurator/composer.json index 755aa0dce..a78114979 100644 --- a/modules/ppcp-paylater-configurator/composer.json +++ b/modules/ppcp-paylater-configurator/composer.json @@ -4,7 +4,7 @@ "description": "Pay Later Messaging configurator module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-paylater-wc-blocks/composer.json b/modules/ppcp-paylater-wc-blocks/composer.json index d2832053b..7b33caae4 100644 --- a/modules/ppcp-paylater-wc-blocks/composer.json +++ b/modules/ppcp-paylater-wc-blocks/composer.json @@ -4,7 +4,7 @@ "description": "Pay Later WooCommerce Blocks module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-paypal-subscriptions/composer.json b/modules/ppcp-paypal-subscriptions/composer.json index 161c4b9ce..8e7969c46 100644 --- a/modules/ppcp-paypal-subscriptions/composer.json +++ b/modules/ppcp-paypal-subscriptions/composer.json @@ -4,7 +4,7 @@ "description": "Module for PayPal Subscriptions API integration", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-save-payment-methods/composer.json b/modules/ppcp-save-payment-methods/composer.json index 50ff8c251..54656aa2e 100644 --- a/modules/ppcp-save-payment-methods/composer.json +++ b/modules/ppcp-save-payment-methods/composer.json @@ -4,7 +4,7 @@ "description": "Save payment methods module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-saved-payment-checker/composer.json b/modules/ppcp-saved-payment-checker/composer.json index 96c8931c3..00a15a36a 100644 --- a/modules/ppcp-saved-payment-checker/composer.json +++ b/modules/ppcp-saved-payment-checker/composer.json @@ -4,7 +4,7 @@ "description": "Saved payments checker module", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-session/composer.json b/modules/ppcp-session/composer.json index b5cd73378..3a59ed8fc 100644 --- a/modules/ppcp-session/composer.json +++ b/modules/ppcp-session/composer.json @@ -4,7 +4,7 @@ "description": "Session module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-status-report/composer.json b/modules/ppcp-status-report/composer.json index 181a6590f..53ac3c4d3 100644 --- a/modules/ppcp-status-report/composer.json +++ b/modules/ppcp-status-report/composer.json @@ -4,7 +4,7 @@ "description": "Status report module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-uninstall/composer.json b/modules/ppcp-uninstall/composer.json index 53351b6dc..efede6ce8 100644 --- a/modules/ppcp-uninstall/composer.json +++ b/modules/ppcp-uninstall/composer.json @@ -4,7 +4,7 @@ "description": "Uninstall module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-vaulting/composer.json b/modules/ppcp-vaulting/composer.json index e24f10fe6..7bacd2d46 100644 --- a/modules/ppcp-vaulting/composer.json +++ b/modules/ppcp-vaulting/composer.json @@ -4,7 +4,7 @@ "description": "Vaulting module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-wc-gateway/composer.json b/modules/ppcp-wc-gateway/composer.json index b9ea62f55..d833fd575 100644 --- a/modules/ppcp-wc-gateway/composer.json +++ b/modules/ppcp-wc-gateway/composer.json @@ -4,7 +4,7 @@ "description": "WC gateway module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-wc-subscriptions/composer.json b/modules/ppcp-wc-subscriptions/composer.json index 3cf50034b..4d8036d07 100644 --- a/modules/ppcp-wc-subscriptions/composer.json +++ b/modules/ppcp-wc-subscriptions/composer.json @@ -4,7 +4,7 @@ "description": "Module for WC Subscriptions plugin integration", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/ppcp-webhooks/composer.json b/modules/ppcp-webhooks/composer.json index 47795ad03..df9fc9b14 100644 --- a/modules/ppcp-webhooks/composer.json +++ b/modules/ppcp-webhooks/composer.json @@ -4,7 +4,7 @@ "description": "Webhooks module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/modules/woocommerce-logging/composer.json b/modules/woocommerce-logging/composer.json index 129854023..f1149f3fc 100644 --- a/modules/woocommerce-logging/composer.json +++ b/modules/woocommerce-logging/composer.json @@ -4,7 +4,7 @@ "description": "WC logging module for PPCP", "license": "GPL-2.0", "require": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "dhii/module-interface": "^0.3.0-alpha1" }, "autoload": { diff --git a/readme.txt b/readme.txt index 180629a68..143240085 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: woocommerce, automattic, syde Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple pay, subscriptions, debit card, credit card, google pay Requires at least: 5.3 Tested up to: 6.6 -Requires PHP: 7.2 +Requires PHP: 7.4 Stable tag: 2.9.0 License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -137,7 +137,7 @@ To install and configure WooCommerce PayPal Payments, you will need: * WordPress Version 5.3 or newer (installed) * WooCommerce Version 3.9 or newer (installed and activated) -* PHP Version 7.2 or newer +* PHP Version 7.4 or newer * PayPal business **or** personal account = Installation instructions = diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index afae61309..55a9ccc70 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -7,7 +7,7 @@ * Author: WooCommerce * Author URI: https://woocommerce.com/ * License: GPL-2.0 - * Requires PHP: 7.2 + * Requires PHP: 7.4 * Requires Plugins: woocommerce * WC requires at least: 3.9 * WC tested up to: 9.2 @@ -59,11 +59,11 @@ define( 'PPCP_PAYPAL_BN_CODE', 'Woo_PPCP' ); return; } - if ( version_compare( PHP_VERSION, '7.2', '<' ) ) { + if ( version_compare( PHP_VERSION, '7.4', '<' ) ) { add_action( 'admin_notices', function() { - echo '

' . esc_html__( 'WooCommerce PayPal Payments requires PHP 7.1 or above.', 'woocommerce-paypal-payments' ), '

'; + echo '

' . esc_html__( 'WooCommerce PayPal Payments requires PHP 7.4 or above.', 'woocommerce-paypal-payments' ), '

'; } ); From c808db045dcd7b821c5994177c1349317b2dbab8 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Tue, 3 Sep 2024 09:12:40 +0300 Subject: [PATCH 077/134] Require WP 6.3+ --- .ddev/config.yaml | 2 +- README.md | 2 +- readme.txt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ddev/config.yaml b/.ddev/config.yaml index 55fa91b0a..5686c7920 100644 --- a/.ddev/config.yaml +++ b/.ddev/config.yaml @@ -18,7 +18,7 @@ hooks: pre-start: - exec-host: "mkdir -p .ddev/wordpress/wp-content/plugins/${DDEV_PROJECT}" web_environment: - - WP_VERSION=6.2.2 + - WP_VERSION=6.3.3 - WP_LOCALE=en_US - WP_TITLE=WooCommerce PayPal Payments - WP_MULTISITE=true diff --git a/README.md b/README.md index 58227342d..6f5740cd3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, ## Dependencies * PHP >= 7.4 -* WordPress >=5.3 +* WordPress >= 6.3 * WooCommerce >=4.5 ## Development diff --git a/readme.txt b/readme.txt index 143240085..67ee7d250 100644 --- a/readme.txt +++ b/readme.txt @@ -1,7 +1,7 @@ === WooCommerce PayPal Payments === Contributors: woocommerce, automattic, syde Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple pay, subscriptions, debit card, credit card, google pay -Requires at least: 5.3 +Requires at least: 6.3 Tested up to: 6.6 Requires PHP: 7.4 Stable tag: 2.9.0 @@ -135,7 +135,7 @@ Check out the [Frequently Asked Questions](https://woocommerce.com/document/woo To install and configure WooCommerce PayPal Payments, you will need: -* WordPress Version 5.3 or newer (installed) +* WordPress Version 6.3 or newer (installed) * WooCommerce Version 3.9 or newer (installed and activated) * PHP Version 7.4 or newer * PayPal business **or** personal account From f0c12eb04128e9884ffd930d28a3edb71cdfde94 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Tue, 3 Sep 2024 09:13:07 +0300 Subject: [PATCH 078/134] Require WC 6.9+ --- README.md | 2 +- readme.txt | 2 +- woocommerce-paypal-payments.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6f5740cd3..921614701 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, * PHP >= 7.4 * WordPress >= 6.3 -* WooCommerce >=4.5 +* WooCommerce >= 6.9 ## Development diff --git a/readme.txt b/readme.txt index 67ee7d250..1a0a76a4c 100644 --- a/readme.txt +++ b/readme.txt @@ -136,7 +136,7 @@ Check out the [Frequently Asked Questions](https://woocommerce.com/document/woo To install and configure WooCommerce PayPal Payments, you will need: * WordPress Version 6.3 or newer (installed) -* WooCommerce Version 3.9 or newer (installed and activated) +* WooCommerce Version 6.9 or newer (installed and activated) * PHP Version 7.4 or newer * PayPal business **or** personal account diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index 55a9ccc70..241de3af3 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -9,7 +9,7 @@ * License: GPL-2.0 * Requires PHP: 7.4 * Requires Plugins: woocommerce - * WC requires at least: 3.9 + * WC requires at least: 6.9 * WC tested up to: 9.2 * Text Domain: woocommerce-paypal-payments * From 426f096766752f8c9ea25ded6bbd0eae8eb05f49 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Tue, 3 Sep 2024 09:18:35 +0300 Subject: [PATCH 079/134] Use PHP 7.4 for package GHA --- .github/workflows/package-new.yml | 2 +- .github/workflows/package.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/package-new.yml b/.github/workflows/package-new.yml index 0095034a3..dcc39d24d 100644 --- a/.github/workflows/package-new.yml +++ b/.github/workflows/package-new.yml @@ -29,7 +29,7 @@ jobs: needs: check_version uses: inpsyde/reusable-workflows/.github/workflows/build-plugin-archive.yml@feature/PROD-171-rector-archive with: - PHP_VERSION: 7.2 + PHP_VERSION: 7.4 PLUGIN_MAIN_FILE: ./woocommerce-paypal-payments.php PLUGIN_VERSION: ${{ needs.check_version.outputs.version }} ARCHIVE_NAME: woocommerce-paypal-payments-${{ needs.check_version.outputs.version }} diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 70f6fe58e..e7957d210 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -27,7 +27,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 7.2 + php-version: 7.4 - name: Fix plugin version input # Add the version number if only suffix entered run: echo "PACKAGE_VERSION=$(sed -nE '/Version:/s/.* ([0-9.]+).*/\1/p' woocommerce-paypal-payments.php)-$PACKAGE_VERSION" >> $GITHUB_ENV From 0653a018ed4d9e244ce776af9c5be1221420bb43 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Tue, 3 Sep 2024 09:18:57 +0300 Subject: [PATCH 080/134] Remove WC 5.9 in GHA --- .github/workflows/e2e.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index e78269a31..0dfb99455 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,8 +7,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['7.3', '7.4', '8.2'] - wc-versions: ['5.9.5', '7.7.2'] + php-versions: ['7.4', '8.2'] + wc-versions: ['6.9.4', '7.7.2'] name: PHP ${{ matrix.php-versions }} WC ${{ matrix.wc-versions }} steps: From 1efb3a0087bd509cf3571cbeb0f6b75b938167c6 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 3 Sep 2024 15:05:23 +0400 Subject: [PATCH 081/134] Refactor the configuration to include full names --- modules/ppcp-axo/services.php | 116 +++++++++++++++--- .../src/Helper/SettingsNoticeGenerator.php | 51 +++----- 2 files changed, 118 insertions(+), 49 deletions(-) diff --git a/modules/ppcp-axo/services.php b/modules/ppcp-axo/services.php index 5b468835f..890029ad5 100644 --- a/modules/ppcp-axo/services.php +++ b/modules/ppcp-axo/services.php @@ -21,14 +21,14 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return array( // If AXO can be configured. - 'axo.eligible' => static function ( ContainerInterface $container ): bool { + 'axo.eligible' => static function ( ContainerInterface $container ): bool { $apm_applies = $container->get( 'axo.helpers.apm-applies' ); assert( $apm_applies instanceof ApmApplies ); return $apm_applies->for_country_currency(); }, - 'axo.helpers.apm-applies' => static function ( ContainerInterface $container ) : ApmApplies { + 'axo.helpers.apm-applies' => static function ( ContainerInterface $container ) : ApmApplies { return new ApmApplies( $container->get( 'axo.supported-country-currency-matrix' ), $container->get( 'api.shop.currency' ), @@ -36,16 +36,16 @@ return array( ); }, - 'axo.helpers.settings-notice-generator' => static function ( ContainerInterface $container ) : SettingsNoticeGenerator { - return new SettingsNoticeGenerator(); + 'axo.helpers.settings-notice-generator' => static function ( ContainerInterface $container ) : SettingsNoticeGenerator { + return new SettingsNoticeGenerator( $container->get( 'axo.fastlane-incompatible-plugin-names' ) ); }, // If AXO is configured and onboarded. - 'axo.available' => static function ( ContainerInterface $container ): bool { + 'axo.available' => static function ( ContainerInterface $container ): bool { return true; }, - 'axo.url' => static function ( ContainerInterface $container ): string { + 'axo.url' => static function ( ContainerInterface $container ): string { $path = realpath( __FILE__ ); if ( false === $path ) { return ''; @@ -56,7 +56,7 @@ return array( ); }, - 'axo.manager' => static function ( ContainerInterface $container ): AxoManager { + 'axo.manager' => static function ( ContainerInterface $container ): AxoManager { return new AxoManager( $container->get( 'axo.url' ), $container->get( 'ppcp.asset-version' ), @@ -70,7 +70,7 @@ return array( ); }, - 'axo.gateway' => static function ( ContainerInterface $container ): AxoGateway { + 'axo.gateway' => static function ( ContainerInterface $container ): AxoGateway { return new AxoGateway( $container->get( 'wcgateway.settings.render' ), $container->get( 'wcgateway.settings' ), @@ -87,7 +87,7 @@ return array( ); }, - 'axo.card_icons' => static function ( ContainerInterface $container ): array { + 'axo.card_icons' => static function ( ContainerInterface $container ): array { return array( array( 'title' => 'Visa', @@ -108,7 +108,7 @@ return array( ); }, - 'axo.card_icons.axo' => static function ( ContainerInterface $container ): array { + 'axo.card_icons.axo' => static function ( ContainerInterface $container ): array { return array( array( 'title' => 'Visa', @@ -144,7 +144,7 @@ return array( /** * The matrix which countries and currency combinations can be used for AXO. */ - 'axo.supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array { + 'axo.supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array { /** * Returns which countries and currency combinations can be used for AXO. */ @@ -163,7 +163,7 @@ return array( ); }, - 'axo.settings-conflict-notice' => static function ( ContainerInterface $container ) : string { + 'axo.settings-conflict-notice' => static function ( ContainerInterface $container ) : string { $settings_notice_generator = $container->get( 'axo.helpers.settings-notice-generator' ); assert( $settings_notice_generator instanceof SettingsNoticeGenerator ); @@ -173,28 +173,28 @@ return array( return $settings_notice_generator->generate_settings_conflict_notice( $settings ); }, - 'axo.checkout-config-notice' => static function ( ContainerInterface $container ) : string { + 'axo.checkout-config-notice' => static function ( ContainerInterface $container ) : string { $settings_notice_generator = $container->get( 'axo.helpers.settings-notice-generator' ); assert( $settings_notice_generator instanceof SettingsNoticeGenerator ); return $settings_notice_generator->generate_checkout_notice(); }, - 'axo.shipping-config-notice' => static function ( ContainerInterface $container ) : string { + 'axo.shipping-config-notice' => static function ( ContainerInterface $container ) : string { $settings_notice_generator = $container->get( 'axo.helpers.settings-notice-generator' ); assert( $settings_notice_generator instanceof SettingsNoticeGenerator ); return $settings_notice_generator->generate_shipping_notice(); }, - 'axo.incompatible-plugins-notice' => static function ( ContainerInterface $container ) : string { + 'axo.incompatible-plugins-notice' => static function ( ContainerInterface $container ) : string { $settings_notice_generator = $container->get( 'axo.helpers.settings-notice-generator' ); assert( $settings_notice_generator instanceof SettingsNoticeGenerator ); return $settings_notice_generator->generate_incompatible_plugins_notice(); }, - 'axo.smart-button-location-notice' => static function ( ContainerInterface $container ) : string { + 'axo.smart-button-location-notice' => static function ( ContainerInterface $container ) : string { $settings = $container->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); @@ -222,10 +222,92 @@ return array( return '

' . $notice_content . '

'; }, - 'axo.endpoint.frontend-logger' => static function ( ContainerInterface $container ): FrontendLoggerEndpoint { + 'axo.endpoint.frontend-logger' => static function ( ContainerInterface $container ): FrontendLoggerEndpoint { return new FrontendLoggerEndpoint( $container->get( 'button.request-data' ), $container->get( 'woocommerce.logger.woocommerce' ) ); }, + + /** + * The list of Fastlane incompatible plugins. + * + * @returns array + */ + 'axo.fastlane-incompatible-plugins' => static function () : array { + /** + * Filters the list of Fastlane incompatible plugins. + */ + return apply_filters( + 'woocommerce_paypal_payments_fastlane_incompatible_plugins', + array( + array( + 'name' => 'Elementor', + 'isActive' => did_action( 'elementor/loaded' ), + ), + array( + 'name' => 'CheckoutWC', + 'isActive' => defined( 'CFW_NAME' ), + ), + array( + 'name' => 'Direct Checkout for WooCommerce', + 'isActive' => defined( 'QLWCDC_PLUGIN_NAME' ), + ), + array( + 'name' => 'Multi-Step Checkout for WooCommerce', + 'isActive' => class_exists( 'WPMultiStepCheckout' ), + ), + array( + 'name' => 'Fluid Checkout for WooCommerce', + 'isActive' => class_exists( 'FluidCheckout' ), + ), + array( + 'name' => 'MultiStep Checkout for WooCommerce', + 'isActive' => class_exists( 'THWMSCF_Multistep_Checkout' ), + ), + array( + 'name' => 'WooCommerce Subscriptions', + 'isActive' => class_exists( 'WC_Subscriptions' ), + ), + array( + 'name' => 'CartFlows', + 'isActive' => class_exists( 'Cartflows_Loader' ), + ), + array( + 'name' => 'FunnelKit Funnel Builder', + 'isActive' => class_exists( 'WFFN_Core' ), + ), + array( + 'name' => 'WooCommerce One Page Checkout', + 'isActive' => class_exists( 'PP_One_Page_Checkout' ), + ), + array( + 'name' => 'All Products for Woo Subscriptions', + 'isActive' => class_exists( 'WCS_ATT' ), + ), + ) + ); + }, + + 'axo.fastlane-incompatible-plugin-names' => static function ( ContainerInterface $container ) : array { + $incompatible_plugins = $container->get( 'axo.fastlane-incompatible-plugins' ); + + $active_plugins_list = array_filter( + $incompatible_plugins, + function( $plugin ) { + return $plugin['isActive']; + } + ); + + if ( empty( $active_plugins_list ) ) { + return []; + } + + return array_map( + function ( array $plugin ): string { + return "
  • {$plugin['name']}
  • "; + }, + $active_plugins_list + ); + }, ); diff --git a/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php b/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php index 713c9bc2d..72208d566 100644 --- a/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php +++ b/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php @@ -18,6 +18,22 @@ use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; * Class SettingsNoticeGenerator */ class SettingsNoticeGenerator { + /** + * The list of Fastlane incompatible plugin names. + * + * @var string[] + */ + protected $incompatible_plugin_names; + + /** + * SettingsNoticeGenerator constructor. + * + * @param string[] $incompatible_plugin_names The list of Fastlane incompatible plugin names. + */ + public function __construct( array $incompatible_plugin_names ) { + $this->incompatible_plugin_names = $incompatible_plugin_names; + } + /** * Generates the full HTML of the notification. * @@ -95,7 +111,7 @@ class SettingsNoticeGenerator { public function generate_shipping_notice(): string { $shipping_settings_link = admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=options' ); - $notice_content = ''; + $notice_content = 'asd'; if ( wc_shipping_enabled() && wc_ship_to_billing_address_only() ) { $notice_content = sprintf( @@ -117,39 +133,10 @@ class SettingsNoticeGenerator { * @return string */ public function generate_incompatible_plugins_notice(): string { - /** - * Filters the list of Fastlane incompatible plugins. - */ - $incompatible_plugins = apply_filters( - 'woocommerce_paypal_payments_fastlane_incompatible_plugins', - array( - 'Elementor' => did_action( 'elementor/loaded' ), - 'CheckoutWC' => defined( 'CFW_NAME' ), - 'WCDirectCheckout' => defined( 'QLWCDC_PLUGIN_NAME' ), - 'WPMultiStepCheckout' => class_exists( 'WPMultiStepCheckout' ), - 'FluidCheckout' => class_exists( 'FluidCheckout' ), - 'THWMSCF_Multistep_Checkout' => class_exists( 'THWMSCF_Multistep_Checkout' ), - 'WC_Subscriptions' => class_exists( 'WC_Subscriptions' ), - 'Cartflows' => class_exists( 'Cartflows_Loader' ), - 'FunnelKitFunnelBuilder' => class_exists( 'WFFN_Core' ), - 'WCAllProductsForSubscriptions' => class_exists( 'WCS_ATT' ), - 'WCOnePageCheckout' => class_exists( 'PP_One_Page_Checkout' ), - ) - ); - - $active_plugins_list = array_filter( $incompatible_plugins ); - - if ( empty( $active_plugins_list ) ) { + if ( empty( $this->incompatible_plugin_names ) ) { return ''; } - $incompatible_plugin_items = array_map( - function ( $plugin ) { - return "
  • {$plugin}
  • "; - }, - array_keys( $active_plugins_list ) - ); - $plugins_settings_link = esc_url( admin_url( 'plugins.php' ) ); $notice_content = sprintf( /* translators: %1$s: URL to the plugins settings page. %2$s: List of incompatible plugins. */ @@ -158,7 +145,7 @@ class SettingsNoticeGenerator { 'woocommerce-paypal-payments' ), $plugins_settings_link, - implode( '', $incompatible_plugin_items ) + implode( '', $this->incompatible_plugin_names ) ); return '

    ' . $notice_content . '

    '; From cc06b0101ab760021678d98a64d0955231414fad Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 3 Sep 2024 15:05:58 +0400 Subject: [PATCH 082/134] Fix the coding styles --- modules/ppcp-axo/services.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-axo/services.php b/modules/ppcp-axo/services.php index 890029ad5..074e5e63e 100644 --- a/modules/ppcp-axo/services.php +++ b/modules/ppcp-axo/services.php @@ -300,7 +300,7 @@ return array( ); if ( empty( $active_plugins_list ) ) { - return []; + return array(); } return array_map( From 1398c4ac97d9fdf6b8e624969db76a43d48adb1d Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 3 Sep 2024 13:16:43 +0200 Subject: [PATCH 083/134] =?UTF-8?q?=F0=9F=90=9B=20Refactor=20code=20to=20a?= =?UTF-8?q?ddress=20some=20edge=20cases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When user selects a different gateway, enters a phone number, and then switches back to Fastlane: The existing phone number is correctly synced to Fastlane on initial component render. --- modules/ppcp-axo/resources/js/AxoManager.js | 108 +++++++++++++------- 1 file changed, 71 insertions(+), 37 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index 8f2e4afc6..f676ac486 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -42,6 +42,7 @@ class AxoManager { el = null; emailInput = null; + phoneInput = null; shippingView = null; billingView = null; cardView = null; @@ -126,6 +127,9 @@ class AxoManager { } } + this.onChangePhone = this.onChangePhone.bind( this ); + this.initPhoneSyncWooToFastlane(); + this.triggerGatewayChange(); } @@ -494,6 +498,7 @@ class AxoManager { this.initPlacements(); this.initFastlane(); this.setStatus( 'active', true ); + this.setPhoneFromWoo(); log( `Attempt on activation - emailInput: ${ this.emailInput.value }` ); log( @@ -726,6 +731,48 @@ class AxoManager { } } + /** + * Locates the WooCommerce checkout "billing phone" field and adds event listeners to it. + */ + initPhoneSyncWooToFastlane() { + this.phoneInput = document.querySelector( '#billing_phone' ); + this.phoneInput?.addEventListener( 'change', this.onChangePhone ); + } + + /** + * Strips the country prefix and non-numeric characters from the phone number. If the remaining + * phone number is valid, it's returned. Otherwise, the function returns null. + * + * @param {string} number - Phone number to sanitize. + * @return {string|null} A valid US phone number, or null if the number is invalid. + */ + sanitizePhoneNumber( number ) { + const localNumber = number.replace( /^\+1/, '' ); + const cleanNumber = localNumber.replace( /\D/g, '' ); + + // All valid US mobile numbers have exactly 10 digits. + return cleanNumber.length === 10 ? cleanNumber : null; + } + + /** + * Reads the phone number from the WooCommerce checkout form, sanitizes it, and (if valid) + * stores it in the internal customer details object. + */ + setPhoneFromWoo() { + if ( ! this.phoneInput ) { + return; + } + + const phoneNumber = this.phoneInput.value; + const cleanPhoneNumber = this.sanitizePhoneNumber( phoneNumber ); + + if ( ! cleanPhoneNumber ) { + return; + } + + this.data.phone = cleanPhoneNumber; + } + async onChangeEmail() { this.clearData(); @@ -769,6 +816,8 @@ class AxoManager { this.data.email = this.emailInput.value; this.billingView.setData( this.data ); + this.setPhoneFromWoo(); + if ( ! this.fastlane.identity ) { log( 'Not initialized.' ); return; @@ -793,6 +842,22 @@ class AxoManager { this.enableGatewaySelection(); } + /** + * Event handler that fires when the customer changed the phone number in the WooCommerce + * checkout form. If Fastlane is active, the component is refreshed. + * + * @return {Promise} + */ + async onChangePhone() { + this.setPhoneFromWoo(); + + if ( this.status.active ) { + await this.refreshFastlaneComponent(); + } + + return Promise.resolve(); + } + async lookupCustomerByEmail() { const lookupResponse = await this.fastlane.identity.lookupCustomerByEmail( @@ -884,8 +949,6 @@ class AxoManager { this.cardComponent = await this.refreshFastlaneComponent(); } - - this.syncPhoneFromWooToFastlane(); } disableGatewaySelection() { @@ -973,7 +1036,8 @@ class AxoManager { ), }; - if ( this.data.phone ) { + // Ryan is a known customer, we do not need his phone number. + if ( this.data.phone && ! this.isRyanFlow ) { config.fields.phoneNumber = { prefill: this.data.phone, }; @@ -988,6 +1052,10 @@ class AxoManager { * @return {Promise<*>} Resolves when the component was refreshed. */ async refreshFastlaneComponent() { + if ( ! this.status.active ) { + return Promise.resolve(); + } + const elem = this.el.paymentContainer.selector + '-form'; const config = this.cardComponentData(); @@ -1217,40 +1285,6 @@ class AxoManager { this.$( '#billing_email_field input' ).on( 'input', reEnableInput ); this.$( '#billing_email_field input' ).on( 'click', reEnableInput ); } - - syncPhoneFromWooToFastlane() { - // Ryan is a known customer, we do not need his phone number. - if ( this.isRyanFlow ) { - return; - } - - const phoneEl = document.querySelector( '#billing_phone' ); - - if ( ! phoneEl ) { - return; - } - - const sanitizePhoneNumber = ( number ) => { - const localNumber = number.replace( /^\+1/, '' ); - const cleanNumber = localNumber.replace( /\D/g, '' ); - - // All valid US mobile numbers have exactly 10 digits. - return cleanNumber.length === 10 ? cleanNumber : null; - }; - - const onWooPhoneChanged = async ( ev ) => { - const cleanPhoneNumber = sanitizePhoneNumber( ev.target.value ); - - if ( ! cleanPhoneNumber ) { - return; - } - - this.data.phone = cleanPhoneNumber; - await this.refreshFastlaneComponent(); - }; - - phoneEl.addEventListener( 'change', onWooPhoneChanged ); - } } export default AxoManager; From a803467b9634464fcea9aacb5da494fbd1f3a177 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 3 Sep 2024 15:19:38 +0400 Subject: [PATCH 084/134] Fix the coding styles --- modules/ppcp-axo/services.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-axo/services.php b/modules/ppcp-axo/services.php index 074e5e63e..1ad8cfe39 100644 --- a/modules/ppcp-axo/services.php +++ b/modules/ppcp-axo/services.php @@ -294,8 +294,8 @@ return array( $active_plugins_list = array_filter( $incompatible_plugins, - function( $plugin ) { - return $plugin['isActive']; + function( array $plugin ): bool { + return (bool) $plugin['isActive']; } ); From ed98033d104451be3c6c6c380d053d67c7133ecf Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 3 Sep 2024 13:21:25 +0200 Subject: [PATCH 085/134] =?UTF-8?q?=F0=9F=92=AC=20Minor=20changes=20in=20c?= =?UTF-8?q?omment=20&=20variable=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-axo/resources/js/AxoManager.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index f676ac486..a56348e12 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -137,8 +137,7 @@ class AxoManager { * Checks if the current flow is the "Ryan flow": Ryan is a known customer who created a * Fastlane profile before. Ryan can leverage all benefits of the accelerated 1-click checkout. * - * @return {boolean} True means, the Fastlane could link the customer's email to an existing - * account. + * @return {boolean} True means, Fastlane could link the customer's email to an existing account. */ get isRyanFlow() { return !! this.data.card; @@ -764,13 +763,13 @@ class AxoManager { } const phoneNumber = this.phoneInput.value; - const cleanPhoneNumber = this.sanitizePhoneNumber( phoneNumber ); + const validPhoneNumber = this.sanitizePhoneNumber( phoneNumber ); - if ( ! cleanPhoneNumber ) { + if ( ! validPhoneNumber ) { return; } - this.data.phone = cleanPhoneNumber; + this.data.phone = validPhoneNumber; } async onChangeEmail() { From 99101640446abe41a8248006a8370506ab582845 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 3 Sep 2024 14:07:52 +0200 Subject: [PATCH 086/134] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Only=20re-render?= =?UTF-8?q?=20the=20component=20when=20phone=20changed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-axo/resources/js/AxoManager.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index a56348e12..f71fc595e 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -756,20 +756,23 @@ class AxoManager { /** * Reads the phone number from the WooCommerce checkout form, sanitizes it, and (if valid) * stores it in the internal customer details object. + * + * @return {boolean} True, if the internal phone number was updated. */ setPhoneFromWoo() { if ( ! this.phoneInput ) { - return; + return false; } const phoneNumber = this.phoneInput.value; const validPhoneNumber = this.sanitizePhoneNumber( phoneNumber ); if ( ! validPhoneNumber ) { - return; + return false; } this.data.phone = validPhoneNumber; + return true; } async onChangeEmail() { @@ -848,9 +851,9 @@ class AxoManager { * @return {Promise} */ async onChangePhone() { - this.setPhoneFromWoo(); + const hasChanged = this.setPhoneFromWoo(); - if ( this.status.active ) { + if ( hasChanged && this.status.active ) { await this.refreshFastlaneComponent(); } From 8514f3a49cf752d74b41935a1d3850960586fe04 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 3 Sep 2024 16:35:58 +0400 Subject: [PATCH 087/134] Fix the coding styles --- modules/ppcp-axo/services.php | 48 +++++++++---------- .../src/Helper/SettingsNoticeGenerator.php | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/modules/ppcp-axo/services.php b/modules/ppcp-axo/services.php index 1ad8cfe39..b860eab15 100644 --- a/modules/ppcp-axo/services.php +++ b/modules/ppcp-axo/services.php @@ -232,7 +232,7 @@ return array( /** * The list of Fastlane incompatible plugins. * - * @returns array + * @returns array */ 'axo.fastlane-incompatible-plugins' => static function () : array { /** @@ -242,48 +242,48 @@ return array( 'woocommerce_paypal_payments_fastlane_incompatible_plugins', array( array( - 'name' => 'Elementor', - 'isActive' => did_action( 'elementor/loaded' ), + 'name' => 'Elementor', + 'is_active' => did_action( 'elementor/loaded' ), ), array( - 'name' => 'CheckoutWC', - 'isActive' => defined( 'CFW_NAME' ), + 'name' => 'CheckoutWC', + 'is_active' => defined( 'CFW_NAME' ), ), array( - 'name' => 'Direct Checkout for WooCommerce', - 'isActive' => defined( 'QLWCDC_PLUGIN_NAME' ), + 'name' => 'Direct Checkout for WooCommerce', + 'is_active' => defined( 'QLWCDC_PLUGIN_NAME' ), ), array( - 'name' => 'Multi-Step Checkout for WooCommerce', - 'isActive' => class_exists( 'WPMultiStepCheckout' ), + 'name' => 'Multi-Step Checkout for WooCommerce', + 'is_active' => class_exists( 'WPMultiStepCheckout' ), ), array( - 'name' => 'Fluid Checkout for WooCommerce', - 'isActive' => class_exists( 'FluidCheckout' ), + 'name' => 'Fluid Checkout for WooCommerce', + 'is_active' => class_exists( 'FluidCheckout' ), ), array( - 'name' => 'MultiStep Checkout for WooCommerce', - 'isActive' => class_exists( 'THWMSCF_Multistep_Checkout' ), + 'name' => 'MultiStep Checkout for WooCommerce', + 'is_active' => class_exists( 'THWMSCF_Multistep_Checkout' ), ), array( - 'name' => 'WooCommerce Subscriptions', - 'isActive' => class_exists( 'WC_Subscriptions' ), + 'name' => 'WooCommerce Subscriptions', + 'is_active' => class_exists( 'WC_Subscriptions' ), ), array( - 'name' => 'CartFlows', - 'isActive' => class_exists( 'Cartflows_Loader' ), + 'name' => 'CartFlows', + 'is_active' => class_exists( 'Cartflows_Loader' ), ), array( - 'name' => 'FunnelKit Funnel Builder', - 'isActive' => class_exists( 'WFFN_Core' ), + 'name' => 'FunnelKit Funnel Builder', + 'is_active' => class_exists( 'WFFN_Core' ), ), array( - 'name' => 'WooCommerce One Page Checkout', - 'isActive' => class_exists( 'PP_One_Page_Checkout' ), + 'name' => 'WooCommerce One Page Checkout', + 'is_active' => class_exists( 'PP_One_Page_Checkout' ), ), array( - 'name' => 'All Products for Woo Subscriptions', - 'isActive' => class_exists( 'WCS_ATT' ), + 'name' => 'All Products for Woo Subscriptions', + 'is_active' => class_exists( 'WCS_ATT' ), ), ) ); @@ -295,7 +295,7 @@ return array( $active_plugins_list = array_filter( $incompatible_plugins, function( array $plugin ): bool { - return (bool) $plugin['isActive']; + return (bool) $plugin['is_active']; } ); diff --git a/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php b/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php index 72208d566..d4d4cb824 100644 --- a/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php +++ b/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php @@ -111,7 +111,7 @@ class SettingsNoticeGenerator { public function generate_shipping_notice(): string { $shipping_settings_link = admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=options' ); - $notice_content = 'asd'; + $notice_content = ''; if ( wc_shipping_enabled() && wc_ship_to_billing_address_only() ) { $notice_content = sprintf( From f1480fac133b4faba1f7efdf762c4a8c7ab37f9f Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Tue, 3 Sep 2024 16:21:34 +0300 Subject: [PATCH 088/134] Update versions in phpcs --- phpcs.xml.dist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 8e32114f5..d8661df81 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -3,8 +3,8 @@ WooCommerce PayPal Payments ruleset. - - + + From 4462fb38c9697ba0569935018a56e1186b3d58d6 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Tue, 3 Sep 2024 16:23:11 +0300 Subject: [PATCH 089/134] Update FilePathPluginFactory defaults --- src/FilePathPluginFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FilePathPluginFactory.php b/src/FilePathPluginFactory.php index 15f4f761d..f561b14d5 100644 --- a/src/FilePathPluginFactory.php +++ b/src/FilePathPluginFactory.php @@ -82,8 +82,8 @@ class FilePathPluginFactory implements FilePathPluginFactoryInterface { 'Title' => '', 'Description' => '', 'TextDomain' => '', - 'RequiresWP' => '5.0', - 'RequiresPHP' => '7.2', + 'RequiresWP' => '6.3', + 'RequiresPHP' => '7.4', ), $plugin_data ); From d7f0b693e33c486365ec509247b2684371ed7bbd Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 3 Sep 2024 17:35:36 +0200 Subject: [PATCH 090/134] =?UTF-8?q?=E2=9C=A8=20Define=20generic=20size=20f?= =?UTF-8?q?or=20payment=20gateway=20icons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-button/resources/css/hosted-fields.scss | 9 ++++----- modules/ppcp-googlepay/resources/css/styles.scss | 6 ------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/modules/ppcp-button/resources/css/hosted-fields.scss b/modules/ppcp-button/resources/css/hosted-fields.scss index 578a70a09..54482b573 100644 --- a/modules/ppcp-button/resources/css/hosted-fields.scss +++ b/modules/ppcp-button/resources/css/hosted-fields.scss @@ -1,11 +1,10 @@ -#payment ul.payment_methods li img.ppcp-card-icon { - padding: 0 0 3px 3px; - max-height: 25px; - display: inline-block; +#payment ul.payment_methods [class*="payment_method_ppcp-"] label img { + max-height: 25px; + display: inline-block; } .payments-sdk-contingency-handler { - z-index: 1000 !important; + z-index: 1000 !important; } .ppcp-credit-card-gateway-form-field-disabled { diff --git a/modules/ppcp-googlepay/resources/css/styles.scss b/modules/ppcp-googlepay/resources/css/styles.scss index c1eae1563..6cf2119a0 100644 --- a/modules/ppcp-googlepay/resources/css/styles.scss +++ b/modules/ppcp-googlepay/resources/css/styles.scss @@ -17,9 +17,3 @@ #ppc-button-ppcp-googlepay { display: none; } - -label[for='payment_method_ppcp-googlepay'] { - img { - max-height: 25px; - } -} From 27e8b06b29268773e3c8af3b7aca6d9e76bc4a23 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 3 Sep 2024 18:16:10 +0200 Subject: [PATCH 091/134] =?UTF-8?q?=F0=9F=90=9B=20Update=20ApplePay=20logo?= =?UTF-8?q?=20in=20gateway?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-applepay/src/ApplePayGateway.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-applepay/src/ApplePayGateway.php b/modules/ppcp-applepay/src/ApplePayGateway.php index 7c87258f9..3ee57ee96 100644 --- a/modules/ppcp-applepay/src/ApplePayGateway.php +++ b/modules/ppcp-applepay/src/ApplePayGateway.php @@ -112,7 +112,7 @@ class ApplePayGateway extends WC_Payment_Gateway { $this->description = $this->get_option( 'description', '' ); $this->module_url = $module_url; - $this->icon = esc_url( $this->module_url ) . 'assets/images/applepay.png'; + $this->icon = esc_url( $this->module_url ) . 'assets/images/applepay.svg'; $this->init_form_fields(); $this->init_settings(); From 38adb9bb2184cc91fe37e5633033444fc762e288 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Wed, 4 Sep 2024 08:19:33 +0300 Subject: [PATCH 092/134] Remove disabled before triggering save button click --- modules/ppcp-onboarding/resources/js/onboarding.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-onboarding/resources/js/onboarding.js b/modules/ppcp-onboarding/resources/js/onboarding.js index 905c66c65..5a6ab333a 100644 --- a/modules/ppcp-onboarding/resources/js/onboarding.js +++ b/modules/ppcp-onboarding/resources/js/onboarding.js @@ -326,7 +326,9 @@ window.ppcp_onboarding_productionCallback = function ( ...args ) { isDisconnecting = true; - document.querySelector( '.woocommerce-save-button' ).click(); + const saveButton = document.querySelector( '.woocommerce-save-button' ); + saveButton.removeAttribute( 'disabled' ); + saveButton.click(); }; // Prevent the message about unsaved checkbox/radiobutton when reloading the page. From dfc047a2eb3952f98f41de2bc6af1038cd19639d Mon Sep 17 00:00:00 2001 From: Alex Pantechovskis Date: Wed, 4 Sep 2024 09:40:37 +0300 Subject: [PATCH 093/134] Keep only 5 tags in readme.txt wp .org now allows only 5 tags. --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 180629a68..ef1fc2f14 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ === WooCommerce PayPal Payments === Contributors: woocommerce, automattic, syde -Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple pay, subscriptions, debit card, credit card, google pay +Tags: woocommerce, paypal, payments, ecommerce, credit card Requires at least: 5.3 Tested up to: 6.6 Requires PHP: 7.2 From b3a05ae3d8667d56ebe1e8f98ecf3e0ec096406f Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 4 Sep 2024 12:02:23 +0200 Subject: [PATCH 094/134] =?UTF-8?q?=F0=9F=90=9B=20Fix=20bug=20with=20defau?= =?UTF-8?q?ltShippingId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/GooglepayButton.js | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 3e1fc2eb4..98e22f55b 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -557,19 +557,23 @@ class GooglepayButton extends PaymentButton { * @return {Object} Sanitized object. */ sanitizeShippingOptions( responseData ) { - const cleanOptions = []; + // Sanitize the shipping options. + const cleanOptions = responseData.shippingOptions.map( ( item ) => ( { + id: item.id, + label: item.label, + description: item.description, + } ) ); - responseData.shippingOptions.forEach( ( item ) => { - cleanOptions.push( { - id: item.id, - label: item.label, - description: item.description, - } ); - } ); + // Ensure that the default option is valid. + let defaultOptionId = responseData.defaultSelectedOptionId; + if ( ! cleanOptions.some( ( item ) => item.id === defaultOptionId ) ) { + defaultOptionId = cleanOptions[ 0 ].id; + } - responseData.shippingOptions = cleanOptions; - - return { ...responseData, shippingOptions: cleanOptions }; + return { + defaultSelectedOptionId: defaultOptionId, + shippingOptions: cleanOptions, + }; } /** From c72c97f8218dcbb54d612f64a5eddf512c7430e3 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 4 Sep 2024 15:06:50 +0200 Subject: [PATCH 095/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Rename=20a=20funct?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-axo/resources/js/AxoManager.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index f71fc595e..be8d2beac 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -27,9 +27,10 @@ class AxoManager { ppcpConfig = null; $ = null; + fastlane = null; + initialized = false; hideGatewaySelection = false; - fastlane = null; phoneNumber = null; /** @@ -497,7 +498,7 @@ class AxoManager { this.initPlacements(); this.initFastlane(); this.setStatus( 'active', true ); - this.setPhoneFromWoo(); + this.readPhoneFromWoo(); log( `Attempt on activation - emailInput: ${ this.emailInput.value }` ); log( @@ -759,7 +760,7 @@ class AxoManager { * * @return {boolean} True, if the internal phone number was updated. */ - setPhoneFromWoo() { + readPhoneFromWoo() { if ( ! this.phoneInput ) { return false; } @@ -818,7 +819,7 @@ class AxoManager { this.data.email = this.emailInput.value; this.billingView.setData( this.data ); - this.setPhoneFromWoo(); + this.readPhoneFromWoo(); if ( ! this.fastlane.identity ) { log( 'Not initialized.' ); @@ -851,7 +852,7 @@ class AxoManager { * @return {Promise} */ async onChangePhone() { - const hasChanged = this.setPhoneFromWoo(); + const hasChanged = this.readPhoneFromWoo(); if ( hasChanged && this.status.active ) { await this.refreshFastlaneComponent(); From 5e08e415f006b8650a5acc6d53ddc0e53b329cea Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 4 Sep 2024 15:11:03 +0200 Subject: [PATCH 096/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Consolidate=20logi?= =?UTF-8?q?c=20to=20initialize=20Fastlane=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-axo/resources/js/AxoManager.js | 27 ++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index be8d2beac..e7856b661 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -28,6 +28,10 @@ class AxoManager { $ = null; fastlane = null; + /** + * @type {FastlaneCardComponent} + */ + cardComponent = null; initialized = false; hideGatewaySelection = false; @@ -855,7 +859,7 @@ class AxoManager { const hasChanged = this.readPhoneFromWoo(); if ( hasChanged && this.status.active ) { - await this.refreshFastlaneComponent(); + await this.initializeFastlaneComponent(); } return Promise.resolve(); @@ -896,7 +900,7 @@ class AxoManager { if ( authResponse.profileData.card ) { this.setStatus( 'hasCard', true ); } else { - this.cardComponent = await this.refreshFastlaneComponent(); + await this.initializeFastlaneComponent(); } const cardBillingAddress = @@ -937,8 +941,7 @@ class AxoManager { this.setStatus( 'hasProfile', false ); await this.renderWatermark( true ); - - this.cardComponent = await this.refreshFastlaneComponent(); + await this.initializeFastlaneComponent(); } } else { // No profile found with this email address. @@ -949,8 +952,7 @@ class AxoManager { this.setStatus( 'hasProfile', false ); await this.renderWatermark( true ); - - this.cardComponent = await this.refreshFastlaneComponent(); + await this.initializeFastlaneComponent(); } } @@ -1050,11 +1052,12 @@ class AxoManager { } /** - * Refreshes the Fastlane UI component, using configuration provided by the `cardComponentData()` method. + * Initializes the Fastlane UI component, using configuration provided by the + * `cardComponentData()` method. If the UI component was already initialized, nothing happens. * - * @return {Promise<*>} Resolves when the component was refreshed. + * @return {Promise<*>} Resolves when the component was rendered. */ - async refreshFastlaneComponent() { + async initializeFastlaneComponent() { if ( ! this.status.active ) { return Promise.resolve(); } @@ -1062,8 +1065,10 @@ class AxoManager { const elem = this.el.paymentContainer.selector + '-form'; const config = this.cardComponentData(); - const component = await this.fastlane.FastlaneCardComponent( config ); - return component.render( elem ); + this.cardComponent = + await this.fastlane.FastlaneCardComponent( config ); + + return this.cardComponent.render( elem ); } tokenizeData() { From ad2181fd0963eb8b951ceb3f9677a6988454197d Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 4 Sep 2024 15:11:46 +0200 Subject: [PATCH 097/134] =?UTF-8?q?=E2=9C=A8=20Add=20logic=20to=20update?= =?UTF-8?q?=20prefill-values?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-axo/resources/js/AxoManager.js | 27 +++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index e7856b661..3144d28a1 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -513,6 +513,8 @@ class AxoManager { this.lastEmailCheckedIdentity !== this.emailInput.value ) { this.onChangeEmail(); + } else { + this.refreshFastlanePrefills(); } } @@ -859,7 +861,7 @@ class AxoManager { const hasChanged = this.readPhoneFromWoo(); if ( hasChanged && this.status.active ) { - await this.initializeFastlaneComponent(); + await this.refreshFastlanePrefills(); } return Promise.resolve(); @@ -1058,7 +1060,7 @@ class AxoManager { * @return {Promise<*>} Resolves when the component was rendered. */ async initializeFastlaneComponent() { - if ( ! this.status.active ) { + if ( ! this.status.active || this.cardComponent ) { return Promise.resolve(); } @@ -1071,6 +1073,27 @@ class AxoManager { return this.cardComponent.render( elem ); } + /** + * Updates the prefill-values in the UI component. This method only updates empty fields. + * + * @return {Promise<*>} Resolves when the component was refreshed. + */ + async refreshFastlanePrefills() { + if ( ! this.cardComponent ) { + return Promise.resolve(); + } + + const { fields } = this.cardComponentData(); + const prefills = Object.keys( fields ).reduce( ( result, key ) => { + if ( fields[ key ].hasOwnProperty( 'prefill' ) ) { + result[ key ] = fields[ key ].prefill; + } + return result; + }, {} ); + + return this.cardComponent.updatePrefills( prefills ); + } + tokenizeData() { return { cardholderName: { From c9486c4c1769e8d12afb16577cf29f2e205b0917 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 4 Sep 2024 16:05:48 +0200 Subject: [PATCH 098/134] Update platform requirement See fa36ff33ff3704d813186cd939a222086402ddb4 --- composer.json | 2 +- composer.lock | 1538 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 1126 insertions(+), 414 deletions(-) diff --git a/composer.json b/composer.json index 5a67ee63e..4d4b9f2f2 100644 --- a/composer.json +++ b/composer.json @@ -96,7 +96,7 @@ }, "config": { "platform": { - "php": "7.2" + "php": "7.4" }, "allow-plugins": { "inpsyde/composer-assets-compiler": true, diff --git a/composer.lock b/composer.lock index e3a275ffd..a18b56927 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": "4ada1f9416971ef72b0587ca34b32cc1", + "content-hash": "2fa610ed883c0868838d3008b7127cbf", "packages": [ { "name": "container-interop/service-provider", @@ -296,20 +296,20 @@ }, { "name": "psr/container", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=7.4.0" }, "type": "library", "autoload": { @@ -338,9 +338,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" + "source": "https://github.com/php-fig/container/tree/1.1.2" }, - "time": "2021-03-05T17:36:06+00:00" + "time": "2021-11-05T16:50:12+00:00" }, { "name": "psr/log", @@ -979,30 +979,38 @@ }, { "name": "composer/pcre", - "version": "1.0.1", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" }, "require-dev": { - "phpstan/phpstan": "^1.3", + "phpstan/phpstan": "^1.11.10", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.x-dev" + "dev-main": "3.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "autoload": { @@ -1030,7 +1038,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/1.0.1" + "source": "https://github.com/composer/pcre/tree/3.3.1" }, "funding": [ { @@ -1046,7 +1054,7 @@ "type": "tidelift" } ], - "time": "2022-01-21T20:24:37+00:00" + "time": "2024-08-27T18:44:43+00:00" }, { "name": "composer/semver", @@ -1131,27 +1139,27 @@ }, { "name": "composer/xdebug-handler", - "version": "2.0.5", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", "shasum": "" }, "require": { - "composer/pcre": "^1", - "php": "^5.3.2 || ^7.0 || ^8.0", + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", "psr/log": "^1 || ^2 || ^3" }, "require-dev": { "phpstan/phpstan": "^1.0", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" }, "type": "library", "autoload": { @@ -1175,9 +1183,9 @@ "performance" ], "support": { - "irc": "irc://irc.freenode.org/composer", + "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" }, "funding": [ { @@ -1193,7 +1201,7 @@ "type": "tidelift" } ], - "time": "2022-02-24T20:20:32+00:00" + "time": "2024-05-06T16:37:16+00:00" }, { "name": "dealerdirect/phpcodesniffer-composer-installer", @@ -1327,30 +1335,30 @@ }, { "name": "dhii/containers", - "version": "v0.1.4", + "version": "v0.1.5", "source": { "type": "git", "url": "https://github.com/Dhii/containers.git", - "reference": "42ab24683183fa0dc155f26c6a470ef697bbdc9a" + "reference": "1568cb2def9dee213c5846c4618f9d6b2cebbdef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Dhii/containers/zipball/42ab24683183fa0dc155f26c6a470ef697bbdc9a", - "reference": "42ab24683183fa0dc155f26c6a470ef697bbdc9a", + "url": "https://api.github.com/repos/Dhii/containers/zipball/1568cb2def9dee213c5846c4618f9d6b2cebbdef", + "reference": "1568cb2def9dee213c5846c4618f9d6b2cebbdef", "shasum": "" }, "require": { "container-interop/service-provider": "^0.4", "dhii/collections-interface": "^0.3.0-alpha4", - "php": "^7.1 | ^8.0" + "php": "^7.4 | ^8.0" }, "require-dev": { "gmazzap/andrew": "^1.1", - "phpunit/phpunit": "^7.0 | ^8.0 | ^9.0", + "phpunit/phpunit": "^9.0", "psr/container": "^1.0", "psr/simple-cache": "^1.0", "slevomat/coding-standard": "^6.0", - "vimeo/psalm": "^4.0", + "vimeo/psalm": "^5.0", "wildwolf/psr-memory-cache": "^1.0" }, "type": "library", @@ -1381,9 +1389,9 @@ ], "support": { "issues": "https://github.com/Dhii/containers/issues", - "source": "https://github.com/Dhii/containers/tree/v0.1.4" + "source": "https://github.com/Dhii/containers/tree/v0.1.5" }, - "time": "2021-10-06T11:13:51+00:00" + "time": "2024-04-27T01:55:40+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -1422,6 +1430,53 @@ }, "time": "2019-12-04T15:06:13+00:00" }, + { + "name": "doctrine/deprecations", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + }, + "time": "2024-01-30T19:34:25+00:00" + }, { "name": "doctrine/instantiator", "version": "1.5.0", @@ -1595,24 +1650,24 @@ }, { "name": "graham-campbell/result-type", - "version": "v1.0.4", + "version": "v1.1.3", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "0690bde05318336c7221785f2a932467f98b64ca" + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/0690bde05318336c7221785f2a932467f98b64ca", - "reference": "0690bde05318336c7221785f2a932467f98b64ca", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", "shasum": "" }, "require": { - "php": "^7.0 || ^8.0", - "phpoption/phpoption": "^1.8" + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3" }, "require-dev": { - "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "autoload": { @@ -1641,7 +1696,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.4" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" }, "funding": [ { @@ -1653,7 +1708,7 @@ "type": "tidelift" } ], - "time": "2021-11-21T21:41:47+00:00" + "time": "2024-07-20T21:45:45+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -1773,31 +1828,31 @@ }, { "name": "inpsyde/modularity", - "version": "1.8.0", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/inpsyde/modularity.git", - "reference": "c6855a6d9c4ce6f090d031e820f176bddf2a0b1c" + "reference": "2119d0e32706741a3c6dc0a85d908ec19ebf142e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/inpsyde/modularity/zipball/c6855a6d9c4ce6f090d031e820f176bddf2a0b1c", - "reference": "c6855a6d9c4ce6f090d031e820f176bddf2a0b1c", + "url": "https://api.github.com/repos/inpsyde/modularity/zipball/2119d0e32706741a3c6dc0a85d908ec19ebf142e", + "reference": "2119d0e32706741a3c6dc0a85d908ec19ebf142e", "shasum": "" }, "require": { "ext-json": "*", - "php": ">=7.2", + "php": ">=7.4 <8.4", "psr/container": "^1.1.0 || ^2" }, "require-dev": { "brain/monkey": "^2.6.1", - "inpsyde/php-coding-standards": "^1", - "johnpbloch/wordpress-core": ">=5.8", - "mikey179/vfsstream": "^v1.6.10", - "php-stubs/wordpress-stubs": ">=5.8@stable", - "phpunit/phpunit": "^8.5.21 || ^9.6.7", - "vimeo/psalm": "^4.13.1" + "inpsyde/php-coding-standards": "^2@dev", + "inpsyde/wp-stubs-versions": "dev-latest", + "mikey179/vfsstream": "^v1.6.11", + "phpunit/phpunit": "^9.6.19", + "roots/wordpress-no-content": "@dev", + "vimeo/psalm": "^5.24.0" }, "type": "library", "extra": { @@ -1820,56 +1875,49 @@ "email": "hello@inpsyde.com", "homepage": "https://inpsyde.com/", "role": "Company" - }, - { - "name": "Christian Leucht", - "email": "c.leucht@inpsyde.com", - "role": "Developer" - }, - { - "name": "Giuseppe Mazzapica", - "email": "g.mazzapica@inpsyde.com", - "role": "Developer" } ], "description": "Modular PSR-11 implementation for WordPress plugins, themes or libraries.", "support": { "issues": "https://github.com/inpsyde/modularity/issues", - "source": "https://github.com/inpsyde/modularity/tree/1.8.0" + "source": "https://github.com/inpsyde/modularity/tree/1.10.0" }, - "time": "2024-05-14T06:07:35+00:00" + "time": "2024-09-03T10:42:50+00:00" }, { "name": "mockery/mockery", - "version": "1.3.6", + "version": "1.6.12", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "dc206df4fa314a50bbb81cf72239a305c5bbd5c0" + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/dc206df4fa314a50bbb81cf72239a305c5bbd5c0", - "reference": "dc206df4fa314a50bbb81cf72239a305c5bbd5c0", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", "shasum": "" }, "require": { "hamcrest/hamcrest-php": "^2.0.1", "lib-pcre": ">=7.0", - "php": ">=5.6.0" + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^5.7.10|^6.5|^7.5|^8.5|^9.3" + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, "autoload": { - "psr-0": { - "Mockery": "library/" + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" } }, "notification-url": "https://packagist.org/downloads/", @@ -1880,12 +1928,20 @@ { "name": "Pádraic Brady", "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" + "homepage": "https://github.com/padraic", + "role": "Author" }, { "name": "Dave Marshall", "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "http://davedevelopment.co.uk" + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" } ], "description": "Mockery is a simple yet flexible PHP mock object framework", @@ -1903,10 +1959,13 @@ "testing" ], "support": { + "docs": "https://docs.mockery.io/", "issues": "https://github.com/mockery/mockery/issues", - "source": "https://github.com/mockery/mockery/tree/1.3.6" + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" }, - "time": "2022-09-07T15:05:49+00:00" + "time": "2024-05-16T03:13:13+00:00" }, { "name": "myclabs/deep-copy", @@ -2596,28 +2655,35 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", + "version": "5.4.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.1", "ext-filter": "*", - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" }, "type": "library", "extra": { @@ -2641,37 +2707,45 @@ }, { "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" + "email": "opensource@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" }, - "time": "2021-10-19T17:43:47+00:00" + "time": "2024-05-21T05:55:05+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.6.1", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" + "reference": "153ae662783729388a584b4361f2545e4d841e3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" }, "require-dev": { "ext-tokenizer": "*", - "psalm/phar": "^4.8" + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" }, "type": "library", "extra": { @@ -2697,35 +2771,39 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" }, - "time": "2022-03-15T21:29:03+00:00" + "time": "2024-02-23T11:10:43+00:00" }, { "name": "phpoption/phpoption", - "version": "1.8.1", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15" + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15", - "reference": "eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", "shasum": "" }, "require": { - "php": "^7.0 || ^8.0" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", - "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, "branch-alias": { - "dev-master": "1.8-dev" + "dev-master": "1.9-dev" } }, "autoload": { @@ -2758,7 +2836,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.8.1" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" }, "funding": [ { @@ -2770,44 +2848,95 @@ "type": "tidelift" } ], - "time": "2021-12-04T23:24:31+00:00" + "time": "2024-07-20T21:41:07+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "7.0.17", + "name": "phpstan/phpdoc-parser", + "version": "1.30.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66" + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", - "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/5ceb0e384997db59f38774bf79c2a6134252c08f", + "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.30.0" + }, + "time": "2024-08-29T09:54:52+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.32", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-xmlwriter": "*", - "php": ">=7.2", - "phpunit/php-file-iterator": "^2.0.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.1.3 || ^4.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^4.2.2", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1.3" + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^8.2.2" + "phpunit/phpunit": "^9.6" }, "suggest": { - "ext-xdebug": "^2.7.2" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "7.0-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -2835,7 +2964,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.17" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -2843,32 +2973,32 @@ "type": "github" } ], - "time": "2024-03-02T06:09:37+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "2.0.6", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "69deeb8664f611f156a924154985fbd4911eb36b" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/69deeb8664f611f156a924154985fbd4911eb36b", - "reference": "69deeb8664f611f156a924154985fbd4911eb36b", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2895,7 +3025,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.6" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, "funding": [ { @@ -2903,26 +3033,97 @@ "type": "github" } ], - "time": "2024-03-01T13:39:50+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "phpunit/php-invoker", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -2946,34 +3147,40 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" }, - "time": "2015-06-21T13:50:34+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" }, { "name": "phpunit/php-timer", - "version": "2.1.4", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb" + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a691211e94ff39a34811abd521c31bd5b305b0bb", - "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2999,7 +3206,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.4" + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" }, "funding": [ { @@ -3007,84 +3214,24 @@ "type": "github" } ], - "time": "2024-03-01T13:42:41+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "3.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9c1da83261628cb24b6a6df371b6e312b3954768", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", - "source": "https://github.com/sebastianbergmann/php-token-stream/tree/3.1.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "abandoned": true, - "time": "2021-07-26T12:15:06+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/phpunit", - "version": "8.5.39", + "version": "9.6.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "172ba97bcf97ae6ef86ca256adf77aece8a143fe" + "reference": "49d7820565836236411f5dc002d16dd689cde42f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/172ba97bcf97ae6ef86ca256adf77aece8a143fe", - "reference": "172ba97bcf97ae6ef86ca256adf77aece8a143fe", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/49d7820565836236411f5dc002d16dd689cde42f", + "reference": "49d7820565836236411f5dc002d16dd689cde42f", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.5.0", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -3094,25 +3241,27 @@ "myclabs/deep-copy": "^1.12.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=7.2", - "phpunit/php-code-coverage": "^7.0.17", - "phpunit/php-file-iterator": "^2.0.6", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1.4", - "sebastian/comparator": "^3.0.5", - "sebastian/diff": "^3.0.6", - "sebastian/environment": "^4.2.5", - "sebastian/exporter": "^3.1.6", - "sebastian/global-state": "^3.0.5", - "sebastian/object-enumerator": "^3.0.5", - "sebastian/resource-operations": "^2.0.3", - "sebastian/type": "^1.1.5", - "sebastian/version": "^2.0.1" + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.31", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", + "sebastian/version": "^3.0.2" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage", - "phpunit/php-invoker": "To allow enforcing time limits" + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -3120,10 +3269,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "8.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -3149,7 +3301,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.39" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.20" }, "funding": [ { @@ -3165,32 +3317,144 @@ "type": "tidelift" } ], - "time": "2024-07-10T11:43:00+00:00" + "time": "2024-07-10T11:45:39+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.3", + "name": "sebastian/cli-parser", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", - "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:27:43+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" } }, "autoload": { @@ -3212,7 +3476,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.3" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" }, "funding": [ { @@ -3220,34 +3484,34 @@ "type": "github" } ], - "time": "2024-03-01T13:45:45+00:00" + "time": "2020-09-28T05:30:19+00:00" }, { "name": "sebastian/comparator", - "version": "3.0.5", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { - "php": ">=7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3286,7 +3550,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -3294,33 +3558,90 @@ "type": "github" } ], - "time": "2022-09-14T12:31:48+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { - "name": "sebastian/diff", - "version": "3.0.6", + "name": "sebastian/complexity", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/98ff311ca519c3aa73ccd3de053bdb377171d7b6", - "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", "shasum": "" }, "require": { - "php": ">=7.1" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -3352,7 +3673,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/3.0.6" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -3360,27 +3681,27 @@ "type": "github" } ], - "time": "2024-03-02T06:16:36+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", - "version": "4.2.5", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "56932f6049a0482853056ffd617c91ffcc754205" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/56932f6049a0482853056ffd617c91ffcc754205", - "reference": "56932f6049a0482853056ffd617c91ffcc754205", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.5" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-posix": "*" @@ -3388,7 +3709,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -3415,7 +3736,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/4.2.5" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -3423,34 +3744,34 @@ "type": "github" } ], - "time": "2024-03-01T13:49:59+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.6", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56" + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1939bc8fd1d39adcfa88c5b35335910869214c56", - "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { - "php": ">=7.2", - "sebastian/recursion-context": "^3.0" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3485,14 +3806,14 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" }, "funding": [ { @@ -3500,30 +3821,30 @@ "type": "github" } ], - "time": "2024-03-02T06:21:38+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { "name": "sebastian/global-state", - "version": "3.0.5", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9" + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/91c7c47047a971f02de57ed6f040087ef110c5d9", - "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { - "php": ">=7.2", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^8.0" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-uopz": "*" @@ -3531,7 +3852,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -3556,7 +3877,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" }, "funding": [ { @@ -3564,34 +3885,91 @@ "type": "github" } ], - "time": "2024-03-02T06:13:16+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "3.0.5", + "name": "sebastian/lines-of-code", + "version": "1.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "ac5b293dba925751b808e02923399fb44ff0d541" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/ac5b293dba925751b808e02923399fb44ff0d541", - "reference": "ac5b293dba925751b808e02923399fb44ff0d541", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", "shasum": "" }, "require": { - "php": ">=7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -3613,7 +3991,7 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" }, "funding": [ { @@ -3621,32 +3999,32 @@ "type": "github" } ], - "time": "2024-03-01T13:54:02+00:00" + "time": "2020-10-26T13:12:34+00:00" }, { "name": "sebastian/object-reflector", - "version": "1.1.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "1d439c229e61f244ff1f211e5c99737f90c67def" + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/1d439c229e61f244ff1f211e5c99737f90c67def", - "reference": "1d439c229e61f244ff1f211e5c99737f90c67def", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { - "php": ">=7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -3668,7 +4046,7 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.3" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" }, "funding": [ { @@ -3676,32 +4054,32 @@ "type": "github" } ], - "time": "2024-03-01T13:56:04+00:00" + "time": "2020-10-26T13:14:26+00:00" }, { "name": "sebastian/recursion-context", - "version": "3.0.2", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/9bfd3c6f1f08c026f542032dfb42813544f7d64c", - "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { - "php": ">=7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3728,10 +4106,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -3739,29 +4117,32 @@ "type": "github" } ], - "time": "2024-03-01T14:07:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", - "version": "2.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/72a7f7674d053d548003b16ff5a106e7e0e06eee", - "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3782,7 +4163,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.3" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -3790,32 +4171,32 @@ "type": "github" } ], - "time": "2024-03-01T13:59:09+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", - "version": "1.1.5", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/18f071c3a29892b037d35e6b20ddf3ea39b42874", - "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^8.2" + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3838,7 +4219,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/1.1.5" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -3846,29 +4227,29 @@ "type": "github" } ], - "time": "2024-03-01T14:04:07+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3891,9 +4272,15 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/master" + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" }, - "time": "2016-10-03T07:35:21+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -3977,43 +4364,46 @@ }, { "name": "symfony/console", - "version": "v4.4.49", + "version": "v5.4.43", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9" + "reference": "e86f8554de667c16dde8aeb89a3990cfde924df9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", - "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", + "url": "https://api.github.com/repos/symfony/console/zipball/e86f8554de667c16dde8aeb89a3990cfde924df9", + "reference": "e86f8554de667c16dde8aeb89a3990cfde924df9", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2" + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" }, "conflict": { "psr/log": ">=3", - "symfony/dependency-injection": "<3.4", - "symfony/event-dispatcher": "<4.3|>=5", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", "symfony/lock": "<4.4", - "symfony/process": "<3.3" + "symfony/process": "<4.4" }, "provide": { "psr/log-implementation": "1.0|2.0" }, "require-dev": { "psr/log": "^1|^2", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/event-dispatcher": "^4.3", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", - "symfony/var-dumper": "^4.3|^5.0" + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" }, "suggest": { "psr/log": "For using the console logger", @@ -4046,8 +4436,14 @@ ], "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], "support": { - "source": "https://github.com/symfony/console/tree/v4.4.49" + "source": "https://github.com/symfony/console/tree/v5.4.43" }, "funding": [ { @@ -4063,7 +4459,74 @@ "type": "tidelift" } ], - "time": "2022-11-05T17:10:16+00:00" + "time": "2024-08-13T16:31:56+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "80d075412b557d41002320b96a096ca65aa2c98d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/80d075412b557d41002320b96a096ca65aa2c98d", + "reference": "80d075412b557d41002320b96a096ca65aa2c98d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.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-01-24T14:02:46+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4144,6 +4607,165 @@ ], "time": "2024-05-31T15:07:36+00:00" }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" + }, + "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": "2024-05-31T15:07:36+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" + }, + "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": "2024-05-31T15:07:36+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.30.0", @@ -4302,21 +4924,25 @@ }, { "name": "symfony/service-contracts", - "version": "v1.10.0", + "version": "v2.5.3", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "afa00c500c2d6aea6e3b2f4862355f507bc5ebb4" + "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/afa00c500c2d6aea6e3b2f4862355f507bc5ebb4", - "reference": "afa00c500c2d6aea6e3b2f4862355f507bc5ebb4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a2329596ddc8fd568900e3fc76cba42489ecc7f3", + "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3", "shasum": "" }, "require": { - "php": ">=7.1.3", - "psr/container": "^1.0" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" }, "suggest": { "symfony/service-implementation": "" @@ -4324,7 +4950,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.1-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -4361,7 +4987,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v1.10.0" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.3" }, "funding": [ { @@ -4377,7 +5003,93 @@ "type": "tidelift" } ], - "time": "2022-05-27T14:01:05+00:00" + "time": "2023-04-21T15:04:16+00:00" + }, + { + "name": "symfony/string", + "version": "v5.4.43", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "8be1d484951ff5ca995eaf8edcbcb8b9a5888450" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/8be1d484951ff5ca995eaf8edcbcb8b9a5888450", + "reference": "8be1d484951ff5ca995eaf8edcbcb8b9a5888450", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.43" + }, + "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": "2024-08-01T10:24:28+00:00" }, { "name": "theseer/tokenizer", @@ -4539,31 +5251,31 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.5.0", + "version": "v5.6.1", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7" + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", - "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.0.2", - "php": "^7.1.3 || ^8.0", - "phpoption/phpoption": "^1.8", - "symfony/polyfill-ctype": "^1.23", - "symfony/polyfill-mbstring": "^1.23.1", - "symfony/polyfill-php80": "^1.23.1" + "graham-campbell/result-type": "^1.1.3", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-filter": "*", - "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "suggest": { "ext-filter": "Required to use the boolean validator." @@ -4572,10 +5284,10 @@ "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { - "dev-master": "5.5-dev" + "dev-master": "5.6-dev" } }, "autoload": { @@ -4607,7 +5319,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" }, "funding": [ { @@ -4619,7 +5331,7 @@ "type": "tidelift" } ], - "time": "2022-10-16T01:01:54+00:00" + "time": "2024-07-20T21:52:34+00:00" }, { "name": "webmozart/assert", @@ -4835,12 +5547,12 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^7.2 | ^8.0", + "php": "^7.4 | ^8.0", "ext-json": "*" }, "platform-dev": [], "platform-overrides": { - "php": "7.2" + "php": "7.4" }, "plugin-api-version": "2.6.0" } From a0c859637c42f7c03c0e27664571a4cd1f9e2af3 Mon Sep 17 00:00:00 2001 From: Alex Pantechovskis Date: Wed, 4 Sep 2024 17:26:30 +0300 Subject: [PATCH 099/134] Use main package workflow branch --- .github/workflows/package-new.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package-new.yml b/.github/workflows/package-new.yml index abec979a4..44c5c8182 100644 --- a/.github/workflows/package-new.yml +++ b/.github/workflows/package-new.yml @@ -27,7 +27,7 @@ jobs: create_archive: needs: check_version - uses: inpsyde/reusable-workflows/.github/workflows/build-plugin-archive.yml@feature/prefixed-archives + uses: inpsyde/reusable-workflows/.github/workflows/build-plugin-archive.yml@main with: PHP_VERSION: 7.4 PLUGIN_MAIN_FILE: ./woocommerce-paypal-payments.php From 91eb74987779d8cb726e0a005043206139ba52a3 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 4 Sep 2024 16:30:02 +0200 Subject: [PATCH 100/134] Fix linter warning --- modules/ppcp-paylater-wc-blocks/module.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/ppcp-paylater-wc-blocks/module.php b/modules/ppcp-paylater-wc-blocks/module.php index 6b4d37147..044de74d5 100644 --- a/modules/ppcp-paylater-wc-blocks/module.php +++ b/modules/ppcp-paylater-wc-blocks/module.php @@ -9,7 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\PayLaterWCBlocks; - return static function (): PayLaterWCBlocksModule { return new PayLaterWCBlocksModule(); }; From 95566c311de09ba93fbdd487ed1977488a663ac9 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Wed, 4 Sep 2024 21:01:30 +0300 Subject: [PATCH 101/134] Fix folder name in package PLUGIN_FOLDER_NAME defaults to ARCHIVE_NAME --- .github/workflows/package-new.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/package-new.yml b/.github/workflows/package-new.yml index 44c5c8182..3d2125420 100644 --- a/.github/workflows/package-new.yml +++ b/.github/workflows/package-new.yml @@ -32,5 +32,6 @@ jobs: PHP_VERSION: 7.4 PLUGIN_MAIN_FILE: ./woocommerce-paypal-payments.php PLUGIN_VERSION: ${{ needs.check_version.outputs.version }} + PLUGIN_FOLDER_NAME: woocommerce-paypal-payments ARCHIVE_NAME: woocommerce-paypal-payments-${{ needs.check_version.outputs.version }} COMPILE_ASSETS_ARGS: '-vv --env=root' From c87698c4713cd2812749f4a6efc72ca169fcdde3 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Wed, 4 Sep 2024 21:22:14 +0300 Subject: [PATCH 102/134] Fix resources in .distignore was excluding some folder in symfony polyfils --- .distignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.distignore b/.distignore index 7ad587da2..836792c75 100644 --- a/.distignore +++ b/.distignore @@ -14,7 +14,7 @@ tests .phpunit.result.cache babel.config.json node_modules -resources +modules/*/resources *.lock webpack.config.js wp-cli.yml From 503ce63975114d835bd818040f794281a1088612 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Fri, 6 Sep 2024 09:01:19 +0300 Subject: [PATCH 103/134] Do not exclude block.json in .distignore --- .distignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.distignore b/.distignore index 836792c75..614705af1 100644 --- a/.distignore +++ b/.distignore @@ -14,7 +14,8 @@ tests .phpunit.result.cache babel.config.json node_modules -modules/*/resources +modules/*/resources/css +modules/*/resources/js/**/*.js *.lock webpack.config.js wp-cli.yml From d78201634b18168d468e6e1e077bae8793c54a3b Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Fri, 6 Sep 2024 15:24:06 +0200 Subject: [PATCH 104/134] =?UTF-8?q?=F0=9F=92=A1=20Add=20todo=20about=20mis?= =?UTF-8?q?sin=20refactoring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-applepay/resources/js/ApplepayButton.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index 858495389..0f217f606 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -57,6 +57,8 @@ const CONTEXT = { * On a single page, multiple Apple Pay buttons can be displayed, which also means multiple * ApplePayButton instances exist. A typical case is on the product page, where one Apple Pay button * is located inside the minicart-popup, and another pay-now button is in the product context. + * + * TODO - extend from PaymentButton (same as we do in GooglepayButton.js) */ class ApplePayButton { /** From 9b3ec4692a4eba8458562792125699714775b61d Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Sat, 7 Sep 2024 13:05:54 +0300 Subject: [PATCH 105/134] Improve card fields hiding --- modules/ppcp-card-fields/resources/js/Render.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-card-fields/resources/js/Render.js b/modules/ppcp-card-fields/resources/js/Render.js index 9a35ff449..ee891edf7 100644 --- a/modules/ppcp-card-fields/resources/js/Render.js +++ b/modules/ppcp-card-fields/resources/js/Render.js @@ -1,4 +1,5 @@ import { cardFieldStyles } from './CardFieldsHelper'; +import { hide } from '../../../ppcp-button/resources/js/modules/Helper/Hiding'; export function renderFields( cardFields ) { const nameField = document.getElementById( @@ -9,7 +10,7 @@ export function renderFields( cardFields ) { cardFields .NameField( { style: { input: styles } } ) .render( nameField.parentNode ); - nameField.hidden = true; + hide( nameField, true ); } const numberField = document.getElementById( @@ -20,7 +21,7 @@ export function renderFields( cardFields ) { cardFields .NumberField( { style: { input: styles } } ) .render( numberField.parentNode ); - numberField.hidden = true; + hide( numberField, true ); } const expiryField = document.getElementById( @@ -31,7 +32,7 @@ export function renderFields( cardFields ) { cardFields .ExpiryField( { style: { input: styles } } ) .render( expiryField.parentNode ); - expiryField.hidden = true; + hide( expiryField, true ); } const cvvField = document.getElementById( @@ -42,6 +43,6 @@ export function renderFields( cardFields ) { cardFields .CVVField( { style: { input: styles } } ) .render( cvvField.parentNode ); - cvvField.hidden = true; + hide( cvvField, true ); } } From 36522f685c0f7c21f17aae8f8323a652b671b57b Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 9 Sep 2024 12:10:47 +0200 Subject: [PATCH 106/134] Adjust logic to additionally set the hidden-attrib --- modules/ppcp-card-fields/resources/js/Render.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-card-fields/resources/js/Render.js b/modules/ppcp-card-fields/resources/js/Render.js index ee891edf7..892b88138 100644 --- a/modules/ppcp-card-fields/resources/js/Render.js +++ b/modules/ppcp-card-fields/resources/js/Render.js @@ -10,7 +10,8 @@ export function renderFields( cardFields ) { cardFields .NameField( { style: { input: styles } } ) .render( nameField.parentNode ); - hide( nameField, true ); + hide( nameField, true ); + nameField.hidden = true; } const numberField = document.getElementById( @@ -21,7 +22,8 @@ export function renderFields( cardFields ) { cardFields .NumberField( { style: { input: styles } } ) .render( numberField.parentNode ); - hide( numberField, true ); + hide( numberField, true ); + numberField.hidden = true; } const expiryField = document.getElementById( @@ -32,7 +34,8 @@ export function renderFields( cardFields ) { cardFields .ExpiryField( { style: { input: styles } } ) .render( expiryField.parentNode ); - hide( expiryField, true ); + hide( expiryField, true ); + expiryField.hidden = true; } const cvvField = document.getElementById( @@ -43,6 +46,7 @@ export function renderFields( cardFields ) { cardFields .CVVField( { style: { input: styles } } ) .render( cvvField.parentNode ); - hide( cvvField, true ); + hide( cvvField, true ); + cvvField.hidden = true; } } From fc4d2baa6703c9040bc01486879b452988fd7db8 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 9 Sep 2024 12:16:02 +0200 Subject: [PATCH 107/134] Extract repeat logic into new helper method --- modules/ppcp-card-fields/resources/js/Render.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/modules/ppcp-card-fields/resources/js/Render.js b/modules/ppcp-card-fields/resources/js/Render.js index 892b88138..b899cb788 100644 --- a/modules/ppcp-card-fields/resources/js/Render.js +++ b/modules/ppcp-card-fields/resources/js/Render.js @@ -1,6 +1,20 @@ import { cardFieldStyles } from './CardFieldsHelper'; import { hide } from '../../../ppcp-button/resources/js/modules/Helper/Hiding'; +function renderField( cardField, inputField ) { + if ( ! inputField || inputField.hidden || ! cardField ) { + return; + } + + // Insert the PayPal card field after the original input field. + const styles = cardFieldStyles( inputField ); + cardField( { style: { input: styles } } ).render( inputField.parentNode ); + + // Hide the original input field. + hide( inputField, true ); + inputField.hidden = true; +} + export function renderFields( cardFields ) { const nameField = document.getElementById( 'ppcp-credit-card-gateway-card-name' From e00a4a302c47d782ec5d98160feeb59eb4ce0618 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 9 Sep 2024 12:16:27 +0200 Subject: [PATCH 108/134] Replace existing logic with new helper method --- .../ppcp-card-fields/resources/js/Render.js | 55 ++++--------------- 1 file changed, 12 insertions(+), 43 deletions(-) diff --git a/modules/ppcp-card-fields/resources/js/Render.js b/modules/ppcp-card-fields/resources/js/Render.js index b899cb788..146396288 100644 --- a/modules/ppcp-card-fields/resources/js/Render.js +++ b/modules/ppcp-card-fields/resources/js/Render.js @@ -16,51 +16,20 @@ function renderField( cardField, inputField ) { } export function renderFields( cardFields ) { - const nameField = document.getElementById( - 'ppcp-credit-card-gateway-card-name' + renderField( + cardFields.NameField, + document.getElementById( 'ppcp-credit-card-gateway-card-name' ) ); - if ( nameField && nameField.hidden !== true ) { - const styles = cardFieldStyles( nameField ); - cardFields - .NameField( { style: { input: styles } } ) - .render( nameField.parentNode ); - hide( nameField, true ); - nameField.hidden = true; - } - - const numberField = document.getElementById( - 'ppcp-credit-card-gateway-card-number' + renderField( + cardFields.NumberField, + document.getElementById( 'ppcp-credit-card-gateway-card-number' ) ); - if ( numberField && numberField.hidden !== true ) { - const styles = cardFieldStyles( numberField ); - cardFields - .NumberField( { style: { input: styles } } ) - .render( numberField.parentNode ); - hide( numberField, true ); - numberField.hidden = true; - } - - const expiryField = document.getElementById( - 'ppcp-credit-card-gateway-card-expiry' + renderField( + cardFields.ExpiryField, + document.getElementById( 'ppcp-credit-card-gateway-card-expiry' ) ); - if ( expiryField && expiryField.hidden !== true ) { - const styles = cardFieldStyles( expiryField ); - cardFields - .ExpiryField( { style: { input: styles } } ) - .render( expiryField.parentNode ); - hide( expiryField, true ); - expiryField.hidden = true; - } - - const cvvField = document.getElementById( - 'ppcp-credit-card-gateway-card-cvc' + renderField( + cardFields.CVVField, + document.getElementById( 'ppcp-credit-card-gateway-card-cvc' ) ); - if ( cvvField && cvvField.hidden !== true ) { - const styles = cardFieldStyles( cvvField ); - cardFields - .CVVField( { style: { input: styles } } ) - .render( cvvField.parentNode ); - hide( cvvField, true ); - cvvField.hidden = true; - } } From 9bafceddec1f68e0dddbc1836675ae12aa503353 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Tue, 10 Sep 2024 16:41:53 +0300 Subject: [PATCH 109/134] Fix shipping callback condition in status report --- modules/ppcp-status-report/src/StatusReportModule.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index 8cff26b17..da015d586 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -184,9 +184,9 @@ class StatusReportModule implements ServiceModule, ExtendingModule, ExecutableMo array( 'label' => esc_html__( 'PayPal Shipping Callback', 'woocommerce-paypal-payments' ), 'exported_label' => 'PayPal Shipping Callback', - 'description' => esc_html__( 'Whether the "Require final confirmation on checkout" setting is enabled.', 'woocommerce-paypal-payments' ), + 'description' => esc_html__( 'Whether the "Require final confirmation on checkout" setting is disabled.', 'woocommerce-paypal-payments' ), 'value' => $this->bool_to_html( - $settings->has( 'blocks_final_review_enabled' ) && $settings->get( 'blocks_final_review_enabled' ) + $settings->has( 'blocks_final_review_enabled' ) && ! $settings->get( 'blocks_final_review_enabled' ) ), ), array( From c24b753c383f70a95b1043ef83b28961d400de68 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Tue, 10 Sep 2024 19:12:14 +0200 Subject: [PATCH 110/134] AXO: Remove restriction for the Force shipping to the customer billing address shipping config --- modules/ppcp-axo/extensions.php | 1 - modules/ppcp-axo/services.php | 7 ------ modules/ppcp-axo/src/AxoModule.php | 16 +------------ .../src/Helper/SettingsNoticeGenerator.php | 24 ------------------- 4 files changed, 1 insertion(+), 47 deletions(-) diff --git a/modules/ppcp-axo/extensions.php b/modules/ppcp-axo/extensions.php index fe67bb3d5..9d26cffd5 100644 --- a/modules/ppcp-axo/extensions.php +++ b/modules/ppcp-axo/extensions.php @@ -120,7 +120,6 @@ return array( '', array( $container->get( 'axo.settings-conflict-notice' ), - $container->get( 'axo.shipping-config-notice' ), $container->get( 'axo.checkout-config-notice' ), $container->get( 'axo.incompatible-plugins-notice' ), ) diff --git a/modules/ppcp-axo/services.php b/modules/ppcp-axo/services.php index b860eab15..0519e9209 100644 --- a/modules/ppcp-axo/services.php +++ b/modules/ppcp-axo/services.php @@ -180,13 +180,6 @@ return array( return $settings_notice_generator->generate_checkout_notice(); }, - 'axo.shipping-config-notice' => static function ( ContainerInterface $container ) : string { - $settings_notice_generator = $container->get( 'axo.helpers.settings-notice-generator' ); - assert( $settings_notice_generator instanceof SettingsNoticeGenerator ); - - return $settings_notice_generator->generate_shipping_notice(); - }, - 'axo.incompatible-plugins-notice' => static function ( ContainerInterface $container ) : string { $settings_notice_generator = $container->get( 'axo.helpers.settings-notice-generator' ); assert( $settings_notice_generator instanceof SettingsNoticeGenerator ); diff --git a/modules/ppcp-axo/src/AxoModule.php b/modules/ppcp-axo/src/AxoModule.php index 2b554d1bb..069860550 100644 --- a/modules/ppcp-axo/src/AxoModule.php +++ b/modules/ppcp-axo/src/AxoModule.php @@ -99,10 +99,6 @@ class AxoModule implements ServiceModule, ExtendingModule, ExecutableModule { return $methods; } - if ( ! $this->is_compatible_shipping_config() ) { - return $methods; - } - $methods[] = $gateway; return $methods; }, @@ -173,7 +169,7 @@ class AxoModule implements ServiceModule, ExtendingModule, ExecutableModule { || ! $c->get( 'axo.eligible' ) || 'continuation' === $c->get( 'button.context' ) || $subscription_helper->cart_contains_subscription() - || ! $this->is_compatible_shipping_config() ) { + ) { return; } @@ -357,7 +353,6 @@ class AxoModule implements ServiceModule, ExtendingModule, ExecutableModule { return ! is_user_logged_in() && CartCheckoutDetector::has_classic_checkout() - && $this->is_compatible_shipping_config() && $is_axo_enabled && $is_dcc_enabled && ! $this->is_excluded_endpoint(); @@ -414,15 +409,6 @@ class AxoModule implements ServiceModule, ExtendingModule, ExecutableModule { return is_wc_endpoint_url( 'order-pay' ); } - /** - * Condition to evaluate if the shipping configuration is compatible. - * - * @return bool - */ - private function is_compatible_shipping_config(): bool { - return ! wc_shipping_enabled() || ( wc_shipping_enabled() && ! wc_ship_to_billing_address_only() ); - } - /** * Outputs a meta tag to allow feature detection on certain pages. * diff --git a/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php b/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php index d4d4cb824..aec8848a0 100644 --- a/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php +++ b/modules/ppcp-axo/src/Helper/SettingsNoticeGenerator.php @@ -103,30 +103,6 @@ class SettingsNoticeGenerator { return $notice_content ? '

    ' . $notice_content . '

    ' : ''; } - /** - * Generates the shipping notice. - * - * @return string - */ - public function generate_shipping_notice(): string { - $shipping_settings_link = admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=options' ); - - $notice_content = ''; - - if ( wc_shipping_enabled() && wc_ship_to_billing_address_only() ) { - $notice_content = sprintf( - /* translators: %1$s: URL to the Shipping destination settings page. */ - __( - 'Warning: The Shipping destination of your store is currently configured to Force shipping to the customer billing address. To enable Fastlane and accelerate payments, the shipping destination must be configured either to Default to customer shipping address or Default to customer billing address so buyers can set separate billing and shipping details.', - 'woocommerce-paypal-payments' - ), - esc_url( $shipping_settings_link ) - ); - } - - return $notice_content ? '

    ' . $notice_content . '

    ' : ''; - } - /** * Generates the incompatible plugins notice. * From dd82f678886991bb7a314ff554e053d8d97697b0 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Wed, 11 Sep 2024 16:47:15 +0300 Subject: [PATCH 111/134] Do not cache webhook.status.registered-webhooks --- modules/ppcp-webhooks/factories.php | 28 +++++++++++++++++++++ modules/ppcp-webhooks/services.php | 12 --------- modules/ppcp-webhooks/src/WebhookModule.php | 10 +++++++- 3 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 modules/ppcp-webhooks/factories.php diff --git a/modules/ppcp-webhooks/factories.php b/modules/ppcp-webhooks/factories.php new file mode 100644 index 000000000..6d36ae4fa --- /dev/null +++ b/modules/ppcp-webhooks/factories.php @@ -0,0 +1,28 @@ + function( ContainerInterface $container ) : array { + $endpoint = $container->get( 'api.endpoint.webhook' ); + assert( $endpoint instanceof WebhookEndpoint ); + + $state = $container->get( 'onboarding.state' ); + if ( $state->current_state() >= State::STATE_ONBOARDED ) { + return $endpoint->list(); + } + + return array(); + }, +); diff --git a/modules/ppcp-webhooks/services.php b/modules/ppcp-webhooks/services.php index 4d585206a..0f75a58a0 100644 --- a/modules/ppcp-webhooks/services.php +++ b/modules/ppcp-webhooks/services.php @@ -131,18 +131,6 @@ return array( return $container->get( 'webhook.current' ) !== null; }, - 'webhook.status.registered-webhooks' => function( ContainerInterface $container ) : array { - $endpoint = $container->get( 'api.endpoint.webhook' ); - assert( $endpoint instanceof WebhookEndpoint ); - - $state = $container->get( 'onboarding.state' ); - if ( $state->current_state() >= State::STATE_ONBOARDED ) { - return $endpoint->list(); - } - - return array(); - }, - 'webhook.status.registered-webhooks-data' => function( ContainerInterface $container ) : array { $empty_placeholder = __( 'No webhooks found.', 'woocommerce-paypal-payments' ); diff --git a/modules/ppcp-webhooks/src/WebhookModule.php b/modules/ppcp-webhooks/src/WebhookModule.php index 64c7dfea5..22ae0fc19 100644 --- a/modules/ppcp-webhooks/src/WebhookModule.php +++ b/modules/ppcp-webhooks/src/WebhookModule.php @@ -14,6 +14,7 @@ use WooCommerce\PayPalCommerce\Onboarding\State; use Exception; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; +use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\FactoryModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; @@ -27,7 +28,7 @@ use WooCommerce\PayPalCommerce\Webhooks\Status\Assets\WebhooksStatusPageAssets; /** * Class WebhookModule */ -class WebhookModule implements ServiceModule, ExtendingModule, ExecutableModule { +class WebhookModule implements ServiceModule, FactoryModule, ExtendingModule, ExecutableModule { use ModuleClassNameIdTrait; /** @@ -37,6 +38,13 @@ class WebhookModule implements ServiceModule, ExtendingModule, ExecutableModule return require __DIR__ . '/../services.php'; } + /** + * {@inheritDoc} + */ + public function factories(): array { + return require __DIR__ . '/../factories.php'; + } + /** * {@inheritDoc} */ From ea9ecbeb23f9c4fec88dcdfd557c08a2d8c61ba4 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 11 Sep 2024 19:19:15 +0400 Subject: [PATCH 112/134] Create the simple redirect task --- .../WcTasks/Tasks/SimpleRedirectTask.php | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php new file mode 100644 index 000000000..b187f6b17 --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php @@ -0,0 +1,120 @@ +id = $id; + $this->title = $title; + $this->description = $description; + $this->redirect_url = $redirect_url; + } + + /** + * The task ID. + * + * @return string + */ + public function get_id(): string { + return $this->id; + } + + /** + * The task title. + * + * @return string + */ + public function get_title(): string { + return $this->title; + } + + /** + * The task content. + * + * @return string + */ + public function get_content(): string { + return ''; + } + + /** + * The task time. + * + * @return string + */ + public function get_time(): string { + return $this->description; + } + + /** + * The task redirection URL. + * + * @return string + */ + public function get_action_url(): string { + return $this->redirect_url; + } + + /** + * The task completion. + * + * We need to set the task completed when the redirection happened for the first time. + * So this method of a parent class should be overridden. + * + * @return bool + */ + public function is_complete(): bool { + return parent::is_visited(); + } +} From dd216475619041c335558e7d53c0ac0948e1c7bf Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 11 Sep 2024 19:19:38 +0400 Subject: [PATCH 113/134] Create the factory for simple redirect task creation --- .../Factory/SimpleRedirectTaskFactory.php | 23 ++++++++++++++++ .../SimpleRedirectTaskFactoryInterface.php | 26 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php create mode 100644 modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactoryInterface.php diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php new file mode 100644 index 000000000..7f9d6e893 --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php @@ -0,0 +1,23 @@ + Date: Wed, 11 Sep 2024 19:19:51 +0400 Subject: [PATCH 114/134] Create the task registrar --- .../WcTasks/Registrar/TaskRegistrar.php | 32 +++++++++++++++++++ .../Registrar/TaskRegistrarInterface.php | 25 +++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php create mode 100644 modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrarInterface.php diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php new file mode 100644 index 000000000..174e60e6b --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php @@ -0,0 +1,32 @@ +get_error_message() ); + } + } + } +} diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrarInterface.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrarInterface.php new file mode 100644 index 000000000..992b41150 --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrarInterface.php @@ -0,0 +1,25 @@ + Date: Wed, 11 Sep 2024 19:20:04 +0400 Subject: [PATCH 115/134] Add the services and configs --- modules/ppcp-wc-gateway/services.php | 59 ++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 6ca2ecafe..f487818c5 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -29,6 +29,11 @@ use WooCommerce\PayPalCommerce\WcGateway\Endpoint\CaptureCardPayment; use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint; use WooCommerce\PayPalCommerce\WcGateway\Helper\CartCheckoutDetector; use WooCommerce\PayPalCommerce\WcGateway\Helper\FeesUpdater; +use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Factory\SimpleRedirectTaskFactory; +use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Factory\SimpleRedirectTaskFactoryInterface; +use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Registrar\TaskRegistrar; +use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Registrar\TaskRegistrarInterface; +use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Tasks\SimpleRedirectTask; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer; @@ -1762,4 +1767,58 @@ return array( $container->get( 'woocommerce.logger.woocommerce' ) ); }, + + 'wcgateway.settings.wc-tasks.simple-redirect-task-factory' => static function(): SimpleRedirectTaskFactoryInterface { + return new SimpleRedirectTaskFactory(); + }, + 'wcgateway.settings.wc-tasks.task-registrar' => static function(): TaskRegistrarInterface { + return new TaskRegistrar(); + }, + + /** + * A configuration for simple redirect wc tasks. + * + * @returns array + */ + 'wcgateway.settings.wc-tasks.simple-redirect-tasks-config' => static function(): array { + $section_id = PayPalGateway::ID; + $pay_later_tab_id = Settings::PAY_LATER_TAB_ID; + + return array( + array( + 'id' => 'pay-later-messaging-task', + 'title' => __( 'Configure PayPal Pay Later messaging', 'woocommerce-paypal-payments' ), + 'description' => __( 'Decide where you want dynamic Pay Later messaging to show up and how you want it to look on your site.', 'woocommerce-paypal-payments' ), + 'redirect_url' => admin_url("admin.php?page=wc-settings&tab=checkout§ion={$section_id}&ppcp-tab={$pay_later_tab_id}"), + ), + ); + }, + + /** + * Retrieves the list of simple redirect task instances. + * + * @returns SimpleRedirectTask[] + */ + 'wcgateway.settings.wc-tasks.simple-redirect-tasks' => static function( ContainerInterface $container ): array { + $simple_redirect_tasks_config = $container->get( 'wcgateway.settings.wc-tasks.simple-redirect-tasks-config' ); + $simple_redirect_task_factory = $container->get( 'wcgateway.settings.wc-tasks.simple-redirect-task-factory' ); + assert( $simple_redirect_task_factory instanceof SimpleRedirectTaskFactoryInterface ); + + $simple_redirect_tasks = array(); + + foreach ( $simple_redirect_tasks_config as $config ) { + $id = $config['id'] ?? ''; + $title = $config['title'] ?? ''; + $description = $config['description'] ?? ''; + $redirect_url = $config['redirect_url'] ?? ''; + $simple_redirect_tasks[] = $simple_redirect_task_factory->create_task( $id, $title, $description, $redirect_url ); + } + + return $simple_redirect_tasks; + }, ); From 12d17a7990ce40786ebae82ae1d9d24ab4763d7e Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 11 Sep 2024 19:20:19 +0400 Subject: [PATCH 116/134] Register the tasks --- .../ppcp-wc-gateway/src/WCGatewayModule.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index 09cceda99..eab936f52 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway; +use Exception; use Psr\Log\LoggerInterface; use Throwable; use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message; @@ -55,6 +56,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener; use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Registrar\TaskRegistrarInterface; /** * Class WcGatewayModule @@ -86,6 +88,7 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul $this->register_order_functionality( $c ); $this->register_columns( $c ); $this->register_checkout_paypal_address_preset( $c ); + $this->register_wc_tasks( $c ); add_action( 'woocommerce_sections_checkout', @@ -831,4 +834,30 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul 2 ); } + + /** + * Registers the tasks inside "Things to do next" WC section. + * + * @param ContainerInterface $container The container. + * @return void + */ + protected function register_wc_tasks( ContainerInterface $container ): void { + $simple_redirect_tasks = $container->get( 'wcgateway.settings.wc-tasks.simple-redirect-tasks' ); + $task_registrar = $container->get( 'wcgateway.settings.wc-tasks.task-registrar' ); + assert( $task_registrar instanceof TaskRegistrarInterface ); + + $logger = $container->get( 'woocommerce.logger.woocommerce' ); + assert( $logger instanceof LoggerInterface ); + + add_action( + 'init', + static function () use ( $simple_redirect_tasks, $task_registrar, $logger ): void { + try { + $task_registrar->register( $simple_redirect_tasks ); + } catch ( Exception $exception ) { + $logger->error( "Failed to create a task in the 'Things to do next' section of WC. " . $exception->getMessage() ); + } + }, + ); + } } From 4fb62c5c72f872ad6eeef455874e424e0f62a72f Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 11 Sep 2024 19:41:12 +0400 Subject: [PATCH 117/134] Add stubs for WC Task --- tests/stubs/Task.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/stubs/Task.php diff --git a/tests/stubs/Task.php b/tests/stubs/Task.php new file mode 100644 index 000000000..1d2461c90 --- /dev/null +++ b/tests/stubs/Task.php @@ -0,0 +1,36 @@ + Date: Wed, 11 Sep 2024 19:44:57 +0400 Subject: [PATCH 118/134] Add stubs for WC Task --- tests/stubs/Task.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/stubs/Task.php b/tests/stubs/Task.php index 1d2461c90..d0e3c23c1 100644 --- a/tests/stubs/Task.php +++ b/tests/stubs/Task.php @@ -1,9 +1,7 @@ Date: Wed, 11 Sep 2024 19:46:48 +0400 Subject: [PATCH 119/134] Add stubs for WC Task --- tests/PHPUnit/bootstrap.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/PHPUnit/bootstrap.php b/tests/PHPUnit/bootstrap.php index 8910b0241..647473e12 100644 --- a/tests/PHPUnit/bootstrap.php +++ b/tests/PHPUnit/bootstrap.php @@ -10,5 +10,6 @@ require_once TESTS_ROOT_DIR . '/stubs/WC_Payment_Gateway.php'; require_once TESTS_ROOT_DIR . '/stubs/WC_Payment_Gateway_CC.php'; require_once TESTS_ROOT_DIR . '/stubs/WC_Ajax.php'; require_once TESTS_ROOT_DIR . '/stubs/WC_Checkout.php'; +require_once TESTS_ROOT_DIR . '/stubs/Task.php'; Hamcrest\Util::registerGlobalFunctions(); From 15a8a0d9d0e515973190cbc09c2e472cdc662699 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 11 Sep 2024 20:18:46 +0400 Subject: [PATCH 120/134] Add condition to check if pay later task should be enabled --- modules/ppcp-wc-gateway/services.php | 9 +++++--- .../Factory/SimpleRedirectTaskFactory.php | 4 ++-- .../SimpleRedirectTaskFactoryInterface.php | 3 ++- .../WcTasks/Registrar/TaskRegistrar.php | 5 +++++ .../WcTasks/Tasks/SimpleRedirectTask.php | 21 ++++++++++++++++++- 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index f487818c5..4bacab63a 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1782,10 +1782,11 @@ return array( * id: string, * title: string, * description: string, - * redirect_url: string + * redirect_url: string, + * is_enabled: bool * }> */ - 'wcgateway.settings.wc-tasks.simple-redirect-tasks-config' => static function(): array { + 'wcgateway.settings.wc-tasks.simple-redirect-tasks-config' => static function( ContainerInterface $container ): array { $section_id = PayPalGateway::ID; $pay_later_tab_id = Settings::PAY_LATER_TAB_ID; @@ -1795,6 +1796,7 @@ return array( 'title' => __( 'Configure PayPal Pay Later messaging', 'woocommerce-paypal-payments' ), 'description' => __( 'Decide where you want dynamic Pay Later messaging to show up and how you want it to look on your site.', 'woocommerce-paypal-payments' ), 'redirect_url' => admin_url("admin.php?page=wc-settings&tab=checkout§ion={$section_id}&ppcp-tab={$pay_later_tab_id}"), + 'is_enabled' => $container->get('paylater-configurator.is-available'), ), ); }, @@ -1816,7 +1818,8 @@ return array( $title = $config['title'] ?? ''; $description = $config['description'] ?? ''; $redirect_url = $config['redirect_url'] ?? ''; - $simple_redirect_tasks[] = $simple_redirect_task_factory->create_task( $id, $title, $description, $redirect_url ); + $is_enabled = $config['is_enabled'] ?? false; + $simple_redirect_tasks[] = $simple_redirect_task_factory->create_task( $id, $title, $description, $redirect_url, $is_enabled ); } return $simple_redirect_tasks; diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php index 7f9d6e893..be21d6cfa 100644 --- a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php @@ -17,7 +17,7 @@ class SimpleRedirectTaskFactory implements SimpleRedirectTaskFactoryInterface { /** * {@inheritDoc} */ - public function create_task( string $id, string $title, string $description, string $redirect_url ): SimpleRedirectTask { - return new SimpleRedirectTask( $id, $title, $description, $redirect_url ); + public function create_task( string $id, string $title, string $description, string $redirect_url, bool $is_enabled ): SimpleRedirectTask { + return new SimpleRedirectTask( $id, $title, $description, $redirect_url, $is_enabled ); } } diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactoryInterface.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactoryInterface.php index 8931622d4..f8d17b57f 100644 --- a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactoryInterface.php +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactoryInterface.php @@ -20,7 +20,8 @@ interface SimpleRedirectTaskFactoryInterface { * @param string $title The task title. * @param string $description The task description. * @param string $redirect_url The redirection URL. + * @param bool $is_enabled Whether the task is enabled. * @return SimpleRedirectTask The task. */ - public function create_task( string $id, string $title, string $description, string $redirect_url ): SimpleRedirectTask; + public function create_task( string $id, string $title, string $description, string $redirect_url, bool $is_enabled ): SimpleRedirectTask; } diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php index 174e60e6b..c710c7a09 100644 --- a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php @@ -9,6 +9,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Registrar; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists; use RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Tasks\SimpleRedirectTask; use WP_Error; /** @@ -23,6 +24,10 @@ class TaskRegistrar implements TaskRegistrarInterface { */ public function register( array $tasks ): void { foreach ( $tasks as $task ) { + if ( $task instanceof SimpleRedirectTask && ! $task->is_enabled() ) { + return; + } + $added_task = TaskLists::add_task( 'extended', $task ); if ( $added_task instanceof WP_Error ) { throw new RuntimeException( $added_task->get_error_message() ); diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php index b187f6b17..104a9be6d 100644 --- a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php @@ -44,6 +44,14 @@ class SimpleRedirectTask extends Task { */ protected string $redirect_url; + /** + * Whether the task is enabled. + * + * @var bool + */ + protected bool $is_enabled; + + /** * SimpleRedirectTask constructor. * @@ -51,14 +59,16 @@ class SimpleRedirectTask extends Task { * @param string $title The task title. * @param string $description The task description. * @param string $redirect_url The redirection URL. + * @param bool $is_enabled Whether the task is enabled. */ - public function __construct( string $id, string $title, string $description, string $redirect_url ) { + public function __construct( string $id, string $title, string $description, string $redirect_url, bool $is_enabled ) { parent::__construct(); $this->id = $id; $this->title = $title; $this->description = $description; $this->redirect_url = $redirect_url; + $this->is_enabled = $is_enabled; } /** @@ -106,6 +116,15 @@ class SimpleRedirectTask extends Task { return $this->redirect_url; } + /** + * Whether the task is enabled. + * + * @return bool + */ + public function is_enabled(): bool { + return $this->is_enabled; + } + /** * The task completion. * From 42a6cb2b45ba2a42c69fe0ebbece12ac1e485a16 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 11 Sep 2024 20:23:09 +0400 Subject: [PATCH 121/134] Continue instead of exit --- .../src/Settings/WcTasks/Registrar/TaskRegistrar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php index c710c7a09..c7ec4b5d5 100644 --- a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php @@ -25,7 +25,7 @@ class TaskRegistrar implements TaskRegistrarInterface { public function register( array $tasks ): void { foreach ( $tasks as $task ) { if ( $task instanceof SimpleRedirectTask && ! $task->is_enabled() ) { - return; + continue; } $added_task = TaskLists::add_task( 'extended', $task ); From 137a8b4975977c9eac5c04ab418fb984289735d1 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 11 Sep 2024 20:28:31 +0400 Subject: [PATCH 122/134] Early return instead of complicating the task --- modules/ppcp-wc-gateway/services.php | 16 +++++++------- .../Factory/SimpleRedirectTaskFactory.php | 4 ++-- .../SimpleRedirectTaskFactoryInterface.php | 3 +-- .../WcTasks/Tasks/SimpleRedirectTask.php | 21 +------------------ .../ppcp-wc-gateway/src/WCGatewayModule.php | 6 +++++- 5 files changed, 18 insertions(+), 32 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 4bacab63a..e0001821c 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1790,15 +1790,18 @@ return array( $section_id = PayPalGateway::ID; $pay_later_tab_id = Settings::PAY_LATER_TAB_ID; - return array( - array( + $list_of_config = array(); + + if ( $container->get('paylater-configurator.is-available') ) { + $list_of_config[] = array( 'id' => 'pay-later-messaging-task', 'title' => __( 'Configure PayPal Pay Later messaging', 'woocommerce-paypal-payments' ), 'description' => __( 'Decide where you want dynamic Pay Later messaging to show up and how you want it to look on your site.', 'woocommerce-paypal-payments' ), 'redirect_url' => admin_url("admin.php?page=wc-settings&tab=checkout§ion={$section_id}&ppcp-tab={$pay_later_tab_id}"), - 'is_enabled' => $container->get('paylater-configurator.is-available'), - ), - ); + ); + } + + return $list_of_config; }, /** @@ -1818,8 +1821,7 @@ return array( $title = $config['title'] ?? ''; $description = $config['description'] ?? ''; $redirect_url = $config['redirect_url'] ?? ''; - $is_enabled = $config['is_enabled'] ?? false; - $simple_redirect_tasks[] = $simple_redirect_task_factory->create_task( $id, $title, $description, $redirect_url, $is_enabled ); + $simple_redirect_tasks[] = $simple_redirect_task_factory->create_task( $id, $title, $description, $redirect_url ); } return $simple_redirect_tasks; diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php index be21d6cfa..7f9d6e893 100644 --- a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactory.php @@ -17,7 +17,7 @@ class SimpleRedirectTaskFactory implements SimpleRedirectTaskFactoryInterface { /** * {@inheritDoc} */ - public function create_task( string $id, string $title, string $description, string $redirect_url, bool $is_enabled ): SimpleRedirectTask { - return new SimpleRedirectTask( $id, $title, $description, $redirect_url, $is_enabled ); + public function create_task( string $id, string $title, string $description, string $redirect_url ): SimpleRedirectTask { + return new SimpleRedirectTask( $id, $title, $description, $redirect_url ); } } diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactoryInterface.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactoryInterface.php index f8d17b57f..8931622d4 100644 --- a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactoryInterface.php +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Factory/SimpleRedirectTaskFactoryInterface.php @@ -20,8 +20,7 @@ interface SimpleRedirectTaskFactoryInterface { * @param string $title The task title. * @param string $description The task description. * @param string $redirect_url The redirection URL. - * @param bool $is_enabled Whether the task is enabled. * @return SimpleRedirectTask The task. */ - public function create_task( string $id, string $title, string $description, string $redirect_url, bool $is_enabled ): SimpleRedirectTask; + public function create_task( string $id, string $title, string $description, string $redirect_url ): SimpleRedirectTask; } diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php index 104a9be6d..b187f6b17 100644 --- a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Tasks/SimpleRedirectTask.php @@ -44,14 +44,6 @@ class SimpleRedirectTask extends Task { */ protected string $redirect_url; - /** - * Whether the task is enabled. - * - * @var bool - */ - protected bool $is_enabled; - - /** * SimpleRedirectTask constructor. * @@ -59,16 +51,14 @@ class SimpleRedirectTask extends Task { * @param string $title The task title. * @param string $description The task description. * @param string $redirect_url The redirection URL. - * @param bool $is_enabled Whether the task is enabled. */ - public function __construct( string $id, string $title, string $description, string $redirect_url, bool $is_enabled ) { + public function __construct( string $id, string $title, string $description, string $redirect_url ) { parent::__construct(); $this->id = $id; $this->title = $title; $this->description = $description; $this->redirect_url = $redirect_url; - $this->is_enabled = $is_enabled; } /** @@ -116,15 +106,6 @@ class SimpleRedirectTask extends Task { return $this->redirect_url; } - /** - * Whether the task is enabled. - * - * @return bool - */ - public function is_enabled(): bool { - return $this->is_enabled; - } - /** * The task completion. * diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index eab936f52..5a7ca2c62 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -843,7 +843,11 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul */ protected function register_wc_tasks( ContainerInterface $container ): void { $simple_redirect_tasks = $container->get( 'wcgateway.settings.wc-tasks.simple-redirect-tasks' ); - $task_registrar = $container->get( 'wcgateway.settings.wc-tasks.task-registrar' ); + if ( empty( $simple_redirect_tasks ) ) { + return; + } + + $task_registrar = $container->get( 'wcgateway.settings.wc-tasks.task-registrar' ); assert( $task_registrar instanceof TaskRegistrarInterface ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); From 216654418cd7e72014c59d73312e991b2721460b Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 11 Sep 2024 20:29:36 +0400 Subject: [PATCH 123/134] Fix the dockblock --- modules/ppcp-wc-gateway/services.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index e0001821c..a78be7a54 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1782,8 +1782,7 @@ return array( * id: string, * title: string, * description: string, - * redirect_url: string, - * is_enabled: bool + * redirect_url: string * }> */ 'wcgateway.settings.wc-tasks.simple-redirect-tasks-config' => static function( ContainerInterface $container ): array { From 09b6e09df442ad9f7f10a112c8e4605da7cc9a37 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 11 Sep 2024 20:31:19 +0400 Subject: [PATCH 124/134] Remove the leftover check --- .../src/Settings/WcTasks/Registrar/TaskRegistrar.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php index c7ec4b5d5..174e60e6b 100644 --- a/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php +++ b/modules/ppcp-wc-gateway/src/Settings/WcTasks/Registrar/TaskRegistrar.php @@ -9,7 +9,6 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Registrar; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists; use RuntimeException; -use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Tasks\SimpleRedirectTask; use WP_Error; /** @@ -24,10 +23,6 @@ class TaskRegistrar implements TaskRegistrarInterface { */ public function register( array $tasks ): void { foreach ( $tasks as $task ) { - if ( $task instanceof SimpleRedirectTask && ! $task->is_enabled() ) { - continue; - } - $added_task = TaskLists::add_task( 'extended', $task ); if ( $added_task instanceof WP_Error ) { throw new RuntimeException( $added_task->get_error_message() ); From 6e1a6280de5d5516e1bf5c7a322ecc1142b9cfbb Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 11 Sep 2024 18:49:31 +0200 Subject: [PATCH 125/134] =?UTF-8?q?=F0=9F=90=9B=20Quick-fix=20to=20re-rend?= =?UTF-8?q?er=20missing=20Card=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the clean-up process during email change, to generate a fresh Card component when needed. --- modules/ppcp-axo/resources/js/AxoManager.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index 3144d28a1..5488a82bf 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -803,8 +803,8 @@ class AxoManager { this.emailInput.value = this.stripSpaces( this.emailInput.value ); - this.$( this.el.paymentContainer.selector + '-detail' ).html( '' ); - this.$( this.el.paymentContainer.selector + '-form' ).html( '' ); + this.$( this.el.paymentContainer.selector + '-details' ).html( '' ); + this.removeFastlaneComponent(); this.setStatus( 'validEmail', false ); this.setStatus( 'hasProfile', false ); @@ -1073,6 +1073,20 @@ class AxoManager { return this.cardComponent.render( elem ); } + /** + * Reverts the changes made by `initializeFastlaneComponent()`. + * + * Calling this method will lose any input that the user made inside the + * Fastlane Card Component. + */ + removeFastlaneComponent() { + document.querySelector( + this.el.paymentContainer.selector + '-form' + ).innerHTML = ''; + + this.cardComponent = null; + } + /** * Updates the prefill-values in the UI component. This method only updates empty fields. * From fbcc19ef4d968e2334b1bc1371846e2269b1a9da Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 11 Sep 2024 18:55:03 +0200 Subject: [PATCH 126/134] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20New=20getter=20for?= =?UTF-8?q?=20form-selector?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid typos and better document usage. --- modules/ppcp-axo/resources/js/AxoManager.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index 5488a82bf..4dfcf39b2 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -148,6 +148,15 @@ class AxoManager { return !! this.data.card; } + /** + * CSS selector to target the Fastlane Card Component wrapper. + * + * @return {string} CSS selector. + */ + get cardFormSelector() { + return this.el.paymentContainer.selector + '-form'; + } + registerEventHandlers() { this.$( document ).on( 'change', @@ -1064,7 +1073,7 @@ class AxoManager { return Promise.resolve(); } - const elem = this.el.paymentContainer.selector + '-form'; + const elem = this.cardFormSelector; const config = this.cardComponentData(); this.cardComponent = @@ -1080,9 +1089,7 @@ class AxoManager { * Fastlane Card Component. */ removeFastlaneComponent() { - document.querySelector( - this.el.paymentContainer.selector + '-form' - ).innerHTML = ''; + document.querySelector( this.cardFormSelector ).innerHTML = ''; this.cardComponent = null; } From 4309689365db63aff10b00e0e060589a26a1ee64 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Thu, 12 Sep 2024 12:11:39 +0200 Subject: [PATCH 127/134] Add namespace and constructor to stub task class --- tests/stubs/Task.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/stubs/Task.php b/tests/stubs/Task.php index d0e3c23c1..0a577cebe 100644 --- a/tests/stubs/Task.php +++ b/tests/stubs/Task.php @@ -1,9 +1,22 @@ task_list = $task_list; + } + /** * ID. * From 2722c3f326f95bf88c1f165c9bccf13beb0bee67 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Thu, 12 Sep 2024 14:23:42 +0400 Subject: [PATCH 128/134] Fix the coding styles --- modules/ppcp-wc-gateway/services.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index a78be7a54..a23de8457 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1791,12 +1791,12 @@ return array( $list_of_config = array(); - if ( $container->get('paylater-configurator.is-available') ) { + if ( $container->get( 'paylater-configurator.is-available' ) ) { $list_of_config[] = array( 'id' => 'pay-later-messaging-task', 'title' => __( 'Configure PayPal Pay Later messaging', 'woocommerce-paypal-payments' ), 'description' => __( 'Decide where you want dynamic Pay Later messaging to show up and how you want it to look on your site.', 'woocommerce-paypal-payments' ), - 'redirect_url' => admin_url("admin.php?page=wc-settings&tab=checkout§ion={$section_id}&ppcp-tab={$pay_later_tab_id}"), + 'redirect_url' => admin_url( "admin.php?page=wc-settings&tab=checkout§ion={$section_id}&ppcp-tab={$pay_later_tab_id}" ), ); } From a280c1b0f469906d16705408e0b878c2cf19363c Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Thu, 12 Sep 2024 14:47:34 +0400 Subject: [PATCH 129/134] Remove leftover `console.log` --- modules/ppcp-button/resources/js/modules/Renderer/Renderer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/ppcp-button/resources/js/modules/Renderer/Renderer.js b/modules/ppcp-button/resources/js/modules/Renderer/Renderer.js index 63bd5e2ed..9fa4708bc 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/Renderer.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/Renderer.js @@ -228,7 +228,6 @@ class Renderer { }; shouldEnableShippingCallback = () => { - console.log(this.defaultSettings.context, this.defaultSettings) let needShipping = this.defaultSettings.needShipping || this.defaultSettings.context === 'product' return this.defaultSettings.should_handle_shipping_in_paypal && needShipping }; From 23962841e782816454e0da0a64e8704cd5856be3 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 16 Sep 2024 12:22:33 +0200 Subject: [PATCH 130/134] Move fraudnet session id logic into entity getter method --- modules/ppcp-wc-gateway/services.php | 5 -- .../ppcp-wc-gateway/src/FraudNet/FraudNet.php | 35 +++++++++----- .../src/FraudNet/FraudNetSessionId.php | 48 ------------------- 3 files changed, 23 insertions(+), 65 deletions(-) delete mode 100644 modules/ppcp-wc-gateway/src/FraudNet/FraudNetSessionId.php diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index a23de8457..15e27872a 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1285,17 +1285,12 @@ return array( $container->get( 'wcgateway.processor.refunds' ) ); }, - 'wcgateway.fraudnet-session-id' => static function ( ContainerInterface $container ): FraudNetSessionId { - return new FraudNetSessionId(); - }, 'wcgateway.fraudnet-source-website-id' => static function ( ContainerInterface $container ): FraudNetSourceWebsiteId { return new FraudNetSourceWebsiteId( $container->get( 'api.merchant_id' ) ); }, 'wcgateway.fraudnet' => static function ( ContainerInterface $container ): FraudNet { - $session_id = $container->get( 'wcgateway.fraudnet-session-id' ); $source_website_id = $container->get( 'wcgateway.fraudnet-source-website-id' ); return new FraudNet( - (string) $session_id(), (string) $source_website_id() ); }, diff --git a/modules/ppcp-wc-gateway/src/FraudNet/FraudNet.php b/modules/ppcp-wc-gateway/src/FraudNet/FraudNet.php index b021f4539..167abc07b 100644 --- a/modules/ppcp-wc-gateway/src/FraudNet/FraudNet.php +++ b/modules/ppcp-wc-gateway/src/FraudNet/FraudNet.php @@ -14,13 +14,6 @@ namespace WooCommerce\PayPalCommerce\WcGateway\FraudNet; */ class FraudNet { - /** - * The session ID. - * - * @var string - */ - protected $session_id; - /** * The source website ID. * @@ -31,21 +24,39 @@ class FraudNet { /** * FraudNet constructor. * - * @param string $session_id The session ID. * @param string $source_website_id The source website ID. */ - public function __construct( string $session_id, string $source_website_id ) { - $this->session_id = $session_id; + public function __construct( string $source_website_id ) { $this->source_website_id = $source_website_id; } /** - * Returns the session ID. + * Returns the Fraudnet session ID. * * @return string */ public function session_id(): string { - return $this->session_id; + if ( WC()->session === null ) { + return ''; + } + + if ( WC()->session->get( 'ppcp_fraudnet_session_id' ) ) { + return WC()->session->get( 'ppcp_fraudnet_session_id' ); + } + + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( isset( $_GET['pay_for_order'] ) && 'true' === $_GET['pay_for_order'] ) { + // phpcs:ignore WordPress.Security.NonceVerification.Missing + $pui_pay_for_order_session_id = wc_clean( wp_unslash( $_POST['pui_pay_for_order_session_id'] ?? '' ) ); + if ( $pui_pay_for_order_session_id && '' !== $pui_pay_for_order_session_id ) { + return $pui_pay_for_order_session_id; + } + } + + $session_id = bin2hex( random_bytes( 16 ) ); + WC()->session->set( 'ppcp_fraudnet_session_id', $session_id ); + + return $session_id; } /** diff --git a/modules/ppcp-wc-gateway/src/FraudNet/FraudNetSessionId.php b/modules/ppcp-wc-gateway/src/FraudNet/FraudNetSessionId.php deleted file mode 100644 index c7a1b8d98..000000000 --- a/modules/ppcp-wc-gateway/src/FraudNet/FraudNetSessionId.php +++ /dev/null @@ -1,48 +0,0 @@ -session === null ) { - return ''; - } - - if ( WC()->session->get( 'ppcp_fraudnet_session_id' ) ) { - return WC()->session->get( 'ppcp_fraudnet_session_id' ); - } - - // phpcs:ignore WordPress.Security.NonceVerification.Recommended - if ( isset( $_GET['pay_for_order'] ) && 'true' === $_GET['pay_for_order'] ) { - // phpcs:ignore WordPress.Security.NonceVerification.Missing - $pui_pay_for_order_session_id = wc_clean( wp_unslash( $_POST['pui_pay_for_order_session_id'] ?? '' ) ); - if ( $pui_pay_for_order_session_id && '' !== $pui_pay_for_order_session_id ) { - return $pui_pay_for_order_session_id; - } - } - - $session_id = bin2hex( random_bytes( 16 ) ); - WC()->session->set( 'ppcp_fraudnet_session_id', $session_id ); - - return $session_id; - } -} From 660ce00887b8b12863616f7b2c699427e8c646b6 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 16 Sep 2024 12:42:25 +0200 Subject: [PATCH 131/134] Fix psalm --- modules/ppcp-wc-gateway/src/FraudNet/FraudNet.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/FraudNet/FraudNet.php b/modules/ppcp-wc-gateway/src/FraudNet/FraudNet.php index 167abc07b..f89be5ac5 100644 --- a/modules/ppcp-wc-gateway/src/FraudNet/FraudNet.php +++ b/modules/ppcp-wc-gateway/src/FraudNet/FraudNet.php @@ -40,15 +40,16 @@ class FraudNet { return ''; } - if ( WC()->session->get( 'ppcp_fraudnet_session_id' ) ) { - return WC()->session->get( 'ppcp_fraudnet_session_id' ); + $fraudnet_session_id = WC()->session->get( 'ppcp_fraudnet_session_id' ); + if ( is_string( $fraudnet_session_id ) && $fraudnet_session_id !== '' ) { + return $fraudnet_session_id; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended - if ( isset( $_GET['pay_for_order'] ) && 'true' === $_GET['pay_for_order'] ) { + if ( isset( $_GET['pay_for_order'] ) && $_GET['pay_for_order'] === 'true' ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing $pui_pay_for_order_session_id = wc_clean( wp_unslash( $_POST['pui_pay_for_order_session_id'] ?? '' ) ); - if ( $pui_pay_for_order_session_id && '' !== $pui_pay_for_order_session_id ) { + if ( is_string( $pui_pay_for_order_session_id ) && $pui_pay_for_order_session_id !== '' ) { return $pui_pay_for_order_session_id; } } From db752b23e206047db1e45ad225f87ad542aaeba9 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 16 Sep 2024 15:14:45 +0200 Subject: [PATCH 132/134] Release 2.9.1-rc1 --- changelog.txt | 16 ++++++++++++++++ package.json | 2 +- readme.txt | 18 +++++++++++++++++- woocommerce-paypal-payments.php | 6 +++--- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/changelog.txt b/changelog.txt index 8fee175c0..2a733cac4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,21 @@ *** Changelog *** += 2.9.1 - xxxx-xx-xx = +* Fix - Improve card fields hiding #2574 +* Fix - Google Pay: Shipping callback not calculating totals correctly on Single Product page #2513 +* Fix - Fix shipping callback condition in status report #2578 +* Fix - Can't Disconnect Account #2539 +* Fix - Google Pay billing data without shipping callback #2525 +* Fix - Standard payment tab - Google Pay and Apple Pay button - Shape from one location is applied to all until saving changes #2419 +* Enhancement - Allow to override the list of Pay Later supported countries #2563 +* Enhancement - Add more feature statuses into system report #2550 +* Enhancement - Use SVG for APM gateway icons #2509 +* Enhancement - Add inline notice to inform users about ACDC block Checkout support if the store uses a Classic Checkout setup #2422 +* Enhancement - Remove leftover console.log #2589 +* Enhancement - Require PHP 7.4+, WP 6.3+, WC 6.9+ #2556 +* Enhancement - Modularity module migration #1944 +* Enhancement - Keep only 5 tags in readme.txt #2562 + = 2.9.0 - 2024-09-02 = * Fix - Fatal error in Block Editor when using WooCommerce blocks #2534 * Fix - Can't pay from block pages when the shipping callback is enabled and no shipping methods defined #2429 diff --git a/package.json b/package.json index b5dec8450..d93840034 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "woocommerce-paypal-payments", - "version": "2.9.0", + "version": "2.9.1", "description": "WooCommerce PayPal Payments", "repository": "https://github.com/woocommerce/woocommerce-paypal-payments", "license": "GPL-2.0", diff --git a/readme.txt b/readme.txt index 6ed6f5d54..81924ee66 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, credit card Requires at least: 6.3 Tested up to: 6.6 Requires PHP: 7.4 -Stable tag: 2.9.0 +Stable tag: 2.9.1 License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -179,6 +179,22 @@ If you encounter issues with the PayPal buttons not appearing after an update, p == Changelog == += 2.9.1 - xxxx-xx-xx = +* Fix - Improve card fields hiding #2574 +* Fix - Google Pay: Shipping callback not calculating totals correctly on Single Product page #2513 +* Fix - Fix shipping callback condition in status report #2578 +* Fix - Can't Disconnect Account #2539 +* Fix - Google Pay billing data without shipping callback #2525 +* Fix - Standard payment tab - Google Pay and Apple Pay button - Shape from one location is applied to all until saving changes #2419 +* Enhancement - Allow to override the list of Pay Later supported countries #2563 +* Enhancement - Add more feature statuses into system report #2550 +* Enhancement - Use SVG for APM gateway icons #2509 +* Enhancement - Add inline notice to inform users about ACDC block Checkout support if the store uses a Classic Checkout setup #2422 +* Enhancement - Remove leftover console.log #2589 +* Enhancement - Require PHP 7.4+, WP 6.3+, WC 6.9+ #2556 +* Enhancement - Modularity module migration #1944 +* Enhancement - Keep only 5 tags in readme.txt #2562 + = 2.9.0 - 2024-09-02 = * Fix - Fatal error in Block Editor when using WooCommerce blocks #2534 * Fix - Can't pay from block pages when the shipping callback is enabled and no shipping methods defined #2429 diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index 978aaf017..16d10f84b 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -3,14 +3,14 @@ * Plugin Name: WooCommerce PayPal Payments * Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/ * Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage. - * Version: 2.9.0 + * Version: 2.9.1 * Author: WooCommerce * Author URI: https://woocommerce.com/ * License: GPL-2.0 * Requires PHP: 7.4 * Requires Plugins: woocommerce * WC requires at least: 6.9 - * WC tested up to: 9.2 + * WC tested up to: 9.3 * Text Domain: woocommerce-paypal-payments * * @package WooCommerce\PayPalCommerce @@ -26,7 +26,7 @@ define( 'PAYPAL_API_URL', 'https://api-m.paypal.com' ); define( 'PAYPAL_URL', 'https://www.paypal.com' ); define( 'PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com' ); define( 'PAYPAL_SANDBOX_URL', 'https://www.sandbox.paypal.com' ); -define( 'PAYPAL_INTEGRATION_DATE', '2024-08-28' ); +define( 'PAYPAL_INTEGRATION_DATE', '2024-09-16' ); define( 'PPCP_PAYPAL_BN_CODE', 'Woo_PPCP' ); ! defined( 'CONNECT_WOO_CLIENT_ID' ) && define( 'CONNECT_WOO_CLIENT_ID', 'AcCAsWta_JTL__OfpjspNyH7c1GGHH332fLwonA5CwX4Y10mhybRZmHLA0GdRbwKwjQIhpDQy0pluX_P' ); From eb625af36d61f9289c2733396cb85e825acc19f3 Mon Sep 17 00:00:00 2001 From: "Alex P." Date: Wed, 18 Sep 2024 16:27:32 +0300 Subject: [PATCH 133/134] Make ACDC default for China --- .../src/Render/OnboardingOptionsRenderer.php | 15 +++++++++------ .../src/Settings/Fields/connection-tab-fields.php | 5 ++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-onboarding/src/Render/OnboardingOptionsRenderer.php b/modules/ppcp-onboarding/src/Render/OnboardingOptionsRenderer.php index df99653f8..a0747d8e8 100644 --- a/modules/ppcp-onboarding/src/Render/OnboardingOptionsRenderer.php +++ b/modules/ppcp-onboarding/src/Render/OnboardingOptionsRenderer.php @@ -54,9 +54,10 @@ class OnboardingOptionsRenderer { * Renders the onboarding options. * * @param bool $is_shop_supports_dcc Whether the shop can use DCC (country, currency). + * @param bool $make_dcc_default Whether DCC should be selected by default. */ - public function render( bool $is_shop_supports_dcc ): string { - $checked = $is_shop_supports_dcc ? '' : 'checked'; + public function render( bool $is_shop_supports_dcc, bool $make_dcc_default ): string { + $checked_cards = ( $is_shop_supports_dcc && ! $make_dcc_default ) ? '' : 'checked'; $on_boarding_options = '
  • @@ -65,10 +66,10 @@ class OnboardingOptionsRenderer {
  • - +
  • ' . - $this->render_dcc( $is_shop_supports_dcc ) . + $this->render_dcc( $is_shop_supports_dcc, $make_dcc_default ) . '
  • ' . $this->render_pui_option(); @@ -107,8 +108,9 @@ class OnboardingOptionsRenderer { * Renders the onboarding DCC options. * * @param bool $is_shop_supports_dcc Whether the shop can use DCC (country, currency). + * @param bool $make_dcc_default Whether DCC should be selected by default. */ - private function render_dcc( bool $is_shop_supports_dcc ): string { + private function render_dcc( bool $is_shop_supports_dcc, bool $make_dcc_default ): string { $items = array(); $is_us_shop = 'US' === $this->country; @@ -201,7 +203,8 @@ class OnboardingOptionsRenderer {
  • ' . $this->render_tooltip( __( 'PayPal acts as the payment processor for card transactions. You can add optional features like Chargeback Protection for more security.', 'woocommerce-paypal-payments' ) ) . ' diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/connection-tab-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/connection-tab-fields.php index 7d29dd08b..7a468d5c9 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/connection-tab-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/connection-tab-fields.php @@ -105,7 +105,10 @@ return function ( ContainerInterface $container, array $fields ): array { 'ppcp_onboarading_options' => array( 'type' => 'ppcp-text', 'classes' => array( 'ppcp-onboarding-element' ), - 'text' => $onboarding_options_renderer->render( $is_shop_supports_dcc ), + 'text' => $onboarding_options_renderer->render( + $is_shop_supports_dcc, + $container->get( 'api.shop.country' ) === 'CN' + ), 'raw' => true, 'screens' => array( State::STATE_START, From 5a0ec4fa3717393fa7278d4c8e008e49048557ab Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Fri, 20 Sep 2024 11:11:29 +0200 Subject: [PATCH 134/134] Update changelog --- changelog.txt | 1 + readme.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/changelog.txt b/changelog.txt index 2a733cac4..a12ac75ca 100644 --- a/changelog.txt +++ b/changelog.txt @@ -15,6 +15,7 @@ * Enhancement - Require PHP 7.4+, WP 6.3+, WC 6.9+ #2556 * Enhancement - Modularity module migration #1944 * Enhancement - Keep only 5 tags in readme.txt #2562 +* Enhancement - Select ACDC by default during onboarding for China store locations #2619 = 2.9.0 - 2024-09-02 = * Fix - Fatal error in Block Editor when using WooCommerce blocks #2534 diff --git a/readme.txt b/readme.txt index 81924ee66..a9e4d543d 100644 --- a/readme.txt +++ b/readme.txt @@ -194,6 +194,7 @@ If you encounter issues with the PayPal buttons not appearing after an update, p * Enhancement - Require PHP 7.4+, WP 6.3+, WC 6.9+ #2556 * Enhancement - Modularity module migration #1944 * Enhancement - Keep only 5 tags in readme.txt #2562 +* Enhancement - Select ACDC by default during onboarding for China store locations #2619 = 2.9.0 - 2024-09-02 = * Fix - Fatal error in Block Editor when using WooCommerce blocks #2534