PluginProbe
Packeta / 2.0.9
Packeta v2.0.9
2.3.2 2.3.1 trunk 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3.0 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 All 56 releases
packeta / src / Packetery / Module / Order / CarrierModal.php

CarrierModal.php in Packeta 2.0.9, at src/Packetery/Module/Order/CarrierModal.php

318 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class CarrierModal.
4 *
5 * @package Packetery
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module\Order;
11
12 use Packetery\Latte;
13 use Packetery\Module\Carrier;
14 use Packetery\Module\Carrier\CarrierOptionsFactory;
15 use Packetery\Module\ModuleHelper;
16 use Packetery\Module\Options\OptionsProvider;
17 use Packetery\Nette\Forms;
18 use Packetery\Nette\Forms\Controls\SubmitButton;
19 use RuntimeException;
20 use WC_Order_Item_Shipping;
21
22 /**
23 * Class CarrierModal.
24 *
25 * @package Packetery
26 */
27 class CarrierModal {
28
29 public const MODAL_ID = 'wc-packetery-carrier-modal';
30
31 /**
32 * Latte engine.
33 *
34 * @var Latte\Engine
35 */
36 private $latteEngine;
37
38 /**
39 * Order detail common logic.
40 *
41 * @var DetailCommonLogic
42 */
43 private $detailCommonLogic;
44
45 /**
46 * Order repository.
47 *
48 * @var CarrierModalFormFactory
49 */
50 private $carrierModalFormFactory;
51
52 /**
53 * Carrier repository.
54 *
55 * @var Carrier\EntityRepository
56 */
57 private $carrierRepository;
58
59 /**
60 * Order repository.
61 *
62 * @var Repository
63 */
64 private $orderRepository;
65
66 /**
67 * @var OptionsProvider
68 */
69 private $optionsProvider;
70
71 /**
72 * Carrier options factory.
73 *
74 * @var CarrierOptionsFactory
75 */
76 private $carrierOptionsFactory;
77
78 public function __construct(
79 Latte\Engine $latteEngine,
80 DetailCommonLogic $detailCommonLogic,
81 CarrierModalFormFactory $carrierModalFormFactory,
82 Repository $orderRepository,
83 Carrier\EntityRepository $carrierRepository,
84 OptionsProvider $optionsProvider,
85 CarrierOptionsFactory $carrierOptionsFactory
86 ) {
87 $this->latteEngine = $latteEngine;
88 $this->detailCommonLogic = $detailCommonLogic;
89 $this->carrierModalFormFactory = $carrierModalFormFactory;
90 $this->orderRepository = $orderRepository;
91 $this->carrierRepository = $carrierRepository;
92 $this->optionsProvider = $optionsProvider;
93 $this->carrierOptionsFactory = $carrierOptionsFactory;
94 }
95
96 /**
97 * Registers order modal.
98 *
99 * @return void
100 */
101 public function register(): void {
102 add_action( 'admin_head', [ $this, 'renderCarrierModal' ] );
103 }
104
105 /**
106 * Renders modal.
107 *
108 * @return void
109 */
110 public function renderCarrierModal(): void {
111 if (
112 $this->detailCommonLogic->isPacketeryOrder() === false ||
113 $this->canBeDisplayed() === false
114 ) {
115 return;
116 }
117
118 $form = $this->carrierModalFormFactory->create(
119 $this->getCarrierOptionsByCountry(),
120 $this->getCurrentCarrier()
121 );
122 $form->onSuccess[] = [ $this, 'onFormSuccess' ];
123
124 $submitButton = $form['submit'];
125 if ( $submitButton instanceof SubmitButton && $submitButton->isSubmittedBy() ) {
126 $form->fireEvents();
127 }
128
129 $this->latteEngine->render(
130 PACKETERY_PLUGIN_DIR . '/template/order/carrier-modal.latte',
131 [
132 'id' => self::MODAL_ID,
133 'form' => $form,
134 'translations' => [
135 'header' => __( 'Set carrier', 'packeta' ),
136 'closeModalPanel' => __( 'Close modal panel', 'packeta' ),
137 ],
138 ]
139 );
140 }
141
142 /**
143 * On form success.
144 *
145 * @param Forms\Form $form Form.
146 *
147 * @return void
148 *
149 * @throws RuntimeException In case carrier id could not be obtained.
150 */
151 public function onFormSuccess( Forms\Form $form ): void {
152 $values = $form->getValues();
153 $orderId = $this->detailCommonLogic->getOrderId();
154 $newCarrierId = (string) $values[ CarrierModalFormFactory::FIELD_CARRIER_ID ];
155 if ( $orderId === null ) {
156 throw new RuntimeException( 'Packeta: Failed to process carrier change, new carrier id ' . $newCarrierId );
157 }
158
159 $order = $this->detailCommonLogic->getOrder();
160 if ( $order !== null && $order->getCarrier()->getId() !== $newCarrierId ) {
161 $this->orderRepository->delete( (int) $order->getNumber() );
162 }
163
164 $carrierTitle = $this->createNewCarrierOrder( $orderId, $newCarrierId );
165 $this->updateOrderDeliveryTitle( $orderId, $carrierTitle );
166
167 // Without it, the widget cannot be opened and metabox has no values. Needed even in case no change was made.
168 if ( wp_safe_redirect( ModuleHelper::getOrderDetailUrl( $orderId ) ) ) {
169 exit;
170 }
171 }
172
173 /**
174 * Saves order stub with new Carrier, if instantiable.
175 *
176 * @param int $orderId Order id.
177 * @param string $newCarrierId Carrier id.
178 *
179 * @return string
180 *
181 * @throws RuntimeException In case carrier is not instantiable.
182 */
183 private function createNewCarrierOrder( int $orderId, string $newCarrierId ): string {
184 $newCarrier = $this->carrierRepository->getAnyById( $newCarrierId );
185 if ( $newCarrier === null ) {
186 throw new RuntimeException( 'Packeta: Failed to get instance of carrier with id ' . $newCarrierId );
187 }
188 $this->orderRepository->saveData(
189 [
190 'id' => $orderId,
191 'carrier_id' => $newCarrierId,
192 ]
193 );
194
195 $options = $this->carrierOptionsFactory->createByCarrierId( $newCarrier->getId() );
196 if ( ! $options->hasOptions() ) {
197 throw new RuntimeException( 'Missing options for carrier ' . $newCarrier->getId() );
198 }
199
200 return $options->getName();
201 }
202
203 /**
204 * Gets carrier names by the country of destination.
205 *
206 * @return string[]
207 */
208 private function getCarrierOptionsByCountry(): array {
209 static $carrierOptions;
210
211 if ( isset( $carrierOptions ) ) {
212 return $carrierOptions;
213 }
214
215 $wcOrderId = $this->detailCommonLogic->getOrderId();
216 if ( $wcOrderId === null ) {
217 return [];
218 }
219
220 $wcOrder = $this->orderRepository->getWcOrderById( $wcOrderId );
221 if ( $wcOrder === null ) {
222 return [];
223 }
224
225 $shippingCountry = ModuleHelper::getWcOrderCountry( $wcOrder );
226 if ( $shippingCountry === '' ) {
227 return [];
228 }
229
230 $carriers = $this->carrierRepository->getByCountryIncludingNonFeed( $shippingCountry );
231
232 $carrierOptions = [];
233 foreach ( $carriers as $carrier ) {
234 $options = $this->carrierOptionsFactory->createByCarrierId( $carrier->getId() );
235 if ( $options->hasOptions() ) {
236 $carrierOptions[ $carrier->getId() ] = $options->getName();
237 }
238 }
239
240 return $carrierOptions;
241 }
242
243 /**
244 * There must be two carriers at least and no packet id.
245 *
246 * @return bool
247 */
248 public function canBeDisplayed(): bool {
249 $carrierOptions = $this->getCarrierOptionsByCountry();
250 if ( $carrierOptions === [] ) {
251 return false;
252 }
253
254 if ( $this->optionsProvider->isWcCarrierConfigEnabled() ) {
255 return false;
256 }
257
258 $order = $this->detailCommonLogic->getOrder();
259
260 return ( $order === null || $order->getPacketId() === null );
261 }
262
263 /**
264 * Gets metabox HTML with carrier selection button.
265 *
266 * @return string
267 */
268 public function getMetaboxHtml(): string {
269 return $this->latteEngine->renderToString(
270 PACKETERY_PLUGIN_DIR . '/template/order/metabox-carrier.latte',
271 [
272 'translations' => [
273 'setCarrier' => __( 'Set carrier', 'packeta' ),
274 ],
275 ]
276 );
277 }
278
279 /**
280 * Get current order carrier.
281 *
282 * @return string|null
283 */
284 private function getCurrentCarrier(): ?string {
285 $order = $this->detailCommonLogic->getOrder();
286 if ( $order === null ) {
287 return null;
288 }
289
290 return $order->getCarrier()->getId();
291 }
292
293 /**
294 * Update the delivery title of a specific order.
295 *
296 * @param int $orderId The ID of the order to update.
297 * @param string $carrierTitle The new shipping title to set.
298 *
299 * @return void
300 */
301 private function updateOrderDeliveryTitle( int $orderId, string $carrierTitle ): void {
302 $order = $this->orderRepository->getWcOrderById( $orderId );
303 if ( $order === null ) {
304 return;
305 }
306 $shippingItems = $order->get_items( 'shipping' );
307 if ( is_array( $shippingItems ) && count( $shippingItems ) > 0 ) {
308 $firstItem = reset( $shippingItems );
309 if ( $firstItem instanceof WC_Order_Item_Shipping ) {
310 $firstItem->set_method_title( $carrierTitle );
311 $firstItem->save();
312 $order->calculate_totals();
313 $order->save();
314 }
315 }
316 }
317 }
318