Commit a4ebf244 authored by Omkar Deshpande's avatar Omkar Deshpande Committed by VIGHNESH SADAGOPAL
Browse files

Issue #3282617 by omkar-pd, Vighnesh.: Drupal 9 compatibility

parent f0928b61
Loading
Loading
Loading
Loading
+1 −1
Changes for magento.info.yml: 1 added line, 1 removed line.
Original line number Diff line number Diff line
name: Magento
description: 'Custom module to synchronize content and products data from Magento.'
type: module
core: 8.x
core_version_requirement: ^8.8 || ^9
package: 'Magento'
configure: magento.admin_settings
dependencies:
+1 −1
Changes for magento.services.yml: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -4,4 +4,4 @@ services:
    arguments: ['@config.factory', '@http_client', '@logger.factory']
  magento.utils:
    class: Drupal\magento\Services\MagentoUtils
    arguments: ['@path.alias_storage', '@config.factory', '@database', '@commerce_price.currency_importer', '@entity_type.manager', '@commerce_product.attribute_field_manager', '@logger.factory', '@magento.client', '@commerce_stock.service_manager']
    arguments: ['@config.factory', '@database', '@commerce_price.currency_importer', '@entity_type.manager', '@commerce_product.attribute_field_manager', '@logger.factory', '@magento.client', '@commerce_stock.service_manager']
+212 −29
Changes for src/Services/MagentoUtils.php: 212 added lines, 29 removed lines.
Original line number Diff line number Diff line
@@ -11,11 +11,11 @@ use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Path\AliasStorageInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\file\Entity\File;
use Drupal\magento\Model\SearchCriteria;
use Drupal\entity\BundleFieldDefinition;

/**
 * Class MagentoUtils.
@@ -204,7 +204,6 @@ class MagentoUtils {
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function __construct(
    AliasStorageInterface $aliasStorage,
    ConfigFactoryInterface $config,
    Connection $database,
    CurrencyImporterInterface $currencyImporter,
@@ -216,7 +215,7 @@ class MagentoUtils {
  ) {
    $this->addOnStorage = $entityTypeManager->getStorage('commerce_addon');
    $this->addOnTypeStorage = $entityTypeManager->getStorage('commerce_addon_type');
    $this->aliasStorage = $aliasStorage;
    $this->aliasStorage = $entityTypeManager->getStorage('path_alias')->create();
    $this->config = $config->get('magento.settings');
    $this->currencyImporter = $currencyImporter;
    $this->database = $database;
@@ -774,10 +773,16 @@ class MagentoUtils {
   *   Drupal term ID.
   */
  public function getCategoryTerm($magentoCategoryId) {
    $category = $this->magentoClient->getCategory($magentoCategoryId);
    if ($category) {
      $name = isset($category['name']) ? $category['name'] : '';
      $term = reset($this->termStorage->loadByProperties([
        'name' => $name,
      ]));

      return $term ? $term->id() : 0;
    }
  }


  /**
@@ -794,51 +799,88 @@ class MagentoUtils {
  public function createProduct(array $data, $currencyCode) {
    $id = 0;
    $productType = $this->productTypeStorage->load($data['attribute_set_id']);
    $productTypes = $this->magentoClient->getProductAttributeSets(new SearchCriteria([
      'field' => 'attribute_set_id',
      'condition' => 'gt',
      'value' => 0,
    ]));
    if ($productType) {
      $drupalProductTypeFields = isset($data['custom_attributes']) ? $data['custom_attributes'] : [];
      $attribute_mapping = [];
      $drupalProductTypeFields = $data['custom_attributes'] ?? [];
      $variations = [];
      $sku = $data['sku'];
      $configurableProductOptions = isset($data['extension_attributes']['configurable_product_options'])
        ? $data['extension_attributes']['configurable_product_options'] : [];
      $configurableProductLinks = isset($data['extension_attributes']['configurable_product_links'])
        ? $data['extension_attributes']['configurable_product_links'] : [];
      $product_links = isset($data['product_links']) ? $data['product_links'] : [];
      $configurableProductOptions = $data['extension_attributes']['configurable_product_options'] ?? [];
      $configurableProductLinks = $data['extension_attributes']['configurable_product_links'] ?? [];
      $product_links = $data['product_links'] ?? [];
      $variationTypes = $this->getProductVariationTypes($data['type_id'], $configurableProductOptions, $product_links);
      $quantity = (float) (isset($data['extension_attributes']['stock_item']['qty'])
        ? $data['extension_attributes']['stock_item']['qty'] : 0);
      $mediaGalleryEntries = isset($data['media_gallery_entries']) ? $data['media_gallery_entries'] : [];
      $quantity = (float) ($data['extension_attributes']['stock_item']['qty'] ?? 0);
      $mediaGalleryEntries = $data['media_gallery_entries'] ?? [];
      try {
        foreach ($productTypes as $product) {
          $variationTypes[] = [
            'variation_type' => str_replace(" ", "_", strtolower($product['attribute_set_name'])),
            'attribute_id' => $product['attribute_set_id'],
          ];
          $customVariations[] = [
            'variation_type' => str_replace(" ", "_", strtolower($product['attribute_set_name'])),
            'attribute_id' => $product['attribute_set_id'],
          ];
        }
        foreach ($variationTypes as $variationType) {
          $drupalVariationType = $this->getProductVariationType($variationType['variation_type'], $variationType['variation_type']);
          if ($drupalVariationType->save()) {
            $drupalAttribute = $this->getProductAttribute($variationType['variation_type'], $variationType['variation_type']);
            // Adding image fields @TODO to be replaced by dynamic code.
            $this->addProductVariationImageField($drupalAttribute, 'image', 'image');
            $this->addProductVariationImageField($drupalAttribute, 'small_image', 'small_image');
            $this->addProductVariationImageField($drupalAttribute, 'thumbnail', 'thumbnail');

            if ($drupalAttribute->save()) {
              if (!in_array($drupalAttribute->id(), $this->productAttributeFieldManager->getFieldMap($drupalVariationType->id()))) {
                $this->productAttributeFieldManager->createField($drupalAttribute, $drupalVariationType->id());
              }
            }
            if (isset($variationType['attribute_id'])) {
              if (!in_array($variationType, $customVariations)) {
                $magentoAttribute = $this->magentoClient->getProductAttribute($variationType['attribute_id']);
              $options = isset($magentoAttribute['options']) ? $magentoAttribute['options'] : [];
              }
              $options = $magentoAttribute['options'] ?? [];
              $attribute_mapping[$variationType['attribute_id']] = $options;
              foreach ($options as $option) {
                if (isset($option['label']) && $option['label']) {
                  $attributeValue = $this->getProductAttributeValue($option['label'], $option['label']);
                if (isset($option['label']) && $option['value']) {
                  $attributeValue = $this->getProductAttributeValue($option['value'], $option['label']);
                  if ($attributeValue->save()) {
                    $this->addAttributeValue($drupalAttribute->id(), $attributeValue->id(), $attributeValue->getName());
                  }
                }
              }
            }
            if (empty($configurableProductLinks)) {
          }
        }
        if (empty($configurableProductLinks) && !empty($data['product_links'])) {
          $price = isset($data['price']) && $data['price']
            ? $data['price'] : 0;
          $setId = $data['attribute_set_id'];
          foreach ($variationTypes as $variation) {
            if ($variation['variation_type'] !=='default' && $variation['attribute_id'] == $setId) {
              $variationType = $variation['variation_type'];
            }
          }
          $variation = reset($this->productVariationStorage->loadByProperties([
            'sku' => $data['sku'],
          ]));
          if ($variation) {
            $variation->setPrice(new Price($price, $currencyCode));
          }
          else {
            $variation = $this->productVariationStorage->create([
                'type' => 'default',
              'type' => $variationType,
              'sku' => $sku,
              'price' => new Price((string) $price, $currencyCode),
              'title' => 'Default',
            ]);
              $customAttributes = isset($data['custom_attributes']) ? $data['custom_attributes'] : [];
          }
          $customAttributes = $data['custom_attributes'] ?? [];
          foreach ($customAttributes as $customAttribute) {
            $fieldName = 'attribute_' . $customAttribute['attribute_code'];
            if ($variation->hasField($fieldName)) {
@@ -853,24 +895,60 @@ class MagentoUtils {
            }
          }
        }
        // If the product have different variations.
        foreach ($configurableProductLinks as $configurableProductLink) {
          $magentoConfigurableProduct = $this->getMagentoProduct($configurableProductLink);
          if ($magentoConfigurableProduct) {
                $price = isset($magentoConfigurableProduct['price']) && $magentoConfigurableProduct['price']
                  ? $magentoConfigurableProduct['price'] : 0;
                $customAttributes = isset($magentoConfigurableProduct['custom_attributes'])
                ? $magentoConfigurableProduct['custom_attributes'] : [];
            $customAttributes = $magentoConfigurableProduct[0]['custom_attributes'] ?? [];
            $var = reset($this->productVariationStorage->loadByProperties(
              [
                'sku' =>
                $magentoConfigurableProduct[0]['sku'],
              ]
            ));
            if ($var) {
              $this->updateVarationData($var, $magentoConfigurableProduct, $currencyCode, $customAttributes);
            }
            else {
              $setId = $magentoConfigurableProduct[0]['attribute_set_id'];
              foreach ($variationTypes as $variation) {
                if ($variation['attribute_id'] == $setId) {
                  $drupalVariationType = $this->getProductVariationType($variation['variation_type'], $variation['variation_type']);
                  $attributesToMap = ['color', 'size'];
                  foreach ($attributesToMap as $attributeType) {
                    $this->mapFields($attributeType, $drupalVariationType);
                  }
                }
              }
              $price = isset($magentoConfigurableProduct[0]['price']) && $magentoConfigurableProduct[0]['price']
                ? $magentoConfigurableProduct[0]['price'] : 0;
              $variation = $this->productVariationStorage->create(['type' => $drupalVariationType->id()]);
                $variation->setTitle($magentoConfigurableProduct['name']);
                $variation->setSku($magentoConfigurableProduct['sku']);
              $variation->setTitle($magentoConfigurableProduct[0]['name']);
              $variation->setSku($magentoConfigurableProduct[0]['sku']);
              $variation->setPrice(new Price($price, $currencyCode));
              $imgData = [];
              foreach ($customAttributes as $customAttribute) {
                if ($customAttribute['attribute_code'] == 'image' || $customAttribute['attribute_code'] == 'small_image' || $customAttribute['attribute_code'] == 'thumbnail') {
                  $imgData[] = [
                    'attribute_code' => $customAttribute['attribute_code'],
                    'value' => $customAttribute['value'],
                  ];
                }
                // Mapping Images to the variation type.
                $fieldName = 'attribute_' . $customAttribute['attribute_code'];
                foreach ($attribute_mapping as $options) {
                  foreach ($options as $option) {
                    if ($option['value'] == $customAttribute['value']) {
                      $attribute = $this->getProductAttributeValue($option['value'], $option['label']);
                      $customAttribute['value'] = $attribute->id();
                    }
                  }
                }
                if ($variation->hasField($fieldName)) {
                  $variation->set($fieldName, $customAttribute['value']);
                }
              }
                //$variation->set('field_stock', $quantity);
              $this->mapImagesToVariations($variation, $imgData);
              if ($variation->save()) {
                $variations[] = $variation;
                if ($quantity > 0) {
@@ -880,25 +958,48 @@ class MagentoUtils {
            }
          }
        }
        }
        if (count($variations) > 0) {
          $alias = '';
          $pro = reset($this->productStorage->loadByProperties([
            'sku' => $data['sku'],
          ]));
          if ($pro) {
            $pid = $pro->id();
            $product = $this->productStorage->load($pid);
          }
          else {
            $product = $this->productStorage->create([
              'type' => $productType->id(),
              'title' => $data['name'],
              'variations' => $variations,
              'stores' => [$this->store],
              'sku' => $sku,
            ]);
          $options = isset($data['options']) ? $data['options'] : [];
          }
          $options = $data['options'] ?? [];
          foreach ($drupalProductTypeFields as $drupalProductTypeField) {
            if ($product->hasField($drupalProductTypeField['attribute_code'])) {
              $magentoAttribute = $this->magentoClient->getProductAttribute($drupalProductTypeField['attribute_code']);

              if ($magentoAttribute['frontend_input'] === 'media_image') {
                $urls = explode(',', $drupalProductTypeField['value']);
                $values = [];
                foreach ($urls as $url) {
                  $url = str_replace("_1", "", $url);
                  $baseUrl = $this->config->get('magento_url');
                  $imgUri = $baseUrl . '/media/catalog/product/' . $url;
                  $uri = file_build_uri('products' . $url);
                  $path = explode('//', $uri);
                  $pathOccurance = strripos($path[1], '/');
                  $fullPath = str_split($path[1], $pathOccurance);
                  $dir = 'sites/default/files/' . $fullPath[0];
                  if (!file_exists($dir)) {
                    mkdir($dir, 0777, TRUE);
                  }
                  $file_path = $dir . substr($path[1], $pathOccurance);
                  copy($imgUri, $file_path);
                  $file = File::Create(['uri' => $uri]);
                  $file->setPermanent();
                  if ($file->save()) {
                    $values[] = [
                      'target_id' => $file->id(),
@@ -946,8 +1047,7 @@ class MagentoUtils {
                }
              }
              elseif ($mediaGalleryEntry['media_type'] === 'external-video') {
                $url = isset($mediaGalleryEntry['extension_attributes']['video_content']['video_url']) ?
                  $mediaGalleryEntry['extension_attributes']['video_content']['video_url'] : '';
                $url = $mediaGalleryEntry['extension_attributes']['video_content']['video_url'] ?? '';
                if (!empty($url)) {
                  $product->field_video_embed->appendItem(stripcslashes($url));
                }
@@ -974,5 +1074,88 @@ class MagentoUtils {
    }
    return $id;
  }
  /**
   * Function to add image field in product variation.
   */
  public function addProductVariationImageField($variation, $name, $label) {
    $fields = \Drupal::service('entity_field.manager')->getFieldDefinitions('commerce_product_variation', $variation->id());    if (!isset($fields[$name])) {
      $configurable_field_manager = \Drupal::service('commerce.configurable_field_manager');
      $field_definition = BundleFieldDefinition::create('image')
        ->setTargetEntityTypeId('commerce_product_variation')
        ->setTargetBundle($variation->id())
        ->setName($name)
        ->setLabel($label)
        // @todo See if it is possible to get this from API.
        ->setCardinality(1)
        ->setRequired('required')
        ->setTranslatable(TRUE)
        ->setDefaultValue(NULL)
        ->setDisplayOptions('form', ['weight' => 4])
        ->setDisplayOptions('view', ['weight' => 3]);
      $configurable_field_manager->createField($field_definition, FALSE);
    }
  }
    /**
   * Function to update variation data.
   */
  public function updateVarationData($variation, $variationData, $currencyCode, $customAttributes) {
    $price = isset($variationData[0]['price']) && $variationData[0]['price']
      ? $variationData[0]['price'] : 0;
    $variation->setTitle($variationData[0]['name']);
    $variation->setPrice(new Price($price, $currencyCode));

    // @todo check if image name already exists & if exists skip the request.
    // $fid=$variation->get('small_image')->getValue()->first();exit;
    // $this->entityTypeManager->getStorage('file')->load($fid);
    $imgData = [];
    foreach ($customAttributes as $customAttribute) {
      if ($customAttribute['attribute_code'] == 'image' || $customAttribute['attribute_code'] == 'small_image' || $customAttribute['attribute_code'] == 'thumbnail') {
        $imgData[] = [
          'attribute_code' => $customAttribute['attribute_code'],
          'value' => $customAttribute['value'],
        ];
      }
    }
    $this->mapImagesToVariations($variation, $imgData);
    return $variation;
  }

  /**
   * Function to map color and size to variation types.
   */
  public function mapFields($attributeType, $drupalVariationType) {
    $drupalAttribute = $this->getProductAttribute($attributeType, $attributeType);
    $this->productAttributeFieldManager->createField($drupalAttribute, $drupalVariationType->id());
  }
/**
   * Map images to variations type.
   */
  public function mapImagesToVariations($variation, $imgData) {
    foreach ($imgData as $img) {
      $url = str_replace("_1", "", $img['value']);
      $baseUrl = $this->config->get('magento_url');
      $imgUri = $baseUrl . '/media/catalog/product/' . $url;
      $uri = file_build_uri('products' . $url);
      $path = explode('//', $uri);
      $pathOccurance = strripos($path[1], '/');
      $fullPath = str_split($path[1], $pathOccurance);
      $dir = 'sites/default/files/' . $fullPath[0];
      if (!file_exists($dir)) {
        mkdir($dir, 0777, TRUE);
      }
      $file_path = $dir . substr($path[1], $pathOccurance);
      copy($imgUri, $file_path);
      $file = File::Create(['uri' => $uri]);
      $file->setPermanent();
      if ($file->save()) {
        $values[] = [
          'target_id' => $file->id(),
          'alt' => $img['attribute_code'],
          'title' => $img['attribute_code'],
        ];
      }
      $variation->set($img['attribute_code'], $values);
      $variation->save();
    }
  }
}