acquia_commercemanager-8.x-1.122/modules/acm_sku/src/Entity/SKU.php

modules/acm_sku/src/Entity/SKU.php
<?php

namespace Drupal\acm_sku\Entity;

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\file\Entity\File;
use Drupal\file\FileInterface;
use Drupal\user\UserInterface;
use GuzzleHttp\Exception\RequestException;

/**
 * Defines the SKU entity.
 *
 * @ContentEntityType(
 *   id = "acm_sku",
 *   label = @Translation("SKU entity"),
 *   handlers = {
 *     "view_builder" = "Drupal\acm_sku\Entity\Controller\SKUViewBuilder",
 *     "list_builder" = "Drupal\acm_sku\Entity\Controller\SKUListBuilder",
 *     "views_data" = "Drupal\views\EntityViewsData",
 *     "form" = {
 *       "default" = "Drupal\acm_sku\Form\SKUForm",
 *       "add" = "Drupal\acm_sku\Form\SKUForm",
 *       "edit" = "Drupal\acm_sku\Form\SKUForm",
 *       "delete" = "Drupal\acm_sku\Form\SKUDeleteForm",
 *     },
 *     "access" = "Drupal\acm_sku\SKUAccessControlHandler",
 *     "storage_schema" = "Drupal\acm_sku\SKUStorageSchema",
 *   },
 *   base_table = "acm_sku",
 *   data_table = "acm_sku_field_data",
 *   translatable = TRUE,
 *   common_reference_target = TRUE,
 *   admin_permission = "administer commerce sku entity",
 *   fieldable = TRUE,
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "name",
 *     "bundle" = "type",
 *     "langcode" = "langcode",
 *     "uuid" = "uuid",
 *     "bundle" = "type",
 *     "status" = "status",
 *   },
 *   bundle_entity_type = "acm_sku_type",
 *   bundle_label = @Translation("SKU type"),
 *   links = {
 *     "canonical" = "/admin/commerce/sku/{acm_sku}",
 *     "edit-form" = "/admin/commerce/sku/{acm_sku}/edit",
 *     "delete-form" = "/admin/commerce/sku/{acm_sku}/delete",
 *     "collection" = "/admin/commerce/sku/list"
 *   },
 *   field_ui_base_route = "acm_sku.configuration",
 * )
 */
class SKU extends ContentEntityBase implements SKUInterface {

  /**
   * Processed media array.
   *
   * @var array
   */
  protected $mediaData = [];

  /**
   * {@inheritdoc}
   *
   * When a new entity instance is added, set the user_id entity reference to
   * the current user as the creator of the instance.
   */
  public static function preCreate(EntityStorageInterface $storage_controller, array &$values) {
    parent::preCreate($storage_controller, $values);
    $values += [
      'user_id' => \Drupal::currentUser()->id(),
    ];
  }

  /**
   * Loads a SKU Entity from SKU.
   *
   * @param string $sku
   *   SKU to load.
   * @param string $langcode
   *   Language code.
   * @param bool $log_not_found
   *   Log errors when store not found. Can be false during sync.
   * @param bool $create_translation
   *   Create translation and return if entity available but translation is not.
   *
   * @return SKU|null
   *   Found SKU
   *
   * @throws \Exception
   */
  public static function loadFromSku($sku, $langcode = '', $log_not_found = TRUE, $create_translation = FALSE) {

    $skus_static_cache = &drupal_static(__FUNCTION__, []);

    $is_multilingual = \Drupal::languageManager()->isMultilingual();
    if ($is_multilingual && empty($langcode)) {
      $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
    }

    $static_cache_sku_identifier = $sku . ':' . $langcode;

    // Check if data is available in static cache, return from there.
    // If create translation is true, it means we are doing product sync.
    // For this case we don't want to use any static cache.
    if (isset($skus_static_cache[$static_cache_sku_identifier]) && !$create_translation) {
      return $skus_static_cache[$static_cache_sku_identifier];
    }

    $storage = \Drupal::entityTypeManager()->getStorage('acm_sku');
    $skus = $storage->loadByProperties(['sku' => $sku]);

    if (count($skus) == 0) {
      // We don't log the error while doing sync.
      if ($log_not_found) {
        \Drupal::logger('acm_sku')->error('No SKU found for @sku.', ['@sku' => $sku]);
      }
      return NULL;
    }

    $sku_entity = reset($skus);

    // Sanity check.
    if (!($sku_entity instanceof SKUInterface)) {
      return NULL;
    }

    // Now discard all skus in other languages if there is more than one.
    if ($is_multilingual && count($skus) > 1) {
      // Get rid of undesired languages. Later the first sku is picked up.
      foreach ($skus as $key => $skuEntity) {
        if ($skuEntity->language()->getId() != $langcode) {
          unset($skus[$key]);
        }
      }
    }

    // Now test if there is still more than one sku found.
    // Noting for multiple entries, we just log the error
    // and continue with first sku.
    if (count($skus) > 1) {
      \Drupal::logger('acm_sku')->error('Duplicate SKUs found while loading for @sku.', ['@sku' => $sku]);
    }

    if ($is_multilingual) {
      if ($sku_entity->hasTranslation($langcode)) {
        $sku_entity = $sku_entity->getTranslation($langcode);

        // Set value in static variable.
        // We set in static cache only for proper case, when returning different
        // language or creating translation we can avoid static cache.
        $skus_static_cache[$static_cache_sku_identifier] = $sku_entity;
      }
      elseif ($create_translation) {
        $sku_entity = $sku_entity->addTranslation($langcode, ['sku' => $sku]);
      }
      // We will continue execution with available translation and just log
      // a message. During sync we say don't log messages.
      elseif ($log_not_found) {
        \Drupal::logger('acm_sku')->error('SKU translation not found of @sku for @langcode', ['@sku' => $sku, '@langcode' => $langcode]);
      }
    }
    else {
      // Set value in static variable directly if not a multi-lingual site.
      $skus_static_cache[$static_cache_sku_identifier] = $sku_entity;
    }

    return $sku_entity;
  }

  /**
   * {@inheritdoc}
   */
  public function getCreatedTime() {
    return $this->get('created')->value;
  }

  /**
   * {@inheritdoc}
   */
  public function getChangedTime() {
    return $this->get('changed')->value;
  }

  /**
   * {@inheritdoc}
   */
  public function setChangedTime($timestamp) {
    $this->set('changed', $timestamp);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getChangedTimeAcrossTranslations() {
    $changed = $this->getUntranslated()->getChangedTime();
    foreach ($this->getTranslationLanguages(FALSE) as $language) {
      $translation_changed = $this->getTranslation($language->getId())->getChangedTime();
      $changed = max($translation_changed, $changed);
    }
    return $changed;
  }

  /**
   * {@inheritdoc}
   */
  public function getOwner() {
    return $this->get('user_id')->entity;
  }

  /**
   * {@inheritdoc}
   */
  public function getOwnerId() {
    return $this->get('user_id')->target_id;
  }

  /**
   * Get all the cross sell sku values of current entity.
   */
  public function getCrossSell() {
    return $this->get('crosssell')->getValue();
  }

  /**
   * Get all the upsell sku values of current entity.
   */
  public function getUpSell() {
    return $this->get('upsell')->getValue();
  }

  /**
   * {@inheritdoc}
   */
  public function setOwnerId($uid) {
    $this->set('user_id', $uid);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setOwner(UserInterface $account) {
    $this->set('user_id', $account->id());
    return $this;
  }

  /**
   * {@inheritdoc}
   *
   * Define the field properties here.
   *
   * Field name, type and size determine the table structure.
   *
   * In addition, we can define how the field and its content can be manipulated
   * in the GUI. The behaviour of the widgets used can be determined here.
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);

    $fields['name'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Name'))
      ->setDescription(t("The SKU's human-friendly name."))
      ->setTranslatable(TRUE)
      ->setSettings([
        'default_value' => '',
        'max_length' => 255,
        'text_processing' => 0,
      ])
      ->setDisplayOptions('view', [
        'label' => 'hidden',
        'type' => 'string',
        'weight' => -10,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -10,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['sku'] = BaseFieldDefinition::create('string')
      ->setLabel(t('SKU'))
      ->setDescription(t('The SKU.'))
      ->setTranslatable(TRUE)
      ->setRequired(TRUE)
      ->setSettings([
        'default_value' => '',
        'max_length' => 255,
        'text_processing' => 0,
      ])
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -11,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -11,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['price'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Display Price'))
      ->setDescription(t('Display Price of this SKU.'))
      ->setTranslatable(FALSE)
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -6,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -6,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['special_price'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Special Price'))
      ->setDescription(t('Special Price of this SKU.'))
      ->setTranslatable(FALSE)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['final_price'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Final Price'))
      ->setDescription(t('Final Price of this SKU.'))
      ->setTranslatable(FALSE)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['crosssell'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Cross sell SKU'))
      ->setDescription(t('Reference to all Cross sell SKUs.'))
      ->setTranslatable(TRUE)
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => 5,
      ])
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('form', TRUE);

    $fields['upsell'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Up sell SKU'))
      ->setDescription(t('Reference to all up sell SKUs.'))
      ->setTranslatable(TRUE)
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => 6,
      ])
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('form', TRUE);

    $fields['related'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Related SKU'))
      ->setDescription(t('Reference to all related SKUs.'))
      ->setTranslatable(TRUE)
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => 7,
      ])
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('form', TRUE);

    $fields['image'] = BaseFieldDefinition::create('image')
      ->setLabel(t('Image'))
      ->setDescription(t('Product image'))
      ->setTranslatable(TRUE)
      ->setDisplayOptions('view', [
        'label' => 'hidden',
        'type' => 'image',
        'weight' => -11,
      ])
      ->setDisplayOptions('form', [
        'type' => 'image_image',
        'weight' => -9,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['media'] = BaseFieldDefinition::create('text_long')
      ->setLabel(t('Media'))
      ->setDescription(t('Store all the media files info.'))
      ->setTranslatable(TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['attributes'] = BaseFieldDefinition::create('key_value_long')
      ->setLabel(t('Attributes'))
      ->setDescription(t('Non-Drupal native product data.'))
      ->setTranslatable(TRUE)
      ->setCardinality(-1)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['created'] = BaseFieldDefinition::create('created')
      ->setLabel(t('Created'))
      ->setDescription(t('The time that the entity was created.'))
      ->setTranslatable(TRUE);

    $fields['changed'] = BaseFieldDefinition::create('changed')
      ->setLabel(t('Changed'))
      ->setDescription(t('The time that the entity was last edited.'))
      ->setTranslatable(TRUE);

    $fields['attribute_set'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Attribute Set'))
      ->setDescription(t('Attribtue set for the SKU.'))
      ->setTranslatable(TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['status'] = BaseFieldDefinition::create('boolean')
      ->setLabel(t('Status'))
      ->setDescription(t('Whether the SKU is available or not.'))
      ->setDefaultValue(TRUE);

    $fields['product_id'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Product Id'))
      ->setDescription(t('Commerce Backend Product Id.'))
      ->setTranslatable(TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    // Get all the fields added by other modules and add them as base fields.
    $additionalFields = \Drupal::service('acm_sku.fields_manager')->getFieldAdditions();

    // Get the default weight increment value from variables.
    $defaultWeightIncrement = \Drupal::state()
      ->get('acm_sku.base_field_weight_increment', 20);

    // Check if we have additional fields to be added as base fields.
    if (!empty($additionalFields) && is_array($additionalFields)) {
      foreach ($additionalFields as $machine_name => $field_info) {
        // Initialise the field variable.
        $field = NULL;

        // Showing the fields at the bottom.
        $weight = $defaultWeightIncrement + count($fields);

        switch ($field_info['type']) {
          case 'attribute':
          case 'string':
            $field = BaseFieldDefinition::create('string');

            if ($field_info['visible_view']) {
              $field->setDisplayOptions('view', [
                'label' => 'above',
                'type' => 'string',
                'weight' => $weight,
              ]);
            }

            if ($field_info['visible_form']) {
              $field->setDisplayOptions('form', [
                'type' => 'string_textfield',
                'weight' => $weight,
              ]);
            }
            break;

          case 'text_long':
            $field = BaseFieldDefinition::create('text_long');

            if ($field_info['visible_view']) {
              $field->setDisplayOptions('view', [
                'label' => 'hidden',
                'type' => 'text_default',
                'weight' => $weight,
              ]);
            }

            if ($field_info['visible_form']) {
              $field->setDisplayOptions('form', [
                'type' => 'text_textfield',
                'weight' => $weight,
              ]);
            }
            break;
        }

        // Check if we don't have the field type defined yet.
        if (empty($field)) {
          throw new \RuntimeException('Field type not defined yet, please contact TA.');
        }

        // We want to allow field labels to be translatable.
        // Since we try to do this dynamically, we need to use t() with
        // variable.
        // @codingStandardsIgnoreLine
        $field->setLabel(new TranslatableMarkup($field_info['label']));

        // Update cardinality with default value if empty.
        $field_info['description'] = empty($field_info['description']) ? 1 : $field_info['description'];
        $field->setDescription($field_info['description']);

        $field->setTranslatable(TRUE);

        // Update cardinality with default value if empty.
        $field_info['cardinality'] = empty($field_info['cardinality']) ? 1 : $field_info['cardinality'];
        $field->setCardinality($field_info['cardinality']);

        $field->setDisplayConfigurable('form', 1);
        $field->setDisplayConfigurable('view', 1);

        // We will use attr prefix to avoid conflicts with default base fields.
        $fields['attr_' . $machine_name] = $field;
      }
    }

    return $fields;
  }

  /**
   * {@inheritdoc}
   */
  public function getType() {
    return $this->bundle();
  }

  /**
   * {@inheritdoc}
   */
  public function getSku() {
    return $this->get('sku')->value;
  }

  /**
   * Returns the locale-aware display formatted price like this '$1,234.56'.
   *
   * Calls the price formatting function of the SKU Type.
   */
  public function getAdminGridDisplayFormattedPrice(bool $returnOriginalPrice = FALSE) {
    $skuTypePlugin = $this->getPluginInstance();
    if ($skuTypePlugin === NULL) {
      /** @var \Drupal\acm_sku\AcquiaCommerce\SKUPluginManager $plugin_manager */
      $plugin_manager = \Drupal::service('plugin.manager.sku');
      $skuTypePlugin = $plugin_manager->pluginInstanceFromType('simple');
    }
    // Use the type plugin's price formatter.
    $formattedPrice = $skuTypePlugin->getAdminGridDisplayFormattedPrice($this, $returnOriginalPrice);

    return $formattedPrice;
  }

  /**
   * Returns the locale-aware display formatted price like this '$1,234.56'.
   *
   * Calls the price formatting function of the SKU Type.
   */
  public function getNumberFormattedPrice(bool $returnOriginalPrice = FALSE) {
    $skuTypePlugin = $this->getPluginInstance();
    if ($skuTypePlugin === NULL) {
      /** @var \Drupal\acm_sku\AcquiaCommerce\SKUPluginManager $plugin_manager */
      $plugin_manager = \Drupal::service('plugin.manager.sku');
      $skuTypePlugin = $plugin_manager->pluginInstanceFromType('simple');
    }
    // Use the type plugin's price formatter.
    $formattedPrice = $skuTypePlugin->getNumberFormattedPrice($this, $returnOriginalPrice);

    return $formattedPrice;
  }

  /**
   * {@inheritdoc}
   */
  public function getPluginInstance() {
    $plugin_manager = \Drupal::service('plugin.manager.sku');
    $plugin_definition = $plugin_manager->pluginFromSku($this);

    if (empty($plugin_definition)) {
      return NULL;
    }

    return $plugin_manager->createInstance($plugin_definition['id']);
  }

  /**
   * Function to return first image from media files for a SKU.
   *
   * @return array
   *   Array of media files.
   */
  public function getThumbnail() {
    $media = $this->getMedia();

    // We loop through all the media items and return the first image.
    foreach ($media as $media_item) {
      if (isset($media_item['media_type']) && $media_item['media_type'] == 'image') {
        return $media_item;
      }
    }

    return [];
  }

  /**
   * Function to return media files for a SKU.
   *
   * @param bool $download_media
   *   Whether to download media or not.
   * @param bool $reset
   *   Flag to reset cache and generate array again from serialized string.
   *
   * @return array
   *   Array of media files.
   */
  public function getMedia($download_media = TRUE, $reset = FALSE) {
    if (!$reset && !empty($this->mediaData)) {
      return $this->mediaData;
    }

    if ($media_data = $this->get('media')->getString()) {
      $update_sku = FALSE;

      $media_data = unserialize($media_data);

      if (empty($media_data)) {
        return [];
      }

      foreach ($media_data as &$data) {
        // We don't want to show disabled images.
        if (isset($data['disabled']) && $data['disabled']) {
          continue;
        }

        $media_item = $this->processMediaItem($update_sku, $data, $download_media);

        $this->mediaData[] = $media_item;
      }

      if ($update_sku) {
        $this->get('media')->setValue(serialize($media_data));
        $this->save();
      }
    }

    return $this->mediaData;
  }

  /**
   * Function to get processed media item with File entity in array.
   *
   * @param bool $update_sku
   *   Flag to specify if SKU should be updated or not.
   *   Update is done in parent function, here we only update the flag.
   * @param array $data
   *   Media item array.
   * @param bool $download
   *   Flag to specify if we should download missing images or not.
   *
   * @return array|null
   *   Processed media item or null if some error occurred.
   */
  protected function processMediaItem(&$update_sku, array &$data, $download = FALSE) {
    $media_item = $data;

    // Processing is required only for media type image as of now.
    if (isset($data['media_type']) && $data['media_type'] == 'image') {
      if (!empty($data['fid'])) {
        $file = File::load($data['fid']);
        if (!($file instanceof FileInterface)) {
          \Drupal::logger('acm_sku')->error('Empty file object for fid @fid on sku "@sku"', [
            '@fid' => $data['fid'],
            '@sku' => $this->getSku(),
          ]);

          unset($data['fid']);

          // Try to download again if download flag is set to true.
          if ($download) {
            return $this->processMediaItem($update_sku, $data, TRUE);
          }
        }
      }
      elseif ($download) {
        try {
          // Prepare the File object when we access it the first time.
          $file = $this->downloadMediaImage($data);
          $update_sku = TRUE;
        }
        catch (\Exception $e) {
          \Drupal::logger('acm_sku')->error($e->getMessage());
          return NULL;
        }
      }

      if ($file instanceof FileInterface) {
        $data['fid'] = $file->id();
        $media_item['fid'] = $data['fid'];
        $media_item['file'] = $file;
      }

      if (empty($data['label'])) {
        $media_item['label'] = $this->label();
      }

      return $media_item;
    }
  }

  /**
   * Function to save image file into public dir.
   *
   * @param array $data
   *   File data.
   *
   * @return \Drupal\file\Entity\File
   *   File object.
   *
   * @throws \Exception
   *   If media fails to be downloaded.
   */
  protected function downloadMediaImage(array $data) {
    // Preparing args for all info/error messages.
    $args = ['@file' => $data['file'], '@sku_id' => $this->id()];

    // Download the file contents.
    try {
      $file_data = \Drupal::httpClient()->get($data['file'])->getBody();
    }
    catch (RequestException $e) {
      watchdog_exception('acq_commerce', $e);
    }
    // Check to ensure empty file is not saved in SKU.
    if (empty($file_data)) {
      throw new \Exception(new FormattableMarkup('Failed to download file "@file" for SKU id @sku_id.', $args));
    }

    // Get the path part in the url, remove hostname.
    $path = parse_url($data['file'], PHP_URL_PATH);

    // Remove slashes from start and end.
    $path = trim($path, '/');

    // Get the file name.
    $file_name = basename($path);

    // Prepare the directory path.
    $directory = 'public://media/' . str_replace('/' . $file_name, '', $path);

    // Prepare the directory.
    file_prepare_directory($directory, FILE_CREATE_DIRECTORY);

    // Save the file as file entity.
    /** @var \Drupal\file\Entity\File $file */
    if ($file = file_save_data($file_data, $directory . '/' . $file_name, FILE_EXISTS_REPLACE)) {
      \Drupal::logger('acm_sku')
        ->debug('File @url downloaded to @file for SKU @sku',
          [
            '@url' => $data['file'],
            '@file' => $file->id(),
            '@sku' => $this->id(),
          ]);
      return $file;
    }
    else {
      throw new \Exception(new FormattableMarkup('Failed to save file "@file" for SKU id @sku_id.', $args));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function refreshStock() {
    /** @var \Drupal\acm_sku\AcquiaCommerce\SKUPluginBase $plugin */
    $plugin = $this->getPluginInstance();
    $plugin->refreshStock($this);
  }

  /**
   * {@inheritdoc}
   */
  public static function postDelete(EntityStorageInterface $storage, array $entities) {
    parent::postDelete($storage, $entities);

    // Delete media files.
    foreach ($entities as $entity) {
      foreach ($entity->getMedia(FALSE) as $media) {
        if ($media['file'] instanceof FileInterface) {
          $media['file']->delete();
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheTags() {
    $cache_tags = parent::getCacheTags();
    /** @var \Drupal\acm_sku\AcquiaCommerce\SKUPluginBase $plugin */
    $plugin = $this->getPluginInstance();
    // Get parent skus(if any) for the sku.
    $parent_skus = array_values($plugin->getAllParentSkus($this->getSku()));
    // Prepare cache tags of parent sku.
    $parent_skus = array_map(function ($parent_sku) {
      return 'acm_sku:' . $parent_sku;
    }, $parent_skus);

    // @Todo: Add the tags of the display node as well.
    return Cache::mergeTags($cache_tags, $parent_skus);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc