Provide a plan_record entity type for plan record relationships with metadata #781
This commit is contained in:
commit
ee71b28ae6
|
@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- [Inventory quick form #766](https://github.com/farmOS/farmOS/pull/766)
|
||||
- [Add UI for creating instances of quick forms #785](https://github.com/farmOS/farmOS/pull/785)
|
||||
- [Show map on /locations #779](https://github.com/farmOS/farmOS/pull/779)
|
||||
- [Provide a plan_record entity type for plan record relationships with metadata #781](https://github.com/farmOS/farmOS/pull/781)
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"drupal/date_popup": "^1.3",
|
||||
"drupal/entity": "1.4",
|
||||
"drupal/entity_browser": "^2.10",
|
||||
"drupal/entity_reference_integrity": "^1.1",
|
||||
"drupal/entity_reference_integrity": "1.2",
|
||||
"drupal/entity_reference_revisions": "1.11",
|
||||
"drupal/entity_reference_validators": "^1.0@beta",
|
||||
"drupal/exif_orientation": "^1.2",
|
||||
|
@ -67,6 +67,9 @@
|
|||
"drupal/entity": {
|
||||
"Issue #3206703: Provide reverse relationships for bundle plugin entity_reference fields.": "https://www.drupal.org/files/issues/2022-05-11/3206703-10.patch"
|
||||
},
|
||||
"drupal/entity_reference_integrity": {
|
||||
"Issue #3418000: Delete action only overridden on first entity type": "https://www.drupal.org/files/issues/2024-01-30/3418000-3.patch"
|
||||
},
|
||||
"drupal/entity_reference_revisions": {
|
||||
"Issue #3267304: Infer target_revision_id to be Latest Revision when Only a target_id is Provided": "https://www.drupal.org/files/issues/2022-05-13/3267304-9.patch"
|
||||
},
|
||||
|
|
|
@ -16,6 +16,7 @@ function farm_entity_install() {
|
|||
'data_stream',
|
||||
'file',
|
||||
'log',
|
||||
'plan',
|
||||
'quantity',
|
||||
'taxonomy_term',
|
||||
'user',
|
||||
|
|
|
@ -46,7 +46,7 @@ function farm_entity_entity_type_build(array &$entity_types) {
|
|||
}
|
||||
|
||||
// Enable the use of bundle plugins on specific entity types.
|
||||
foreach (['asset', 'log', 'plan', 'quantity'] as $entity_type) {
|
||||
foreach (['asset', 'log', 'plan', 'plan_record', 'quantity'] as $entity_type) {
|
||||
if (!empty($entity_types[$entity_type])) {
|
||||
$entity_types[$entity_type]->set('bundle_plugin_type', $entity_type . '_type');
|
||||
$entity_types[$entity_type]->setHandlerClass('bundle_plugin', FarmEntityBundlePluginHandler::class);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Post update hooks for the farm_entity module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enforce entity reference integrity on plan reference fields.
|
||||
*/
|
||||
function farm_entity_post_update_enforce_plan_eri(&$sandbox) {
|
||||
$config = \Drupal::configFactory()->getEditable('entity_reference_integrity_enforce.settings');
|
||||
$entity_types = $config->get('enabled_entity_type_ids');
|
||||
$entity_types['plan'] = 'plan';
|
||||
$config->set('enabled_entity_type_ids', $entity_types);
|
||||
$config->save();
|
||||
}
|
|
@ -12,6 +12,9 @@ services:
|
|||
plugin.manager.plan_type:
|
||||
class: Drupal\farm_entity\PlanTypeManager
|
||||
parent: default_plugin_manager
|
||||
plugin.manager.plan_record_type:
|
||||
class: Drupal\farm_entity\PlanRecordTypeManager
|
||||
parent: default_plugin_manager
|
||||
plugin.manager.quantity_type:
|
||||
class: Drupal\farm_entity\QuantityTypeManager
|
||||
parent: default_plugin_manager
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\farm_entity\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
|
||||
/**
|
||||
* Defines the plan record relationship type plugin annotation object.
|
||||
*
|
||||
* Plugin namespace: Plugin\PlanRecord\PlanRecordType.
|
||||
*
|
||||
* @see plugin_api
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class PlanRecordType extends Plugin {
|
||||
|
||||
/**
|
||||
* The plugin ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* The plan record relationship type label.
|
||||
*
|
||||
* @var \Drupal\Core\Annotation\Translation
|
||||
*
|
||||
* @ingroup plugin_translatable
|
||||
*/
|
||||
public $label;
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\farm_entity;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginException;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Plugin\DefaultPluginManager;
|
||||
|
||||
/**
|
||||
* Manages discovery and instantiation of plan record relationship type plugins.
|
||||
*
|
||||
* @see \Drupal\farm_entity\Annotation\PlanType
|
||||
* @see plugin_api
|
||||
*/
|
||||
class PlanRecordTypeManager extends DefaultPluginManager {
|
||||
|
||||
/**
|
||||
* Constructs a new PlanRecordTypeManager object.
|
||||
*
|
||||
* @param \Traversable $namespaces
|
||||
* An object that implements \Traversable which contains the root paths
|
||||
* keyed by the corresponding namespace to look for plugin implementations.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
|
||||
* The cache backend.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
*/
|
||||
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
|
||||
parent::__construct('Plugin/PlanRecord/PlanRecordType', $namespaces, $module_handler, 'Drupal\farm_entity\Plugin\PlanRecord\PlanRecordType\PlanRecordTypeInterface', 'Drupal\farm_entity\Annotation\PlanRecordType');
|
||||
|
||||
$this->alterInfo('plan_record_type_info');
|
||||
$this->setCacheBackend($cache_backend, 'plan_record_type_plugins');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processDefinition(&$definition, $plugin_id) {
|
||||
parent::processDefinition($definition, $plugin_id);
|
||||
|
||||
foreach (['id', 'label'] as $required_property) {
|
||||
if (empty($definition[$required_property])) {
|
||||
throw new PluginException(sprintf('The plan record relationship type %s must define the %s property.', $plugin_id, $required_property));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\farm_entity\Plugin\PlanRecord\PlanRecordType;
|
||||
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* Provides a farmOS plan record relationship type base class.
|
||||
*/
|
||||
class FarmPlanRecordType extends PlanRecordTypeBase {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\farm_entity\Plugin\PlanRecord\PlanRecordType;
|
||||
|
||||
use Drupal\farm_entity\FarmEntityTypeBase;
|
||||
|
||||
/**
|
||||
* Provides the base plan record relationship type class.
|
||||
*/
|
||||
abstract class PlanRecordTypeBase extends FarmEntityTypeBase implements PlanRecordTypeInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLabel() {
|
||||
return $this->pluginDefinition['label'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildFieldDefinitions() {
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\farm_entity\Plugin\PlanRecord\PlanRecordType;
|
||||
|
||||
use Drupal\entity\BundlePlugin\BundlePluginInterface;
|
||||
|
||||
/**
|
||||
* Defines the interface for plan record relationship types.
|
||||
*/
|
||||
interface PlanRecordTypeInterface extends BundlePluginInterface {
|
||||
|
||||
/**
|
||||
* Gets the plan record relationship type label.
|
||||
*
|
||||
* @return string
|
||||
* The plan record relationship type label.
|
||||
*/
|
||||
public function getLabel();
|
||||
|
||||
}
|
|
@ -19,6 +19,20 @@ plan.type.*:
|
|||
type: boolean
|
||||
label: 'Create new revision'
|
||||
|
||||
plan.record.type.*:
|
||||
type: config_entity
|
||||
label: 'Plan record relationship type'
|
||||
mapping:
|
||||
id:
|
||||
type: string
|
||||
label: 'Machine-readable name'
|
||||
label:
|
||||
type: label
|
||||
label: 'Type'
|
||||
description:
|
||||
type: text
|
||||
label: 'Description'
|
||||
|
||||
condition.plugin.plan_type:
|
||||
type: condition.plugin
|
||||
mapping:
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Post update hooks for the plan module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Install plan_record and plan_record_type entity types.
|
||||
*/
|
||||
function plan_post_update_install_plan_record(&$sandbox) {
|
||||
\Drupal::entityDefinitionUpdateManager()->installEntityType(
|
||||
\Drupal::entityTypeManager()->getDefinition('plan_record_type')
|
||||
);
|
||||
\Drupal::entityDefinitionUpdateManager()->installEntityType(
|
||||
\Drupal::entityTypeManager()->getDefinition('plan_record')
|
||||
);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\plan\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines plan_record access logic.
|
||||
*/
|
||||
class PlanRecordAccess extends EntityAccessControlHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
|
||||
// If a plan is referenced, access is based on access to the plan.
|
||||
/** @var \Drupal\plan\Entity\PlanRecordInterface $plan */
|
||||
if ($plan = $entity->getPlan()) {
|
||||
return AccessResult::allowedIf($plan->access($operation, $account));
|
||||
}
|
||||
|
||||
// Otherwise, delegate to the parent method.
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\plan\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines the Plan record relationship entity.
|
||||
*
|
||||
* This entity type can be used to create relationships between a plan and other
|
||||
* record(s) along with additional metadata fields to describe the relationship.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "plan_record",
|
||||
* label = @Translation("Plan record relationship"),
|
||||
* bundle_label = @Translation("Plan record relationship type"),
|
||||
* label_collection = @Translation("Plan record relationships"),
|
||||
* label_singular = @Translation("plan record relationship"),
|
||||
* label_plural = @Translation("plan record relationships"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count plan record relationship",
|
||||
* plural = "@count plan record relationships",
|
||||
* ),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\plan\Access\PlanRecordAccess",
|
||||
* "form" = {
|
||||
* "edit" = "Drupal\Core\Entity\ContentEntityForm",
|
||||
* },
|
||||
* "route_provider" = {
|
||||
* "default" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
|
||||
* },
|
||||
* },
|
||||
* base_table = "plan_record",
|
||||
* data_table = "plan_record_data",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "label" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* },
|
||||
* bundle_entity_type = "plan_record_type",
|
||||
* common_reference_target = TRUE,
|
||||
* links = {
|
||||
* "edit-form" = "/plan/record/{plan_record}/edit",
|
||||
* },
|
||||
* )
|
||||
*/
|
||||
class PlanRecord extends ContentEntityBase implements PlanRecordInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBundleLabel() {
|
||||
/** @var \Drupal\plan\Entity\PlanRecordTypeInterface $type */
|
||||
$type = \Drupal::entityTypeManager()
|
||||
->getStorage('plan_record_type')
|
||||
->load($this->bundle());
|
||||
return $type->label();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['plan'] = BaseFieldDefinition::create('entity_reference')
|
||||
->setLabel(t('Plan'))
|
||||
->setDescription(t('Associate this plan record relationship with a plan entity.'))
|
||||
->setTranslatable(FALSE)
|
||||
->setCardinality(1)
|
||||
->setSetting('target_type', 'plan')
|
||||
->setDisplayOptions('form', [
|
||||
'type' => 'entity_reference',
|
||||
'weight' => 12,
|
||||
])
|
||||
->setDisplayConfigurable('form', TRUE)
|
||||
->setDisplayConfigurable('view', TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPlan(): ?PlanInterface {
|
||||
return $this->get('plan')->first()?->entity;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\plan\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface for defining plan record relationship entities.
|
||||
*/
|
||||
interface PlanRecordInterface extends ContentEntityInterface {
|
||||
|
||||
/**
|
||||
* Gets the label of the plan record relationship type.
|
||||
*
|
||||
* @return string
|
||||
* The label of the plan record relationship type.
|
||||
*/
|
||||
public function getBundleLabel();
|
||||
|
||||
/**
|
||||
* Returns the Plan entity the plan record is assigned to.
|
||||
*
|
||||
* @return \Drupal\plan\Entity\PlanInterface|null
|
||||
* The plant entity or NULL if not assigned.
|
||||
*/
|
||||
public function getPlan(): ?PlanInterface;
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\plan\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
|
||||
|
||||
/**
|
||||
* Defines the Plan record relationship type entity.
|
||||
*
|
||||
* @ConfigEntityType(
|
||||
* id = "plan_record_type",
|
||||
* label = @Translation("Plan record relationship type"),
|
||||
* label_collection = @Translation("Plan record relationship types"),
|
||||
* label_singular = @Translation("Plan record relationship type"),
|
||||
* label_plural = @Translation("plan record relationship types"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count plan record relationship type",
|
||||
* plural = "@count plan record relationship types",
|
||||
* ),
|
||||
* handlers = {
|
||||
* "access" = "\Drupal\entity\BundleEntityAccessControlHandler",
|
||||
* },
|
||||
* config_prefix = "record.type",
|
||||
* bundle_of = "plan_record",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "label" = "label",
|
||||
* "uuid" = "uuid",
|
||||
* },
|
||||
* config_export = {
|
||||
* "id",
|
||||
* "label",
|
||||
* "description",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class PlanRecordType extends ConfigEntityBundleBase implements PlanRecordTypeInterface {
|
||||
|
||||
/**
|
||||
* The Plan record relationship type ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The Plan record relationship type label.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* A brief description of this plan record relationship type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDescription() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDescription($description) {
|
||||
return $this->set('description', $description);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\plan\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Entity\EntityDescriptionInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface for defining Plan record relationship type entities.
|
||||
*/
|
||||
interface PlanRecordTypeInterface extends ConfigEntityInterface, EntityDescriptionInterface {
|
||||
|
||||
}
|
Loading…
Reference in New Issue