|
6 | 6 | */ |
7 | 7 |
|
8 | 8 | use Drupal\commerce_promotion\Entity\PromotionInterface; |
| 9 | +use Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\OrderItemPromotionOfferInterface; |
9 | 10 | use Drupal\Core\Field\BaseFieldDefinition; |
10 | 11 |
|
11 | 12 | /** |
@@ -233,3 +234,153 @@ function commerce_promotion_post_update_8(&$sandbox = NULL) { |
233 | 234 | $sandbox['#finished'] = ($sandbox['total_count'] - $sandbox['current_count']) / $sandbox['total_count']; |
234 | 235 | } |
235 | 236 | } |
| 237 | + |
| 238 | +/** |
| 239 | + * Update offers and conditions. |
| 240 | + */ |
| 241 | +function commerce_promotion_post_update_9(&$sandbox = NULL) { |
| 242 | + $promotion_storage = \Drupal::entityTypeManager()->getStorage('commerce_promotion'); |
| 243 | + if (!isset($sandbox['current_count'])) { |
| 244 | + $query = $promotion_storage->getQuery(); |
| 245 | + $sandbox['total_count'] = $query->count()->execute(); |
| 246 | + $sandbox['current_count'] = 0; |
| 247 | + $sandbox['disabled_offers'] = []; |
| 248 | + $sandbox['disabled_conditions'] = []; |
| 249 | + |
| 250 | + if (empty($sandbox['total_count'])) { |
| 251 | + $sandbox['#finished'] = 1; |
| 252 | + return; |
| 253 | + } |
| 254 | + } |
| 255 | + |
| 256 | + $query = $promotion_storage->getQuery(); |
| 257 | + $query->range($sandbox['current_count'], 25); |
| 258 | + $result = $query->execute(); |
| 259 | + if (empty($result)) { |
| 260 | + $sandbox['#finished'] = 1; |
| 261 | + return; |
| 262 | + } |
| 263 | + |
| 264 | + /** @var \Drupal\commerce_promotion\Entity\PromotionInterface[] $promotions */ |
| 265 | + $promotions = $promotion_storage->loadMultiple($result); |
| 266 | + foreach ($promotions as $promotion) { |
| 267 | + $needs_save = FALSE; |
| 268 | + $needs_disable = FALSE; |
| 269 | + |
| 270 | + $conditions = $promotion->getConditions(); |
| 271 | + $order_item_conditions = array_filter($conditions, function ($condition) { |
| 272 | + /** @var \Drupal\commerce\Plugin\Commerce\Condition\ConditionInterface $condition */ |
| 273 | + return $condition->getEntityTypeId() == 'commerce_order_item' && $condition->getPluginId() != 'order_item_quantity'; |
| 274 | + }); |
| 275 | + $condition_map = [ |
| 276 | + 'order_item_product' => 'order_product', |
| 277 | + 'order_item_product_type' => 'order_product_type', |
| 278 | + 'order_item_variation_type' => 'order_variation_type', |
| 279 | + ]; |
| 280 | + $condition_items = $promotion->get('conditions')->getValue(); |
| 281 | + |
| 282 | + $known_order_item_offers = [ |
| 283 | + 'order_item_fixed_amount_off', |
| 284 | + 'order_item_percentage_off', |
| 285 | + ]; |
| 286 | + $offer = $promotion->getOffer(); |
| 287 | + $offer_item = $promotion->get('offer')->first()->getValue(); |
| 288 | + |
| 289 | + if ($offer->getEntityTypeId() == 'commerce_order_item') { |
| 290 | + $needs_save = TRUE; |
| 291 | + // Transfer order item conditions to the offer. |
| 292 | + // Modify the offer item directly to be able to upgrade offers that |
| 293 | + // haven't yet been converted to extend OfferItemPromotionOfferBase. |
| 294 | + $offer_item['target_plugin_configuration']['conditions'] = []; |
| 295 | + foreach ($order_item_conditions as $condition) { |
| 296 | + $offer_item['target_plugin_configuration']['conditions'][] = [ |
| 297 | + 'plugin' => $condition->getPluginId(), |
| 298 | + 'configuration' => $condition->getConfiguration(), |
| 299 | + ]; |
| 300 | + } |
| 301 | + |
| 302 | + // The promotion is using a custom offer which hasn't been updated yet, |
| 303 | + // disable it so that it can get updated without crashing everything. |
| 304 | + if (!in_array($offer->getPluginId(), $known_order_item_offers)) { |
| 305 | + if (!($offer instanceof OrderItemPromotionOfferInterface)) { |
| 306 | + $needs_disable = TRUE; |
| 307 | + $sandbox['disabled_offers'][] = $promotion->label(); |
| 308 | + } |
| 309 | + } |
| 310 | + } |
| 311 | + |
| 312 | + // Convert known order item conditions to order conditions. |
| 313 | + if ($order_item_conditions) { |
| 314 | + foreach ($condition_items as $index => $condition_item) { |
| 315 | + if (array_key_exists($condition_item['target_plugin_id'], $condition_map)) { |
| 316 | + $condition_items[$index]['target_plugin_id'] = $condition_map[$condition_item['target_plugin_id']]; |
| 317 | + $needs_save = TRUE; |
| 318 | + } |
| 319 | + } |
| 320 | + $promotion->set('conditions', $condition_items); |
| 321 | + } |
| 322 | + |
| 323 | + // Drop unknown order item conditions. |
| 324 | + $conditions = $promotion->getConditions(); |
| 325 | + $order_item_conditions = array_filter($conditions, function ($condition) { |
| 326 | + /** @var \Drupal\commerce\Plugin\Commerce\Condition\ConditionInterface $condition */ |
| 327 | + return $condition->getEntityTypeId() == 'commerce_order_item' && $condition->getPluginId() != 'order_item_quantity'; |
| 328 | + }); |
| 329 | + foreach ($order_item_conditions as $condition) { |
| 330 | + foreach ($condition_items as $index => $condition_item) { |
| 331 | + if ($condition_item['target_plugin_id'] == $condition->getPluginId()) { |
| 332 | + unset($condition_items[$index]); |
| 333 | + $needs_save = TRUE; |
| 334 | + // An unrecognized offer was dropped, but because the offer applies |
| 335 | + // to the order, wasn't transferred there. Disable the promotion |
| 336 | + // to allow the merchant to double check the new configuration. |
| 337 | + if ($offer->getEntityTypeId() == 'commerce_order') { |
| 338 | + $needs_disable = TRUE; |
| 339 | + $sandbox['disabled_conditions'][$promotion->id()] = [$promotion->label(), $condition->getPluginId()]; |
| 340 | + } |
| 341 | + } |
| 342 | + } |
| 343 | + } |
| 344 | + |
| 345 | + if ($needs_disable) { |
| 346 | + $promotion->setEnabled(FALSE); |
| 347 | + } |
| 348 | + if ($needs_save) { |
| 349 | + $promotion->set('offer', $offer_item); |
| 350 | + $promotion->set('conditions', array_values($condition_items)); |
| 351 | + $promotion->save(); |
| 352 | + } |
| 353 | + } |
| 354 | + |
| 355 | + $sandbox['current_count'] += 25; |
| 356 | + if ($sandbox['current_count'] >= $sandbox['total_count']) { |
| 357 | + $sandbox['#finished'] = 1; |
| 358 | + } |
| 359 | + else { |
| 360 | + $sandbox['#finished'] = ($sandbox['total_count'] - $sandbox['current_count']) / $sandbox['total_count']; |
| 361 | + } |
| 362 | + |
| 363 | + if ($sandbox['#finished']) { |
| 364 | + $message = ''; |
| 365 | + if ($sandbox['disabled_offers']) { |
| 366 | + $message .= 'These promotions have been disabled because their offers need to be updated for Commerce 2.8: <br>'; |
| 367 | + foreach ($sandbox['disabled_offers'] as $promotion_title) { |
| 368 | + $message .= '- ' . $promotion_title . '<br>'; |
| 369 | + } |
| 370 | + } |
| 371 | + if ($sandbox['disabled_conditions']) { |
| 372 | + $message .= 'These promotions have been disabled because their conditions need to be updated for Commerce 2.8: <br>'; |
| 373 | + foreach ($sandbox['disabled_conditions'] as $item) { |
| 374 | + $message .= '- ' . $item[0] . ' (Condition: ' . $item[1] . ') <br>'; |
| 375 | + } |
| 376 | + } |
| 377 | + if ($message) { |
| 378 | + $message .= 'Please see https://www.drupal.org/node/2982334 for more information.'; |
| 379 | + } |
| 380 | + else { |
| 381 | + $message .= 'Successfully updated all promotions'; |
| 382 | + } |
| 383 | + |
| 384 | + return $message; |
| 385 | + } |
| 386 | +} |
0 commit comments