Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: PHP Tests

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
php-versions: ['8.3', '8.4', '8.5']

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none

- name: Check PHP Version
run: php -v

- name: Install dependencies
run: composer install --prefer-dist --no-progress

- name: Run unit tests
run: ./vendor/bin/phpunit -c phpunit.xml.dist
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/vendor/
/composer.lock
/.phpunit.cache/
.phpunit.result.cache
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# 2.0.0 (2026-07-21)
- :boom: **BC break**: now requires `oliverde8/php-etl-bundle` `^2.0`, `easycorp/easyadmin-bundle` `^5.2` and PHP `>=8.3`.
- :star2: Compatibility with EasyAdmin 5, Symfony 7/8 and PHP 8.4 (constructor promotion, `FormField::addFieldset`, native return types, `getUserIdentifier()`).
- :star2: V2 (typed PHP `ChainDefinitionInterface`) chains are now listed in the "New execution" form, alongside legacy YAML chains (via the `etl.chain_definition` tag).
- :wrench: Routing moved to native PHP attributes: `#[Route]` + `#[MapEntity]` on the download controller (dropped the abandoned `sensio/framework-extra-bundle` `@ParamConverter`), and `#[AdminRoute]` on the dashboard controller so it renders inside EasyAdmin's `AdminContext`.
- :wrench: Fixed the `code_editor` field template for EasyAdmin 5 (`ea()` accessor).
- :wrench: Vendored the JSON editor assets (jsoneditor 9.4.1) into the bundle instead of loading them from a CDN, so the admin UI works offline and under a strict Content-Security-Policy.
- :wrench: Fixed dashboard typos: the Success tile filter link (`sucess` → `success`) and the time-period selector `name` attribute.
- :warning: The "run from the interface" flow for V2 chains requires the matching `oliverde8/php-etl-bundle` 2.0 fix that stores a string definition for object-based (V2) chain definitions.

# 1.1.0
- :star2: Support for phpEtlBundle 1.1 was added.

Expand Down
8 changes: 6 additions & 2 deletions Controller/Admin/EtlDashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

namespace Oliverde8\PhpEtlEasyAdminBundle\Controller\Admin;

use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminRoute;
use Oliverde8\PhpEtlBundle\Entity\EtlExecution;
use Oliverde8\PhpEtlBundle\Repository\EtlExecutionRepository;
use Oliverde8\PhpEtlBundle\Security\EtlExecutionVoter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class EtlDashboardController extends AbstractController
{
Expand All @@ -21,8 +21,12 @@ public function __construct(protected EtlExecutionRepository $etlExecutionReposi
}

/**
* @Route("/etl/execution/dashboard", name="etl_execution_dashboard")
* Rendered as an EasyAdmin route so the request carries the AdminContext the
* dashboard template needs (the "ea" Twig global + the admin layout/menu).
* The final route name/path are prefixed with the app dashboard's
* (e.g. name "admin_etl_execution_dashboard", path "/admin/etl/execution/dashboard").
*/
#[AdminRoute(path: '/etl/execution/dashboard', name: 'etl_execution_dashboard')]
public function index($startDate = null, $endDate = null): Response
{
$this->denyAccessUnlessGranted(EtlExecutionVoter::DASHBOARD, EtlExecution::class);
Expand Down
16 changes: 8 additions & 8 deletions Controller/Admin/EtlDownloadFileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@
use Oliverde8\PhpEtlBundle\Entity\EtlExecution;
use Oliverde8\PhpEtlBundle\Security\EtlExecutionVoter;
use Oliverde8\PhpEtlBundle\Services\ExecutionContextFactory;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Attribute\Route;

class EtlDownloadFileController extends AbstractController
{
public function __construct(protected ExecutionContextFactory $executionContextFactory)
{
}

/**
* @Route("/etl/execution/download", name="etl_execution_download_file")
*
* @ParamConverter(name="execution", Class="Oliverde8PhpEtlBundle:EtlExecution")
*/
public function index(EtlExecution $execution, string $filename): Response
#[Route(
'/etl/execution/{execution}/download/{filename}',
name: 'etl_execution_download_file',
requirements: ['filename' => '.+'],
)]
public function index(#[MapEntity(id: 'execution')] EtlExecution $execution, string $filename): Response
{
$this->denyAccessUnlessGranted(EtlExecutionVoter::DOWNLOAD, EtlExecution::class);

Expand Down
25 changes: 21 additions & 4 deletions Controller/Admin/EtlExecutionCrudController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,24 @@
use EasyCorp\Bundle\EasyAdminBundle\Filter\ChoiceFilter;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Oliverde8\PhpEtlBundle\Entity\EtlExecution;
use Oliverde8\PhpEtlBundle\Etl\ChainDefinitionInterface\ChainDefinitionInterface;
use Oliverde8\PhpEtlBundle\Security\EtlExecutionVoter;
use Oliverde8\PhpEtlBundle\Services\ChainProcessorsManager;
use Oliverde8\PhpEtlBundle\Services\ExecutionContextFactory;
use Symfony\Component\DependencyInjection\Attribute\AutowireIterator;

class EtlExecutionCrudController extends AbstractCrudController
{
public function __construct(protected ExecutionContextFactory $executionContextFactory, protected ChainProcessorsManager $chainProcessorManager, protected AdminUrlGenerator $adminUrlGenerator)
{
/**
* @param iterable<ChainDefinitionInterface> $chainDefinitions
*/
public function __construct(
protected ExecutionContextFactory $executionContextFactory,
protected ChainProcessorsManager $chainProcessorManager,
protected AdminUrlGenerator $adminUrlGenerator,
#[AutowireIterator('etl.chain_definition')]
protected iterable $chainDefinitions = [],
) {
}

public static function getEntityFqcn(): string
Expand Down Expand Up @@ -168,8 +178,8 @@ public function configureFields(string $pageName): iterable
public function configureAssets(Assets $assets): Assets
{
return $assets
->addJsFile('https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.4.1/jsoneditor.min.js')
->addCssFile('https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.4.1/jsoneditor.min.css')
->addJsFile('/bundles/oliverde8phpetleasyadmin/admin/vendor/jsoneditor/9.4.1/jsoneditor.min.js')
->addCssFile('/bundles/oliverde8phpetleasyadmin/admin/vendor/jsoneditor/9.4.1/jsoneditor.min.css')
->addJsFile('/bundles/oliverde8phpetleasyadmin/admin/fields/json-editor.js');
}

Expand Down Expand Up @@ -216,10 +226,17 @@ public function persistEntity(EntityManagerInterface $entityManager, $entityInst
protected function getChainOptions(): array
{
$options = [];

// Legacy YAML chain definitions.
foreach (array_keys($this->chainProcessorManager->getRawDefinitions()) as $definitionName) {
$options[$definitionName] = $definitionName;
}

// V2 (PHP) chain definitions, tagged with etl.chain_definition.
foreach ($this->chainDefinitions as $definition) {
$options[$definition->getKey()] = $definition->getKey();
}

return $options;
}
}
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# PHP Etl Easy Admin Bundle

<!-- TO BE COMPLETED -->

The Php etl easy admin bundle allows the usage of [Oliver's PHP Etl](https://github.com/oliverde8/php-etl) library in symfony.
Add's an integration to easy admin as well in order to see a list of the executions:

Expand All @@ -24,20 +22,22 @@ Also provides a dashboard to see current state.

3. Enable bundle:
```php
\Oliverde8\PhpEtlBundle\Oliverde8PhpEtlEasyAdminBundle::class => ['all' => true],
Oliverde8\PhpEtlEasyAdminBundle\Oliverde8PhpEtlEasyAdminBundle::class => ['all' => true],
```

4. Add to easy admin
```php
yield MenuItem::linktoRoute("Job Dashboard", 'fas fa-chart-bar', "etl_execution_dashboard");
// EtlDashboardController exposes the stats page via #[AdminRoute(name: 'etl_execution_dashboard')].
// EasyAdmin prefixes it with your Dashboard's own route name, e.g. "admin_etl_execution_dashboard".
yield MenuItem::linkToRoute("Job Dashboard", 'fas fa-chart-bar', "admin_etl_execution_dashboard");
yield MenuItem::linkToCrud('Etl Executions', 'fas fa-list', EtlExecution::class);
```

5. Enable routes
```yaml
etl_bundle:
resource: '@Oliverde8PhpEtlEasyAdminBundle/Controller'
type: annotation
type: attribute
prefix: /admin
```

Expand Down
3 changes: 2 additions & 1 deletion Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ services:
resource: '../../'
exclude:
- '../../DependencyInjection/'
- '../..//Entity/'
- '../../Entity/'
- '../../Tests/'
- '../../Etl/Operation'
- '../../vendor/'

Loading
Loading