arch-8.x-1.x-dev/modules/product/modules/downloadable/arch_downloadable_product.module
modules/product/modules/downloadable/arch_downloadable_product.module
<?php /** * @file * Downloadable product. */ use Drupal\arch_product\Entity\ProductTypeInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; /** * Implements hook_form_alter(). */ function arch_downloadable_product_form_alter(&$form, FormStateInterface $form_state, $form_id) { if (!in_array($form_id, ['product_type_add_form', 'product_type_edit_form'])) { return; } /** @var \Drupal\arch_product\Form\ProductTypeForm $form_object */ $form_object = $form_state->getFormObject(); /** @var \Drupal\arch_product\Entity\ProductType $product_type */ $product_type = $form_object->getEntity(); $form['downloadable'] = [ '#type' => 'details', '#title' => t('Downloadable', [], ['context' => 'arch_downloadable_product']), '#group' => 'product_type_features', '#weight' => -90, ]; $form['downloadable']['is_downloadable'] = [ '#type' => 'checkbox', '#title' => t('Downloadable product', [], ['context' => 'arch_downloadable_product']), '#default_value' => $product_type->getThirdPartySetting('arch_downloadable_product', 'is_downloadable'), ]; if (_arch_downloadable_product_type_has_file_data($product_type)) { $form['downloadable']['is_downloadable']['#disabled'] = TRUE; $form['downloadable']['is_downloadable']['#description'] = t('There are products with files in this type.', [], ['context' => 'arch_stock']); } $form['#entity_builders'][] = 'arch_downloadable_product_form_product_type_form_builder'; } /** * Check if there is any product with files with given type. * * @param \Drupal\arch_product\Entity\ProductTypeInterface $product_type * Product type. * * @return bool * Return TRUE if any. */ function _arch_downloadable_product_type_has_file_data(ProductTypeInterface $product_type) { /** @var \Drupal\field\Entity\FieldConfig $file_field */ $file_field = FieldConfig::load('product.' . $product_type->id() . '.product_file'); if (empty($file_field)) { return FALSE; } $db = \Drupal::database(); $select = $db->select('product__product_file', 'f'); $select->condition('bundle', $product_type->id()); $count = (int) $select->countQuery()->execute()->fetchField(); return $count > 0; } /** * Entity builder for downloadable product type options. * * @see arch_downloadable_product_form_alter() */ function arch_downloadable_product_form_product_type_form_builder($entity_type, ProductTypeInterface $type, &$form, FormStateInterface $form_state) { if ($form_state->getValue('is_downloadable')) { $type->setThirdPartySetting('arch_downloadable_product', 'is_downloadable', TRUE); } else { $type->unsetThirdPartySetting('arch_downloadable_product', 'is_downloadable'); } } /** * Implements hook_entity_insert(). */ function arch_downloadable_product_entity_insert(EntityInterface $entity) { if (\Drupal::isConfigSyncing()) { // Do not change data while config import in progress. return; } if ($entity->getEntityTypeId() == 'product_type') { /** @var \Drupal\arch_product\Entity\ProductTypeInterface $entity */ if ($entity->getThirdPartySetting('arch_downloadable_product', 'is_downloadable')) { _arch_downloadable_product_add_file_field($entity); } } } /** * Implements hook_entity_update(). */ function arch_downloadable_product_entity_update(EntityInterface $entity) { if (\Drupal::isConfigSyncing()) { // Do not change data while config import in progress. return; } if ($entity->getEntityTypeId() == 'product_type') { /** @var \Drupal\arch_product\Entity\ProductTypeInterface $entity */ if ($entity->getThirdPartySetting('arch_downloadable_product', 'is_downloadable')) { _arch_downloadable_product_add_file_field($entity); } else { _arch_downloadable_product_remove_file_field($entity); } } elseif ($entity->getEntityTypeId() == 'order') { /** @var \Drupal\arch_order\Entity\OrderInterface $entity */ _arch_stock_handle_stock_change_on_order_update($entity); } } /** * Add file field to product type. * * @param \Drupal\arch_product\Entity\ProductTypeInterface $product_type * Product type. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException * @throws \Drupal\Core\Entity\EntityStorageException */ function _arch_downloadable_product_add_file_field(ProductTypeInterface $product_type) { $definition = [ 'name' => 'product_file', 'form_display' => [ 'type' => 'file_generic', ], 'display' => [ 'default' => [ 'type' => 'arch_downloadable_product', ], ], ]; // Add or remove the description field, as needed. $field_storage = FieldStorageConfig::loadByName('product', $definition['name']); if (!$field_storage) { $field_storage = FieldStorageConfig::create([ 'status' => TRUE, 'dependencies' => [ 'module' => [ 'arch_product', 'file', ], ], 'id' => 'product.product_file', 'field_name' => 'product_file', 'entity_type' => 'product', 'type' => 'file', 'settings' => [ 'display_field' => FALSE, 'display_default' => FALSE, 'uri_scheme' => 'private', 'target_type' => 'file', ], 'module' => 'file', 'locked' => FALSE, 'cardinality' => -1, 'translatable' => FALSE, ]); $field_storage->save(); } $field = FieldConfig::loadByName('product', $product_type->id(), $definition['name']); if (empty($field)) { $field = FieldConfig::create([ 'label' => 'File', 'field_storage' => $field_storage, 'bundle' => $product_type->id(), ]); $field->save(); $entity_form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display') ->load('product.' . $product_type->id() . '.default'); if (empty($entity_form_display)) { $entity_form_display = EntityFormDisplay::create([ 'targetEntityType' => 'product', 'bundle' => $product_type->id(), 'mode' => 'default', 'status' => TRUE, ]); } // Assign widget settings for the 'default' form mode. $entity_form_display ->setComponent($definition['name'], $definition['form_display']) ->save(); // The teaser view mode is created by the Standard profile and therefore // might not exist. $view_modes = \Drupal::service('entity_display.repository')->getViewModes('product'); // Assign display settings for the 'default' and 'teaser' view modes. foreach ($definition['display'] as $view_mode => $config) { if (isset($view_modes[$view_mode]) || 'default' == $view_mode) { $entity_display = \Drupal::entityTypeManager()->getStorage('entity_view_display') ->load('product.' . $product_type->id() . '.' . $view_mode); if (!$entity_display) { $entity_display = EntityViewDisplay::create([ 'targetEntityType' => 'product', 'bundle' => $product_type->id(), 'mode' => $view_mode, 'status' => TRUE, ]); } $entity_display ->setComponent($definition['name'], $definition['display'][$view_mode]) ->save(); } } } } /** * Remove file field from product type. * * @param \Drupal\arch_product\Entity\ProductTypeInterface $product_type * Product type. * * @throws \Drupal\Core\Entity\EntityStorageException */ function _arch_downloadable_product_remove_file_field(ProductTypeInterface $product_type) { $field = FieldConfig::loadByName('product', $product_type->id(), 'product_file'); if ($field) { $field->delete(); } } /** * Implements hook_form_FORM_ID_alter(). */ function arch_downloadable_product_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) { $form['actions']['delete']['#access'] = FALSE; }