Commit 0aac2f74 authored by bbujisic's avatar bbujisic Committed by bojanz

Issue #2506163 by Branislav Bujisic: Initial product architecture

parent 69825b03
......@@ -7,11 +7,13 @@ dependencies:
- commerce
- commerce_price
- commerce_store
- inline_entity_form
- text
config_devel:
- commerce_product.commerce_product_type.product
- field.field.commerce_product.product.commerce_price
- commerce_product.commerce_product_type.default
- commerce_product.commerce_product_variation_type.default
- field.storage.commerce_product.body
- field.storage.commerce_product.variations
- field.field.commerce_product.default.body
- field.field.commerce_product.default.variations
- views.view.commerce_products
- core.entity_form_display.commerce_product.product.default
- field.storage.commerce_product.commerce_price
- core.entity_view_display.commerce_product.product.default
\ No newline at end of file
entity.commerce_product.add_page:
route_name: entity.commerce_product.add_page
title: 'Add a new product'
title: 'Add product'
appears_on:
- entity.commerce_product.collection
entity.commerce_product_type.add_form:
route_name: entity.commerce_product_type.add_form
title: 'Add a new product type'
title: 'Add product type'
appears_on:
- entity.commerce_product_type.collection
entity.commerce_product_variation_type.add_form:
route_name: entity.commerce_product_variation_type.add_form
title: 'Add product variation type'
appears_on:
- entity.commerce_product_variation_type.collection
......@@ -9,3 +9,9 @@ entity.commerce_product_type.collection:
route_name: 'entity.commerce_product_type.collection'
parent: 'commerce.configuration'
description: 'Manage your product types.'
entity.commerce_product_variation_type.collection:
title: 'Product variation types'
route_name: 'entity.commerce_product_variation_type.collection'
parent: 'commerce.configuration'
description: 'Manage your product variation types.'
......@@ -12,3 +12,8 @@ entity.commerce_product_type.edit_form:
route_name: entity.commerce_product_type.edit_form
base_route: entity.commerce_product_type.edit_form
title: Edit
entity.commerce_product_variation_type.edit_form:
route_name: entity.commerce_product_variation_type.edit_form
base_route: entity.commerce_product_variation_type.edit_form
title: Edit
......@@ -2,9 +2,7 @@
/**
* @file
* Defines the core Commerce product entity, including the entity itself, the
* bundle definitions (product types), and various API functions to manage
* products and interact with them through forms and autocompletes.
* Defines the Product entity and associated features.
*/
use Drupal\field\Entity\FieldConfig;
......@@ -14,18 +12,14 @@ use Drupal\Core\Form\FormStateInterface;
/**
* Adds the default body field to a product type.
*
* @param string $product_type_id
* Id of the Commerce Product type.
* @param \Drupal\commerce_product\ProductTypeInterface $product_type
* The product type.
* @param string $label
* (optional) The label for the body instance. Defaults to 'Body'.
*
* @return array
* Body field instance.
*/
function commerce_product_add_body_field($product_type_id, $label = 'Body') {
// Add or remove the body field, as needed.
function commerce_product_add_body_field($product_type, $label = 'Body') {
$field_storage = FieldStorageConfig::loadByName('commerce_product', 'body');
$instance = FieldConfig::loadByName('commerce_product', $product_type_id, 'body');
$field = FieldConfig::loadByName('commerce_product', $product_type->id(), 'body');
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => 'body',
......@@ -34,33 +28,75 @@ function commerce_product_add_body_field($product_type_id, $label = 'Body') {
]);
$field_storage->save();
}
if (empty($instance)) {
$instance = FieldConfig::create([
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => $product_type_id,
'bundle' => $product_type->id(),
'label' => $label,
'settings' => ['display_summary' => FALSE],
]);
$instance->save();
$field->save();
// Assign widget settings for the 'default' form mode.
entity_get_form_display('commerce_product', $product_type_id, 'default')
entity_get_form_display('commerce_product', $product_type->id(), 'default')
->setComponent('body', [
'type' => 'text_textarea_with_summary',
'weight' => 1,
])
->save();
// Assign display settings for 'default' view mode.
entity_get_display('commerce_product', $product_type_id, 'default')
entity_get_display('commerce_product', $product_type->id(), 'default')
->setComponent('body', [
'label' => 'hidden',
'type' => 'text_default',
])
->save();
}
}
return $instance;
/**
* Adds the default variations field to a product type.
*
* Variations can't be a base field because the Views integraiton is broken.
* Instead, it is created as a configurable field for each product type.
*
* @param \Drupal\commerce_product\ProductTypeInterface $product_type
* The product type.
*/
function commerce_product_add_variations_field($product_type) {
$field_storage = FieldStorageConfig::loadByName('commerce_product', 'variations');
$field = FieldConfig::loadByName('commerce_product', $product_type->id(), 'variations');
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => 'variations',
'entity_type' => 'commerce_product',
'type' => 'entity_reference',
'cardinality' => FieldStorageConfig::CARDINALITY_UNLIMITED,
'settings' => array(
'target_type' => 'commerce_product_variation',
),
'locked' => TRUE,
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => $product_type->id(),
'label' => 'Variations',
'required' => TRUE,
'settings' => ['display_summary' => FALSE],
]);
$field->save();
// Assign widget settings for the 'default' form mode.
entity_get_form_display('commerce_product', $product_type->id(), 'default')
->setComponent('variations', [
'type' => 'inline_entity_form_multiple',
'weight' => 10,
])
->save();
}
}
/**
......@@ -68,10 +104,8 @@ function commerce_product_add_body_field($product_type_id, $label = 'Body') {
*/
function commerce_product_form_field_config_edit_form_alter(array &$form, FormStateInterface $form_state) {
$field = $form_state->getFormObject()->getEntity();
// If the current field instance is attached to a product type,
// and of a field type that defines an options list.
$allowedFields = ['options', 'taxonomy', 'entity_reference'];
if ($field->get('entity_type') == 'commerce_product' && in_array($field->get('fieldStorage')->get('module'), $allowedFields)) {
if ($field->get('entity_type') == 'commerce_product_variation' && in_array($field->get('fieldStorage')->get('module'), $allowedFields)) {
// Get the current instance's attribute settings for use as default values.
$defaultAttributeField = $field->getThirdPartySetting('commerce_product', 'attribute_field', FALSE);
$defaultAttributeWidget = $field->getThirdPartySetting('commerce_product', 'attribute_widget', 'select');
......@@ -131,7 +165,7 @@ function commerce_product_form_field_config_edit_form_alter(array &$form, FormSt
function commerce_product_form_field_config_edit_form_submit($form, FormStateInterface $form_state) {
$field = $form_state->getFormObject()->getEntity();
$allowedFields = ['options', 'taxonomy', 'entity_reference'];
if ($field->get('entity_type') == 'commerce_product' && in_array($field->get('fieldStorage')->get('module'), $allowedFields)) {
if ($field->get('entity_type') == 'commerce_product_variation' && in_array($field->get('fieldStorage')->get('module'), $allowedFields)) {
$formFields = &$form_state->getValues('field');
// If the attribute field is checked, update the attribute fields.
......
entity.commerce_product.configuration:
path: '/admin/commerce/config/product'
defaults:
_controller: '\Drupal\system\Controller\SystemController::systemAdminMenuBlockPage'
_title: 'Product configuration'
requirements:
_permission: 'access administration pages'
entity.commerce_product.add_page:
path: '/admin/commerce/products/add'
defaults:
_title: 'Add a new product'
_title: 'Add new product'
_bundle_type: commerce_product_type
_controller: '\Drupal\commerce\Controller\AddController::addPage'
options:
......@@ -60,7 +52,7 @@ entity.commerce_product.delete_form:
path: '/product/{commerce_product}/delete'
defaults:
_entity_form: commerce_product.delete
_title: 'Delete a product'
_title: 'Delete product'
options:
_admin_route: TRUE
requirements:
......@@ -70,7 +62,7 @@ entity.commerce_product_type.add_form:
path: '/admin/commerce/config/product-types/add'
defaults:
_entity_form: commerce_product_type.edit
_title: 'Add a product type'
_title: 'Add product type'
requirements:
_entity_create_access: 'commerce_product_type'
......@@ -86,7 +78,7 @@ entity.commerce_product_type.edit_form:
path: '/admin/commerce/config/product-types/{commerce_product_type}/edit'
defaults:
_entity_form: commerce_product_type.edit
_title: 'Edit a product type'
_title: 'Edit product type'
requirements:
_entity_access: 'commerce_product_type.edit'
......@@ -94,6 +86,38 @@ entity.commerce_product_type.delete_form:
path: '/admin/commerce/config/product-types/{commerce_product_type}/delete'
defaults:
_entity_form: 'commerce_product_type.delete'
_title: 'Delete a product type'
_title: 'Delete product type'
requirements:
_entity_access: 'commerce_product_type.delete'
entity.commerce_product_variation_type.add_form:
path: '/admin/commerce/config/product-variation-types/add'
defaults:
_entity_form: commerce_product_variation_type.edit
_title: 'Add product variation type'
requirements:
_entity_create_access: 'commerce_product_variation_type'
entity.commerce_product_variation_type.collection:
path: '/admin/commerce/config/product-variation-types'
defaults:
_entity_list: 'commerce_product_variation_type'
_title: 'Product variation types'
requirements:
_permission: 'administer product types'
entity.commerce_product_variation_type.edit_form:
path: '/admin/commerce/config/product-variation-types/{commerce_product_variation_type}/edit'
defaults:
_entity_form: commerce_product_variation_type.edit
_title: 'Edit product variation type'
requirements:
_entity_access: 'commerce_product_variation_type.edit'
entity.commerce_product_variation_type.delete_form:
path: '/admin/commerce/config/product-variation-types/{commerce_product_variation_type}/delete'
defaults:
_entity_form: 'commerce_product_variation_type.delete'
_title: 'Delete product variation type'
requirements:
_entity_access: 'commerce_product_variation_type.delete'
langcode: en
status: true
dependencies: { }
id: default
label: Default
digital: false
description: ''
variationType: default
langcode: en
status: true
dependencies:
config:
- commerce_product.commerce_product_type.product
id: commerce_product.product.default
targetEntityType: commerce_product
bundle: product
mode: default
content:
body:
type: text_textarea_with_summary
weight: 3
settings:
rows: 9
summary_rows: 3
placeholder: ''
third_party_settings: { }
commerce_price:
type: price_default
weight: 4
settings: { }
third_party_settings: { }
created:
type: datetime_timestamp
weight: 10
settings: { }
third_party_settings: { }
sku:
type: string_textfield
weight: 2
settings:
size: 60
placeholder: ''
third_party_settings: { }
status:
type: boolean_checkbox
weight: 5
settings:
display_label: true
third_party_settings: { }
store_id:
type: options_select
weight: 0
settings: { }
third_party_settings: { }
title:
type: string_textfield
weight: 0
settings:
size: 60
placeholder: ''
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
settings:
match_operator: CONTAINS
size: 60
placeholder: ''
third_party_settings: { }
hidden: { }
langcode: en
status: true
dependencies:
config:
- commerce_product.commerce_product_type.product
- field.field.commerce_product.product.commerce_price
module:
- commerce_price
- user
id: commerce_product.product.default
targetEntityType: commerce_product
bundle: product
mode: default
content:
commerce_price:
type: price_default
weight: 1
label: above
settings:
strip_trailing_zeroes: false
display_currency_code: false
third_party_settings: { }
sku:
label: hidden
type: string
weight: 0
settings:
link_to_entity: false
third_party_settings: { }
hidden:
store_id: true
......@@ -2,19 +2,20 @@ langcode: en
status: true
dependencies:
config:
- commerce_product.commerce_product_type.product
- field.storage.commerce_product.commerce_price
- commerce_product.commerce_product_type.default
- field.storage.commerce_product.body
module:
- commerce_price
id: commerce_product.product.commerce_price
field_name: commerce_price
- text
id: commerce_product.default.body
field_name: body
entity_type: commerce_product
bundle: product
label: Price
bundle: default
label: Body
description: ''
required: false
translatable: false
translatable: true
default_value: { }
default_value_callback: ''
settings: { }
field_type: price
settings:
display_summary: false
field_type: text_with_summary
langcode: en
status: true
dependencies:
config:
- commerce_product.commerce_product_type.default
- field.storage.commerce_product.variations
module:
- entity_reference
id: commerce_product.default.variations
field_name: variations
entity_type: commerce_product
bundle: default
label: Variations
description: ''
required: true
translatable: true
default_value: { }
default_value_callback: ''
settings:
handler: 'default:commerce_product_variation'
handler_settings: { }
field_type: entity_reference
......@@ -2,14 +2,14 @@ langcode: en
status: true
dependencies:
module:
- commerce_price
- commerce_product
id: commerce_product.commerce_price
field_name: commerce_price
- text
id: commerce_product.body
field_name: body
entity_type: commerce_product
type: price
type: text_with_summary
settings: { }
module: commerce_price
module: text
locked: false
cardinality: 1
translatable: true
......
langcode: en
status: true
dependencies:
module:
- commerce_product
- entity_reference
id: commerce_product.variations
field_name: variations
entity_type: commerce_product
type: entity_reference
settings:
target_type: commerce_product_variation
module: entity_reference
locked: true
cardinality: -1
translatable: true
indexes: { }
persist_with_no_fields: false
......@@ -14,6 +14,20 @@ commerce_product.commerce_product_type.*:
description:
type: text
label: 'Description'
variationType:
type: string
label: 'Variation type'
commerce_product.commerce_product_variation_type.*:
type: config_entity
label: 'Product variation type'
mapping:
id:
type: string
label: 'Type'
label:
type: label
label: 'Label'
field.field.*.*.*.third_party.commerce_product:
type: mapping
......
......@@ -17,7 +17,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\user\UserInterface;
/**
* Defines the Commerce Product entity.
* Defines the Product entity.
*
* @ContentEntityType(
* id = "commerce_product",
......@@ -63,16 +63,8 @@ class Product extends ContentEntityBase implements ProductInterface {
/**
* {@inheritdoc}
*/
public function getSku() {
return $this->get('sku')->value;
}
/**
* {@inheritdoc}
*/
public function setSku($sku) {
$this->set('sku', $sku);
return $this;
public function getType() {
return $this->get('type')->value;
}
/**
......@@ -127,13 +119,6 @@ class Product extends ContentEntityBase implements ProductInterface {
return $this->get('changed')->value;
}
/**
* {@inheritdoc}
*/
public function getType() {
return $this->get('type')->value;
}
/**
* {@inheritdoc}
*/
......@@ -200,7 +185,6 @@ class Product extends ContentEntityBase implements ProductInterface {
public static function baseFieldDefinitions(EntityTypeInterface $entityType) {
$fields['product_id'] = BaseFieldDefinition::create('integer')
->setLabel(t('Product ID'))
->setDescription(t('The ID of the product.'))
->setReadOnly(TRUE);
$fields['store_id'] = BaseFieldDefinition::create('entity_reference')
......@@ -221,7 +205,6 @@ class Product extends ContentEntityBase implements ProductInterface {
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Author'))
->setDescription(t('The user that created this product.'))
->setSetting('target_type', 'user')
->setSetting('handler', 'default')
->setDefaultValueCallback('Drupal\commerce_product\Entity\Product::getCurrentUserId')
......@@ -245,16 +228,13 @@ class Product extends ContentEntityBase implements ProductInterface {
$fields['uuid'] = BaseFieldDefinition::create('uuid')
->setLabel(t('UUID'))
->setDescription(t('The UUID of the product.'))
->setReadOnly(TRUE);
$fields['langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Language code'))
->setDescription(t('The language code of product.'));
->setLabel(t('Language code'));
$fields['title'] = BaseFieldDefinition::create('string')
->setLabel(t('Title'))
->setDescription(t('The title of this node, always treated as non-markup plain text.'))
->setRequired(TRUE)
->setTranslatable(TRUE)
->setSettings([
......@@ -272,32 +252,12 @@ class Product extends ContentEntityBase implements ProductInterface {
])
->setDisplayConfigurable('form', TRUE);
$fields['sku'] = BaseFieldDefinition::create('string')
->setLabel(t('SKU'))
->setDescription(t('The unique, human-readable identifier for a product.'))
->setRequired(TRUE)
->addConstraint('ProductSku')
->setTranslatable(TRUE)
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'string',
'weight' => -4,
])
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => -4,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['type'] = BaseFieldDefinition::create('string')
->setLabel(t('Type'))
->setDescription(t('The type of the product.'))
->setRequired(TRUE);
$fields['status'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Active'))
->setDescription(t('Disabled products cannot be added to shopping carts and may be hidden in administrative product lists.'))
->setDefaultValue(TRUE)
->setTranslatable(TRUE)
->setSettings([
......@@ -305,7 +265,7 @@ class Product extends ContentEntityBase implements ProductInterface {
])
->setDisplayOptions('form', [
'type' => 'boolean_checkbox',
'weight' => 10,
'weight' => 20,
'settings' => [
'display_label' => TRUE
]
......@@ -335,7 +295,6 @@ class Product extends ContentEntityBase implements ProductInterface {
return $fields;
}
/**
* Default value callback for 'uid' base field definition.
*
......
......@@ -38,6 +38,7 @@ use Drupal\commerce_product\ProductTypeInterface;
* "label",
* "digital",
* "description",
* "variationType",
* },
* links = {
* "edit-form" = "/admin/commerce/config/product-types/{commerce_product_type}/edit",
......@@ -76,6 +77,13 @@ class ProductType extends ConfigEntityBundleBase implements ProductTypeInterface
*/
protected $description;
/**
* The matching variation type.
*
* @var string
*/
protected $variationType;
/**
* Option to specify if the product type is a digital service.
*
......@@ -98,6 +106,21 @@ class ProductType extends ConfigEntityBundleBase implements ProductTypeInterface
return $this;
}
/**
* {@inheritdoc}
*/
public function getVariationType() {
return $this->variationType;
}
/**
* {@inheritdoc}
*/
public function setVariationType($variationType) {
$this->variationType = $variationType;
return $this;
}
/**
* {@inheritdoc}
*/
......
<?php
/**
* @file
* Contains \Drupal\commerce_product\Entity\ProductVariation.
*/
namespace Drupal\commerce_product\Entity;
use Drupal\commerce_product\ProductVariationInterface;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Entity\ContentEntityBase;