# Plugins Reference

Entity Builder uses three plugin types: Operations, Validators, and Extensions.

## Plugin Types Overview

```mermaid
flowchart TB
    subgraph Plugins["Entity Builder Plugins"]
        OP[EbOperation<br/>Execute changes]
        VAL[EbValidator<br/>Cross-cutting validation]
        EXT[EbExtension<br/>Add YAML keys & operations]
    end

    subgraph Managers["Plugin Managers"]
        OPM[plugin.manager.eb_operation]
        VALM[plugin.manager.eb_validator]
        EXTM[plugin.manager.eb_extension]
    end

    OP --> OPM
    VAL --> VALM
    EXT --> EXTM
```

## EbOperation Plugins

Operations are the executable units that create, update, or delete Drupal entities.

### Core Operations

| Plugin ID | Label | Type | Description |
|-----------|-------|------|-------------|
| `create_bundle` | Create Bundle | create | Creates content type, vocabulary, media type |
| `update_bundle` | Update Bundle | update | Updates bundle configuration |
| `delete_bundle` | Delete Bundle | delete | Deletes a bundle |
| `create_field` | Create Field | create | Creates field storage and instance |
| `update_field` | Update Field | update | Updates field configuration |
| `delete_field` | Delete Field | delete | Deletes field instance |
| `hide_field` | Hide Field | update | Hides field from display |
| `reorder_fields` | Reorder Fields | update | Changes field display order |
| `configure_form_mode` | Configure Form Mode | update | Configures widget settings |
| `configure_view_mode` | Configure View Mode | update | Configures formatter settings |
| `create_menu` | Create Menu | create | Creates custom menu |
| `create_menu_link` | Create Menu Link | create | Creates menu link |

### Extension Operations

| Module | Plugin ID | Description |
|--------|-----------|-------------|
| `eb_field_group` | `create_field_group` | Creates field group |
| `eb_field_group` | `update_field_group` | Updates field group |
| `eb_field_group` | `delete_field_group` | Deletes field group |
| `eb_pathauto` | `create_pathauto_pattern` | Creates URL pattern |
| `eb_auto_entitylabel` | `configure_auto_entitylabel` | Configures auto labels |

### Operation Attribute

```php
#[EbOperation(
    id: 'my_operation',
    label: new TranslatableMarkup('My Operation'),
    description: new TranslatableMarkup('Description'),
    operationType: 'create',  // create, update, delete
)]
```

### Operation Interfaces

| Interface | Methods | Purpose |
|-----------|---------|---------|
| `OperationInterface` | `setData()`, `getData()`, `validate()` | Base interface |
| `FullOperationInterface` | `execute()` | Executable operations |
| `ReversibleOperationInterface` | `rollback()` | Rollback support |
| `PreviewableOperationInterface` | `preview()` | Preview generation |

### Creating an Operation

```php
<?php

namespace Drupal\my_module\Plugin\EbOperation;

use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\eb\Attribute\EbOperation;
use Drupal\eb\PluginBase\OperationBase;
use Drupal\eb\Result\ExecutionResult;
use Drupal\eb\Result\PreviewResult;
use Drupal\eb\Result\RollbackResult;
use Drupal\eb\Result\ValidationResult;

#[EbOperation(
    id: 'create_my_entity',
    label: new TranslatableMarkup('Create My Entity'),
    description: new TranslatableMarkup('Creates a my entity'),
    operationType: 'create',
)]
class CreateMyEntityOperation extends OperationBase {

  /**
   * {@inheritdoc}
   */
  public function validate(): ValidationResult {
    $result = new ValidationResult();
    $this->validateRequiredFields(['entity_id', 'label'], $result);
    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function preview(): PreviewResult {
    $preview = new PreviewResult();
    $preview->addOperation(
      'create',
      'my_entity',
      $this->getDataValue('entity_id'),
      $this->t('Create @label', ['@label' => $this->getDataValue('label')])
    );
    return $preview;
  }

  /**
   * {@inheritdoc}
   */
  public function execute(): ExecutionResult {
    // Create the entity
    $entity = $this->entityTypeManager
      ->getStorage('my_entity')
      ->create([
        'id' => $this->getDataValue('entity_id'),
        'label' => $this->getDataValue('label'),
      ]);
    $entity->save();

    $result = new ExecutionResult(TRUE);
    $result->addMessage($this->t('Created @label', ['@label' => $entity->label()]));
    $result->setRollbackData(['entity_id' => $entity->id(), 'was_new' => TRUE]);
    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function rollback(): RollbackResult {
    $rollbackData = $this->getDataValue('_rollback_data', []);
    $entityId = $rollbackData['entity_id'] ?? $this->getDataValue('entity_id');

    $entity = $this->entityTypeManager->getStorage('my_entity')->load($entityId);
    if ($entity && ($rollbackData['was_new'] ?? FALSE)) {
      $entity->delete();
    }

    $result = new RollbackResult(TRUE);
    $result->addMessage($this->t('Deleted @id', ['@id' => $entityId]));
    return $result;
  }

}
```

## EbValidator Plugins

Validators check cross-cutting concerns across all operations.

### Core Validators

| Plugin ID | Description |
|-----------|-------------|
| `dependency_validator` | Verifies entity/bundle/field existence |
| `required_fields_validator` | Checks required properties |
| `unique_name_validator` | Prevents naming conflicts |
| `field_type_validator` | Validates field type exists |
| `widget_compatibility_validator` | Checks widget-field compatibility |
| `formatter_compatibility_validator` | Checks formatter-field compatibility |
| `circular_dependency_validator` | Detects circular dependencies |

### Validator Attribute

```php
#[EbValidator(
    id: 'my_validator',
    label: new TranslatableMarkup('My Validator'),
    description: new TranslatableMarkup('Validates custom rules'),
)]
```

### Creating a Validator

```php
<?php

namespace Drupal\my_module\Plugin\EbValidator;

use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\eb\Attribute\EbValidator;
use Drupal\eb\PluginBase\ValidatorBase;
use Drupal\eb\PluginInterfaces\OperationInterface;
use Drupal\eb\Result\ValidationResult;

#[EbValidator(
    id: 'naming_convention_validator',
    label: new TranslatableMarkup('Naming Convention Validator'),
    description: new TranslatableMarkup('Enforces naming conventions'),
)]
class NamingConventionValidator extends ValidatorBase {

  /**
   * {@inheritdoc}
   */
  public function validate(OperationInterface $operation, array $context = []): ValidationResult {
    $result = new ValidationResult();
    $operationType = $operation->getDataValue('operation');

    if ($operationType === 'create_bundle') {
      $bundleId = $operation->getDataValue('bundle_id');

      // Enforce prefix
      if (!str_starts_with($bundleId, 'myapp_')) {
        $result->addError(
          'Bundle ID must start with "myapp_".',
          'bundle_id',
          'naming_convention'
        );
      }
    }

    return $result;
  }

}
```

## EbExtension Plugins

Extensions add custom YAML keys, operations, and integration logic.

### Core Extensions

| Module | Plugin ID | YAML Keys | Operations |
|--------|-----------|-----------|------------|
| `eb_field_group` | `field_group` | `field_group_definitions` | `create_field_group`, etc. |
| `eb_pathauto` | `pathauto` | - (bundle column) | `create_pathauto_pattern` |
| `eb_auto_entitylabel` | `auto_entitylabel` | - (bundle columns) | `configure_auto_entitylabel` |

### Extension Attribute

```php
#[EbExtension(
    id: 'my_extension',
    label: new TranslatableMarkup('My Extension'),
    description: new TranslatableMarkup('Adds my functionality'),
    yaml_keys: ['my_definitions'],
    operations: ['create_my_entity', 'update_my_entity'],
    module_dependencies: ['my_dependency'],
)]
```

### Extension Interface

| Method | Purpose |
|--------|---------|
| `buildOperations(array $data)` | Convert YAML to operations |
| `getOperationDependencies(array $operation, array $batch)` | Declare dependencies |
| `detectChanges(array $operation, array $context)` | Change detection for sync mode |
| `checkDependencies(array $operation)` | Verify dependencies exist |
| `appliesTo(array $operation)` | Check if extension handles operation |
| `getYamlKeys()` | Get YAML keys from plugin definition |
| `getOperations()` | Get operations from plugin definition |
| `extractConfig(string $entityType, string $bundle)` | Export existing config |

### Creating an Extension

See the [Creating Extensions](../developers/extensions.md) guide for complete examples.

## Plugin Discovery

### List All Plugins

```php
// Operations
$operationManager = \Drupal::service('plugin.manager.eb_operation');
$definitions = $operationManager->getDefinitions();

// Validators
$validatorManager = \Drupal::service('plugin.manager.eb_validator');
$definitions = $validatorManager->getDefinitions();

// Extensions
$extensionManager = \Drupal::service('plugin.manager.eb_extension');
$extensions = $extensionManager->getExtensions();
```

### Create Plugin Instance

```php
// Create operation instance
$operation = $operationManager->createInstance('create_field', [
  'entity_type' => 'node',
  'bundle' => 'article',
  'field_name' => 'field_body',
  'field_type' => 'text_long',
]);

// Create validator instance
$validator = $validatorManager->createInstance('dependency_validator');
```

### Extension Manager Methods

```php
$extensionManager = \Drupal::service('plugin.manager.eb_extension');

// Get extensions for operation type
$extensions = $extensionManager->getExtensionsForOperation('create_field_group');

// Get extensions for YAML key
$extensions = $extensionManager->getExtensionsForYamlKey('field_group_definitions');

// Get all definition keys from extensions
$keys = $extensionManager->getAllDefinitionKeys();
```

## Plugin Namespace Locations

| Plugin Type | Namespace | Directory |
|-------------|-----------|-----------|
| EbOperation | `Drupal\{module}\Plugin\EbOperation` | `src/Plugin/EbOperation/` |
| EbValidator | `Drupal\{module}\Plugin\EbValidator` | `src/Plugin/EbValidator/` |
| EbExtension | `Drupal\{module}\Plugin\EbExtension` | `src/Plugin/EbExtension/` |

## Best Practices

1. **Use base classes** - Extend `OperationBase`, `ValidatorBase`, `EbExtensionBase`
2. **Implement all interfaces** - Full operations need preview, execute, rollback
3. **Store rollback data** - Enable undo functionality
4. **Handle exceptions** - Use specific exception types with meaningful messages
5. **Log operations** - Use the logger channel for audit trail
6. **Test thoroughly** - Write unit tests for all plugin methods
