# Developer Getting Started

Learn how to extend Entity Builder with custom operations, validators, and extensions.

## Architecture Overview

Entity Builder uses three plugin types:

| Plugin Type | Purpose | Manager |
|-------------|---------|---------|
| **EbOperation** | Execute operations (create, update, delete) | `plugin.manager.eb_operation` |
| **EbValidator** | Validate operations (cross-cutting concerns) | `plugin.manager.eb_validator` |
| **EbExtension** | Add custom YAML keys, operations, dependencies | `plugin.manager.eb_extension` |

## Development Environment Setup

### 1. Clone the Repository

```bash
cd web/modules/custom
git clone [repository-url] eb
```

### 2. Install Dependencies

```bash
cd eb
composer install
```

### 3. Enable Development Mode

Edit `eb.settings.yml`:

```yaml
eb.settings:
  debug_mode: true
  log_operations: true
```

### 4. Run Tests

```bash
# Unit tests
./vendor/bin/phpunit tests/src/Unit

# Kernel tests
./vendor/bin/phpunit tests/src/Kernel

# All tests
./vendor/bin/phpunit
```

## Service Overview

### Core Services

```php
// Operation building
$operationBuilder = \Drupal::service('eb.operation_builder');
$operationDataBuilder = \Drupal::service('eb.operation_data_builder');

// Validation
$validationManager = \Drupal::service('eb.validation_manager');

// Execution
$operationProcessor = \Drupal::service('eb.operation_processor');
$rollbackManager = \Drupal::service('eb.rollback_manager');

// Discovery
$discoveryService = \Drupal::service('eb.discovery_service');

// Parsing
$yamlParser = \Drupal::service('eb.yaml_parser');
```

### Plugin Managers

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

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

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

## Key Interfaces

### OperationInterface

All operations must implement `OperationInterface`:

```php
interface OperationInterface {
    public function setData(array $data): void;
    public function getData(): array;
    public function getDataValue(string $key, mixed $default = NULL): mixed;
    public function validate(): ValidationResult;
}
```

### FullOperationInterface

Operations that execute changes implement `FullOperationInterface`:

```php
interface FullOperationInterface extends OperationInterface {
    public function execute(): ExecutionResult;
}
```

### ReversibleOperationInterface

Operations that support rollback implement `ReversibleOperationInterface`:

```php
interface ReversibleOperationInterface {
    public function rollback(): RollbackResult;
}
```

### PreviewableOperationInterface

Operations that show previews implement `PreviewableOperationInterface`:

```php
interface PreviewableOperationInterface {
    public function preview(): PreviewResult;
}
```

## Result Classes

### ValidationResult

```php
$result = new ValidationResult();
$result->addError('Field type not found', 'field_type', 'field_type_not_found');
$result->addWarning('Widget may not be compatible');
$result->isValid(); // false
```

### ExecutionResult

```php
$result = new ExecutionResult(TRUE);
$result->addMessage('Field created successfully.');
$result->addAffectedEntity([
    'type' => 'field_config',
    'id' => 'node.article.field_body',
    'label' => 'Body field',
]);
$result->setRollbackData(['field_id' => 'node.article.field_body']);
```

### PreviewResult

```php
$preview = new PreviewResult();
$preview->addOperation('create', 'field_config', 'node.article.field_body', 'Create Body field');
$preview->addDetails([
    'Field Type' => 'text_long',
    'Required' => 'Yes',
]);
```

### RollbackResult

```php
$result = new RollbackResult(TRUE);
$result->addMessage('Field deleted successfully.');
$result->addRestoredEntity(['type' => 'field_config', 'id' => 'node.article.field_body']);
```

## Quick Examples

### Create a Simple 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\ValidationResult;

#[EbOperation(
    id: 'my_custom_operation',
    label: new TranslatableMarkup('My Custom Operation'),
    description: new TranslatableMarkup('Does something custom'),
    operationType: 'create',
)]
class MyCustomOperation extends OperationBase {

    public function validate(): ValidationResult {
        $result = new ValidationResult();
        $this->validateRequiredFields(['name'], $result);
        return $result;
    }

    public function execute(): ExecutionResult {
        $name = $this->getDataValue('name');
        // Do something with the name value.
        $result = new ExecutionResult(TRUE);
        $result->addMessage("Created: $name");
        return $result;
    }

}
```

### Create a Simple 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: 'my_custom_validator',
    label: new TranslatableMarkup('My Custom Validator'),
    description: new TranslatableMarkup('Validates custom rules'),
)]
class MyCustomValidator extends ValidatorBase {

    public function validate(OperationInterface $operation, array $context = []): ValidationResult {
        $result = new ValidationResult();

        // Add your validation logic
        $name = $operation->getDataValue('name');
        if (strlen($name) < 3) {
            $result->addError('Name must be at least 3 characters', 'name', 'name_too_short');
        }

        return $result;
    }

}
```

## Next Steps

- [Creating Extensions](extensions.md) - Build full extension plugins
