Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow configuration based on shipping classes #1145

Merged
merged 4 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions config/pdk.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use MyParcelNL\Pdk\Base\Contract\CronServiceInterface;
use MyParcelNL\Pdk\Base\Contract\WeightServiceInterface;
use MyParcelNL\Pdk\Base\Support\Arr;
use MyParcelNL\Pdk\Context\Contract\ContextServiceInterface;
use MyParcelNL\Pdk\Facade\Language;
use MyParcelNL\Pdk\Facade\Pdk;
use MyParcelNL\Pdk\Facade\Pdk as PdkFacade;
Expand All @@ -41,7 +42,9 @@
use MyParcelNL\WooCommerce\Facade\WooCommerce;
use MyParcelNL\WooCommerce\Facade\WordPress;
use MyParcelNL\WooCommerce\Logger\WcLogger;
use MyParcelNL\WooCommerce\Pdk\Action\Frontend\Context\WcFetchCheckoutContextAction;
use MyParcelNL\WooCommerce\Pdk\Audit\Repository\WcPdkAuditRepository;
use MyParcelNL\WooCommerce\Pdk\Context\Service\WcContextService;
use MyParcelNL\WooCommerce\Pdk\Guzzle7ClientAdapter;
use MyParcelNL\WooCommerce\Pdk\Plugin\Action\WcBackendEndpointService;
use MyParcelNL\WooCommerce\Pdk\Plugin\Action\WcFrontendEndpointService;
Expand All @@ -68,7 +71,9 @@
use MyParcelNL\WooCommerce\Service\WpInstallerService;
use MyParcelNL\WooCommerce\Service\WpScriptService;
use MyParcelNL\WooCommerce\WooCommerce\Contract\WcOrderRepositoryInterface;
use MyParcelNL\WooCommerce\WooCommerce\Contract\WcShippingRepositoryInterface;
use MyParcelNL\WooCommerce\WooCommerce\Repository\WcOrderRepository;
use MyParcelNL\WooCommerce\WooCommerce\Repository\WcShippingRepository;
use Psr\Log\LoggerInterface;
use function DI\factory;
use function DI\get;
Expand Down Expand Up @@ -170,8 +175,9 @@
# Custom services
###

WordPressServiceInterface::class => get(WordPressService::class),
WooCommerceServiceInterface::class => get(WooCommerceService::class),
WcShippingRepositoryInterface::class => get(WcShippingRepository::class),
WooCommerceServiceInterface::class => get(WooCommerceService::class),
WordPressServiceInterface::class => get(WordPressService::class),

###
# PDK services
Expand All @@ -196,6 +202,7 @@
*/

ApiServiceInterface::class => get(MyParcelApiService::class),
ContextServiceInterface::class => get(WcContextService::class),
CronServiceInterface::class => get(WpCronService::class),
WpDatabaseServiceInterface::class => get(WpDatabaseService::class),
InstallerServiceInterface::class => get(WpInstallerService::class),
Expand Down
18 changes: 13 additions & 5 deletions phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,82 @@

$ignoreErrors = [];
$ignoreErrors[] = [
// identifier: ternary.alwaysTrue
'message' => '#^Ternary operator condition is always true\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Hooks/CartFeesHooks.php',
];
$ignoreErrors[] = [
// identifier: booleanNot.alwaysFalse
'message' => '#^Negated boolean expression is always false\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Hooks/CheckoutScriptHooks.php',
];
$ignoreErrors[] = [
// identifier: arguments.count
'message' => '#^Callback expects 1 parameter, \\$accepted_args is set to 2\\.$#',
'count' => 2,
'path' => __DIR__ . '/src/Hooks/SeparateAddressFieldsHooks.php',
];
$ignoreErrors[] = [
// identifier: arguments.count
'message' => '#^Callback expects 1 parameter, \\$accepted_args is set to 2\\.$#',
'count' => 2,
'path' => __DIR__ . '/src/Hooks/TaxFieldsHooks.php',
];
$ignoreErrors[] = [
// identifier: nullCoalesce.property
'message' => '#^Property MyParcelNL\\\\WooCommerce\\\\Migration\\\\Migration4_0_0\\:\\:\\$newCheckoutSettings \\(array\\) on left side of \\?\\? is not nullable\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Migration/Migration4_0_0.php',
];
$ignoreErrors[] = [
// identifier: property.onlyWritten
'message' => '#^Property MyParcelNL\\\\WooCommerce\\\\Migration\\\\Migration4_0_0\\:\\:\\$newDpdSettings is never read, only written\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Migration/Migration4_0_0.php',
];
$ignoreErrors[] = [
// identifier: nullCoalesce.property
'message' => '#^Property MyParcelNL\\\\WooCommerce\\\\Migration\\\\Migration4_0_0\\:\\:\\$newExportDefaultsSettings \\(array\\) on left side of \\?\\? is not nullable\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Migration/Migration4_0_0.php',
];
$ignoreErrors[] = [
// identifier: nullCoalesce.property
'message' => '#^Property MyParcelNL\\\\WooCommerce\\\\Migration\\\\Migration4_0_0\\:\\:\\$newGeneralSettings \\(array\\) on left side of \\?\\? is not nullable\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Migration/Migration4_0_0.php',
];
$ignoreErrors[] = [
// identifier: nullCoalesce.property
'message' => '#^Property MyParcelNL\\\\WooCommerce\\\\Migration\\\\Migration4_0_0\\:\\:\\$newPostnlSettings \\(array\\) on left side of \\?\\? is not nullable\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Migration/Migration4_0_0.php',
];
$ignoreErrors[] = [
// identifier: arguments.count
'message' => '#^Method MyParcelNL\\\\Pdk\\\\Base\\\\Contract\\\\WeightServiceInterface\\:\\:convertToGrams\\(\\) invoked with 1 parameter, 2 required\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Migration/Pdk/SettingsMigration.php',
];
$ignoreErrors[] = [
// identifier: nullCoalesce.variable
'message' => '#^Variable \\$deliveryOptionsData on left side of \\?\\? is never defined\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Pdk/Hooks/PdkCheckoutPlaceOrderHooks.php',
];
$ignoreErrors[] = [
// identifier: empty.property
'message' => '#^Property WooCommerce\\:\\:\\$cart \\(WC_Cart\\) in empty\\(\\) is not falsy\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Pdk/Hooks/PdkFrontendEndpointHooks.php',
];
$ignoreErrors[] = [
// identifier: assign.propertyType
'message' => '#^Property MyParcelNL\\\\Pdk\\\\App\\\\Order\\\\Model\\\\PdkOrder\\:\\:\\$shipments \\(MyParcelNL\\\\Pdk\\\\Shipment\\\\Collection\\\\ShipmentCollection\\|null\\) does not accept MyParcelNL\\\\Pdk\\\\Base\\\\Support\\\\Collection\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Pdk/Plugin/Repository/PdkOrderRepository.php',
];
$ignoreErrors[] = [
'message' => '#^Access to an undefined property WooCommerce\\:\\:\\$shipping\\.$#',
'count' => 1,
'path' => __DIR__ . '/src/Pdk/Plugin/WcShippingMethodRepository.php',
];

return ['parameters' => ['ignoreErrors' => $ignoreErrors]];
176 changes: 0 additions & 176 deletions src/Migration/Pdk/ProductSettingsMigration.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use MyParcelNL\Pdk\Settings\Model\CustomsSettings;
use MyParcelNL\Pdk\Settings\Model\ProductSettings;
use MyParcelNL\Pdk\Shipment\Model\DeliveryOptions;
use MyParcelNL\Sdk\src\Support\Str;
use WC_Data;
use WC_Meta_Data;
use WC_Product;
Expand All @@ -26,7 +25,6 @@ final class ProductSettingsMigration extends AbstractPdkMigration
DeliveryOptions::PACKAGE_TYPE_LETTER_NAME,
];
private const CHUNK_SIZE = 100;
private const FIT_IN_PACKAGE_AMOUNT_LIMIT = 1000;
private const LEGACY_META_KEY_HS_CODE = '_myparcel_hs_code';
private const LEGACY_META_KEY_COUNTRY = '_myparcel_country_of_origin';
private const LEGACY_META_KEY_AGE_CHECK = '_myparcel_age_check';
Expand Down Expand Up @@ -136,89 +134,6 @@ public function up(): void
}
}

/**
* @param array $cartShippingMethods
* @param \WC_Product $wcProduct
*
* @return array
*/
private function addFlatRateShippingClass(array $cartShippingMethods, WC_Product $wcProduct): array
{
$shippingClassId = $wcProduct->get_shipping_class_id();

if ($shippingClassId) {
foreach ($cartShippingMethods as $cartShippingMethod) {
if (! Str::startsWith($cartShippingMethod, 'flat_rate:')) {
continue;
}

$cartShippingMethods[] = "flat_rate:$shippingClassId";

break;
}
}

return $cartShippingMethods;
}

/**
* @param string $packageType
* @param \WC_Product $wcProduct
* @param int $amountInPackageType
* @param int $increment
* @param int $previousIncrement
*
* @return int
* @throws \Exception
*/
private function calculateAmountFitInPackageType(
string $packageType,
WC_Product $wcProduct,
int $amountInPackageType = 0,
int $increment = 1,
int $previousIncrement = 0
): int {
if ($amountInPackageType > self::FIT_IN_PACKAGE_AMOUNT_LIMIT) {
return self::FIT_IN_PACKAGE_AMOUNT_LIMIT;
}

WC()->cart->add_to_cart($wcProduct->get_id(), $increment);

$fitsInPackageType = array_intersect(
$this->getShippingMethodsForPackageType($packageType),
$this->getCartShippingMethods($wcProduct)
);

if (! $fitsInPackageType && $previousIncrement > 1) {
WC()->cart->empty_cart();
WC()->cart->add_to_cart($wcProduct->get_id(), $amountInPackageType - $previousIncrement);

return $this->calculateAmountFitInPackageType(
$packageType,
$wcProduct,
$amountInPackageType,
1,
$increment
);
}

if ($fitsInPackageType) {
$amountInPackageType += $increment;

return $this->calculateAmountFitInPackageType(
$packageType,
$wcProduct,
$amountInPackageType,
$increment * 2,
$increment
);
}

WC()->cart->empty_cart();

return $amountInPackageType;
}

/**
* @return array
*/
Expand All @@ -235,36 +150,6 @@ private function getAllProductIds(): array
}, $allProducts);
}

/**
* @param \WC_Product $product
*
* @return array
*/
private function getCartShippingMethods(WC_Product $product): array
{
$cartShippingPackages = WC()->cart->get_shipping_packages();

return $this->addFlatRateShippingClass($this->getMethodsFromPackages($cartShippingPackages), $product);
}

/**
* @param array $cartShippingMethods
*
* @return string
*/
private function getMatchingPackageType(array $cartShippingMethods): string
{
foreach (self::PACKAGE_TYPES as $packageType) {
if (! array_intersect($this->getShippingMethodsForPackageType($packageType), $cartShippingMethods)) {
continue;
}

return $packageType;
}

return 'package';
}

/**
* @param \WC_Data $data
*
Expand All @@ -279,65 +164,6 @@ private function getMetaData(WC_Data $data): Collection
);
}

/**
* @param array $cartShippingPackages
*
* @return array
*/
private function getMethodsFromPackages(array $cartShippingPackages): array
{
$cartShippingMethods = [];

foreach (array_keys($cartShippingPackages) as $key) {
$shippingForPackage = WC()->session->get("shipping_for_package_$key");

$cartShippingMethods += array_keys($shippingForPackage['rates'] ?? []);
}

return $cartShippingMethods;
}

/**
* @throws \Exception
*/
private function getSettingsForPackageType(WC_Product $wcProduct): array
{
if (null === WC()->cart) {
wc_load_cart();
}

WC()->cart->empty_cart();
WC()->cart->add_to_cart($wcProduct->get_id());

return [
ProductSettings::FIT_IN_MAILBOX => $this->calculateAmountFitInPackageType(
DeliveryOptions::PACKAGE_TYPE_MAILBOX_NAME,
$wcProduct
),
ProductSettings::FIT_IN_DIGITAL_STAMP => $this->calculateAmountFitInPackageType(
DeliveryOptions::PACKAGE_TYPE_DIGITAL_STAMP_NAME,
$wcProduct
),
ProductSettings::PACKAGE_TYPE => $this->getMatchingPackageType(
$this->getCartShippingMethods($wcProduct)
),
];
}

/**
* @param string $packageType
*
* @return array
*/
private function getShippingMethodsForPackageType(string $packageType): array
{
$legacySettings = get_option(SettingsMigration::LEGACY_OPTION_EXPORT_DEFAULTS_SETTINGS) ?: [];

$shippingMethods = $legacySettings['shipping_methods_package_types'] ?? [];

return $shippingMethods[$packageType] ?? [];
}

/**
* @param \WC_Product $wcProduct
*
Expand All @@ -359,8 +185,6 @@ private function migrateProduct(WC_Product $wcProduct): void
$pdkProduct->settings->setAttribute($newKey, $this->normalizeValue($metaData['value']));
}

$pdkProduct->settings->fill($this->getSettingsForPackageType($wcProduct));

$this->pdkProductRepository->update($pdkProduct);

$migrationMeta = $this->getMigrationMeta($wcProduct);
Expand Down
Loading
Loading