Skip to content

Commit f1e33cb

Browse files
authored
PES-2913: introduced carrier and shipping method caching (#829)
2 parents f8c1113 + 541d31e commit f1e33cb

File tree

10 files changed

+130
-24
lines changed

10 files changed

+130
-24
lines changed

changelog.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
== Changelog ==
2+
= 2.0.10 =
3+
Fixed: Introduced carrier and shipping method caching to prevent excessive memory usage and performance problems.
4+
25
= 2.0.9 =
36
Fixed: Type error when migrating guest session to user session during order.
47

languages/packeta.pot

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
# This file is distributed under the GNU General Public License v3.0.
33
msgid ""
44
msgstr ""
5-
"Project-Id-Version: Packeta 2.0.9\n"
5+
"Project-Id-Version: Packeta 2.0.10\n"
66
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/packeta\n"
77
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
88
"Language-Team: LANGUAGE <[email protected]>\n"
99
"MIME-Version: 1.0\n"
1010
"Content-Type: text/plain; charset=UTF-8\n"
1111
"Content-Transfer-Encoding: 8bit\n"
12-
"POT-Creation-Date: 2025-08-08T10:10:14+02:00\n"
12+
"POT-Creation-Date: 2025-08-14T14:49:12+02:00\n"
1313
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1414
"X-Generator: WP-CLI 2.11.0\n"
1515
"X-Domain: packeta\n"
@@ -24,7 +24,7 @@ msgstr ""
2424
#: src/Packetery/Module/Carrier/PacketaPickupPointsConfig.php:137
2525
#: src/Packetery/Module/Checkout/CheckoutRenderer.php:88
2626
#: src/Packetery/Module/Checkout/CheckoutRenderer.php:110
27-
#: src/Packetery/Module/Checkout/CheckoutSettings.php:181
27+
#: src/Packetery/Module/Checkout/CheckoutSettings.php:190
2828
#: src/Packetery/Module/DashboardWidget.php:116
2929
#: src/Packetery/Module/DashboardWidget.php:189
3030
#: src/Packetery/Module/Log/Page.php:133
@@ -582,38 +582,38 @@ msgstr ""
582582
msgid "COD surcharge"
583583
msgstr ""
584584

585-
#: src/Packetery/Module/Checkout/CheckoutSettings.php:182
585+
#: src/Packetery/Module/Checkout/CheckoutSettings.php:191
586586
#: src/Packetery/Module/Order/Metabox.php:647
587587
msgid "Choose pickup point"
588588
msgstr ""
589589

590-
#: src/Packetery/Module/Checkout/CheckoutSettings.php:183
590+
#: src/Packetery/Module/Checkout/CheckoutSettings.php:192
591591
#: src/Packetery/Module/Checkout/CheckoutValidator.php:157
592592
msgid "Pickup point is not chosen."
593593
msgstr ""
594594

595-
#: src/Packetery/Module/Checkout/CheckoutSettings.php:184
595+
#: src/Packetery/Module/Checkout/CheckoutSettings.php:193
596596
msgid "Loading Packeta widget button..."
597597
msgstr ""
598598

599-
#: src/Packetery/Module/Checkout/CheckoutSettings.php:185
599+
#: src/Packetery/Module/Checkout/CheckoutSettings.php:194
600600
msgid "Choose delivery address"
601601
msgstr ""
602602

603-
#: src/Packetery/Module/Checkout/CheckoutSettings.php:186
603+
#: src/Packetery/Module/Checkout/CheckoutSettings.php:195
604604
msgid "Address validation is out of order"
605605
msgstr ""
606606

607-
#: src/Packetery/Module/Checkout/CheckoutSettings.php:187
607+
#: src/Packetery/Module/Checkout/CheckoutSettings.php:196
608608
#: src/Packetery/Module/Order/Metabox.php:599
609609
msgid "The selected country does not correspond to the destination country."
610610
msgstr ""
611611

612-
#: src/Packetery/Module/Checkout/CheckoutSettings.php:188
612+
#: src/Packetery/Module/Checkout/CheckoutSettings.php:197
613613
msgid "The order will be delivered to the address:"
614614
msgstr ""
615615

616-
#: src/Packetery/Module/Checkout/CheckoutSettings.php:189
616+
#: src/Packetery/Module/Checkout/CheckoutSettings.php:198
617617
msgid "Delivery address has not been chosen. Choosing a delivery address using the widget is required by this carrier."
618618
msgstr ""
619619

@@ -1473,7 +1473,7 @@ msgstr ""
14731473

14741474
#: src/Packetery/Module/Order/GridExtender.php:399
14751475
#: src/Packetery/Module/Order/Metabox.php:430
1476-
#: src/Packetery/Module/Views/AssetManager.php:246
1476+
#: src/Packetery/Module/Views/AssetManager.php:254
14771477
msgid "It is not possible to submit the shipment because all the information required for this shipment is not filled."
14781478
msgstr ""
14791479

@@ -2076,7 +2076,7 @@ msgstr ""
20762076
msgid "Database %s table of Packeta plugin could not be created or altered, you can find more information in Packeta log."
20772077
msgstr ""
20782078

2079-
#: src/Packetery/Module/Views/AssetManager.php:245
2079+
#: src/Packetery/Module/Views/AssetManager.php:253
20802080
msgid "Customs declaration has to be filled in order detail."
20812081
msgstr ""
20822082

packeta.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
* Plugin Name: Packeta
1010
* Description: This is the official plugin, that allows you to choose pickup points of Packeta and its external carriers in all of Europe, or utilize address delivery to 25 countries in the European Union, straight from the cart in your e-shop. Furthermore, you can also submit all your orders to Packeta with just one click.
11-
* Version: 2.0.9
11+
* Version: 2.0.10
1212
* Author: Zásilkovna s.r.o.
1313
* Author URI: https://www.zasilkovna.cz/
1414
* Text Domain: packeta

readme.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Contributors: packeta
33
Tags: WooCommerce, shipping
44
Requires at least: 5.5
55
Tested up to: 6.8.2
6-
Stable tag: 2.0.9
6+
Stable tag: 2.0.10
77
Requires PHP: 7.2
88
WC requires at least: 5.1
99
WC tested up to: 10.0.4
@@ -63,6 +63,9 @@ We are constantly working on adding new features. If there is a feature you woul
6363
Please contact us at [email protected] .
6464

6565
== Changelog ==
66+
= 2.0.10 =
67+
Fixed: Introduced carrier and shipping method caching to prevent excessive memory usage and performance problems.
68+
6669
= 2.0.9 =
6770
Fixed: Type error when migrating guest session to user session during order.
6871

src/Packetery/Module/Carrier/EntityRepository.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
*/
2020
class EntityRepository {
2121

22+
/**
23+
* @var array<int, Entity\Carrier|null>
24+
*/
25+
private static $carrierDataCache = [];
26+
2227
/**
2328
* Carrier repository.
2429
*
@@ -82,7 +87,7 @@ public function __construct(
8287
*
8388
* @return Entity\Carrier|null
8489
*/
85-
public function getById( int $carrierId ): ?Entity\Carrier {
90+
private function getById( int $carrierId ): ?Entity\Carrier {
8691
$result = $this->repository->getById( $carrierId );
8792
if ( $result === null ) {
8893
return null;
@@ -91,14 +96,23 @@ public function getById( int $carrierId ): ?Entity\Carrier {
9196
return $this->carrierEntityFactory->fromDbResult( $result );
9297
}
9398

99+
private function getByIdCached( int $carrierId ): ?Entity\Carrier {
100+
if ( ! isset( self::$carrierDataCache[ $carrierId ] ) ) {
101+
self::$carrierDataCache[ $carrierId ] = $this->getById( $carrierId );
102+
}
103+
104+
return self::$carrierDataCache[ $carrierId ];
105+
}
106+
94107
/**
95108
* Gets feed carrier or Packeta carrier by id.
96109
*
97110
* @param string $carrierId Extended branch service id.
111+
* @param bool $useCache
98112
*
99113
* @return Entity\Carrier|null
100114
*/
101-
public function getAnyById( string $carrierId ): ?Entity\Carrier {
115+
public function getAnyById( string $carrierId, bool $useCache = false ): ?Entity\Carrier {
102116
$nonFeedCarriers = $this->pickupPointsConfig->getCompoundAndVendorCarriers();
103117

104118
foreach ( $nonFeedCarriers as $nonFeedCarrier ) {
@@ -111,6 +125,10 @@ public function getAnyById( string $carrierId ): ?Entity\Carrier {
111125
return null;
112126
}
113127

128+
if ( $useCache === true ) {
129+
return $this->getByIdCached( (int) $carrierId );
130+
}
131+
114132
return $this->getById( (int) $carrierId );
115133
}
116134

src/Packetery/Module/Hooks/HookRegistrar.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -573,9 +573,7 @@ public function addLinksToPluginGrid(): void {
573573
*/
574574
public function addShippingMethods( array $methods ): array {
575575
if ( $this->optionsProvider->isWcCarrierConfigEnabled() ) {
576-
$unsortedMethods = $this->shippingProvider->addMethods( $methods );
577-
578-
return $this->shippingProvider->sortMethods( $unsortedMethods );
576+
return $this->shippingProvider->getSortedCachedMethods( $methods );
579577
}
580578

581579
$methods[ ShippingMethod::PACKETERY_METHOD_ID ] = ShippingMethod::class;

src/Packetery/Module/Plugin.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919
class Plugin {
2020

21-
public const VERSION = '2.0.9';
21+
public const VERSION = '2.0.10';
2222
public const DOMAIN = 'packeta';
2323
public const PARAM_PACKETERY_ACTION = 'packetery_action';
2424
public const PARAM_NONCE = '_wpnonce';

src/Packetery/Module/Shipping/BaseShippingMethod.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function __construct( int $instanceId = 0 ) {
7171
// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
7272
$this->method_description = __( 'Allows to choose one of Packeta delivery methods', 'packeta' );
7373

74-
$carrier = $this->carrierRepository->getAnyById( static::CARRIER_ID );
74+
$carrier = $this->carrierRepository->getAnyById( static::CARRIER_ID, true );
7575
if ( $carrier !== null ) {
7676
// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
7777
$this->method_title = $carrier->getName();

src/Packetery/Module/Shipping/ShippingProvider.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
use WC_Order;
1717

1818
class ShippingProvider {
19+
/**
20+
* @var array<int, array<string, string>>
21+
*/
22+
private static $sortedMethodsCache = [];
1923

2024
/**
2125
* @var FeatureFlagProvider
@@ -153,7 +157,7 @@ public static function isPacketaMethod( string $methodId ): bool {
153157
*
154158
* @return array<string, string>
155159
*/
156-
public function addMethods( array $methods ): array {
160+
private function addMethods( array $methods ): array {
157161
$zoneId = $this->contextResolver->getShippingZoneId();
158162
if ( $zoneId === null ) {
159163
return $this->addAllMethods( $methods );
@@ -225,7 +229,7 @@ private function addActiveCarrierMethod( string $fullyQualifiedClassname, array
225229
*
226230
* @return array<string, string>
227231
*/
228-
public function sortMethods( array $methods ): array {
232+
private function sortMethods( array $methods ): array {
229233
uasort(
230234
$methods,
231235
function ( $classA, $classB ) {
@@ -239,4 +243,21 @@ function ( $classA, $classB ) {
239243

240244
return $methods;
241245
}
246+
247+
/**
248+
* @param array<string, string> $originalMethods
249+
*
250+
* @return array<string, string>
251+
*/
252+
public function getSortedCachedMethods( array $originalMethods ): array {
253+
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
254+
$cacheKey = crc32( serialize( $originalMethods ) );
255+
256+
if ( ! isset( self::$sortedMethodsCache[ $cacheKey ] ) ) {
257+
$unsortedMethods = $this->addMethods( $originalMethods );
258+
self::$sortedMethodsCache[ $cacheKey ] = $this->sortMethods( $unsortedMethods );
259+
}
260+
261+
return self::$sortedMethodsCache[ $cacheKey ];
262+
}
242263
}

tests/Module/Shipping/ShippingProviderTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,47 @@
44

55
namespace Tests\Module\Shipping;
66

7+
use Packetery\Module\Carrier\CarDeliveryConfig;
8+
use Packetery\Module\Carrier\CarrierOptionsFactory;
9+
use Packetery\Module\Carrier\EntityRepository;
10+
use Packetery\Module\Carrier\PacketaPickupPointsConfig;
11+
use Packetery\Module\ContextResolver;
12+
use Packetery\Module\Options\FlagManager\FeatureFlagProvider;
713
use Packetery\Module\Shipping\BaseShippingMethod;
814
use Packetery\Module\Shipping\ShippingProvider;
915
use Packetery\Module\ShippingMethod;
16+
use Packetery\Module\ShippingZoneRepository;
17+
use PHPUnit\Framework\MockObject\MockObject;
1018
use PHPUnit\Framework\TestCase;
19+
use ReflectionClass;
1120

1221
class ShippingProviderTest extends TestCase {
22+
23+
private ContextResolver&MockObject $contextResolver;
24+
private ShippingZoneRepository&MockObject $shippingZoneRepository;
25+
26+
private function createShippingProvider(): ShippingProvider {
27+
$this->contextResolver = $this->createMock( ContextResolver::class );
28+
$this->shippingZoneRepository = $this->createMock( ShippingZoneRepository::class );
29+
30+
return new ShippingProvider(
31+
$this->createMock( FeatureFlagProvider::class ),
32+
$this->createMock( PacketaPickupPointsConfig::class ),
33+
$this->createMock( CarDeliveryConfig::class ),
34+
$this->contextResolver,
35+
$this->shippingZoneRepository,
36+
$this->createMock( EntityRepository::class ),
37+
$this->createMock( CarrierOptionsFactory::class )
38+
);
39+
}
40+
41+
public function tearDown(): void {
42+
$shippingProviderReflection = new ReflectionClass( ShippingProvider::class );
43+
$property = $shippingProviderReflection->getProperty( 'sortedMethodsCache' );
44+
$property->setAccessible( true );
45+
$property->setValue( [] );
46+
}
47+
1348
/**
1449
* @return array
1550
*/
@@ -48,4 +83,32 @@ public static function shippingMethodsProvider(): array {
4883
public function testIsPacketaMethod( $methodId, $isPacketaMethod ): void {
4984
self::assertEquals( $isPacketaMethod, ShippingProvider::isPacketaMethod( $methodId ) );
5085
}
86+
87+
public function testGetSortedCachedMethodsFillsCache(): void {
88+
$shippingProvider = $this->createShippingProvider();
89+
90+
$dummyZoneId = 123;
91+
$this->contextResolver->expects( $this->once() )->method( 'getShippingZoneId' )->willReturn( $dummyZoneId );
92+
$this->shippingZoneRepository->expects( $this->once() )->method( 'getCountryCodesForShippingZone' )->willReturn( [] );
93+
94+
$shippingProvider->getSortedCachedMethods( [] );
95+
}
96+
97+
public function testGetSortedCachedMethodsGetsFromCache(): void {
98+
$shippingProvider = $this->createShippingProvider();
99+
100+
$originalMethods = [];
101+
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
102+
$cacheKey = crc32( serialize( $originalMethods ) );
103+
104+
$shippingProviderReflection = new ReflectionClass( ShippingProvider::class );
105+
$property = $shippingProviderReflection->getProperty( 'sortedMethodsCache' );
106+
$property->setAccessible( true );
107+
$property->setValue( [ $cacheKey => [ 'dummyMethodId' => 'dummyMethodClass' ] ] );
108+
109+
$this->contextResolver->expects( $this->never() )->method( 'getShippingZoneId' );
110+
$this->shippingZoneRepository->expects( $this->never() )->method( 'getCountryCodesForShippingZone' );
111+
112+
$shippingProvider->getSortedCachedMethods( $originalMethods );
113+
}
51114
}

0 commit comments

Comments
 (0)