42 Commits
v4.4.0 ... v6.x

Author SHA1 Message Date
loic
2bde5af903 update changelog 2026-03-03 14:14:17 +01:00
loic
63190e894b add product attributes comparator 2026-03-03 13:48:21 +01:00
loic
a682881db9 add product attributes 2026-03-03 10:56:32 +01:00
loic
957b270bbe fix taxonomy comparator 2026-01-27 13:07:30 +01:00
loic
cca5bc57b4 add number formating 2025-11-04 13:59:17 +01:00
loic
137d5cbbb8 fix pagination 2025-10-13 10:33:49 +02:00
loic
08302a3fd7 fix pagination with TransformingAdapter 2025-10-13 10:30:38 +02:00
loic
1dfcd5ef5d Add transaction on create and update 2025-10-08 10:37:45 +02:00
loic
b3eddc2116 Add excaptions as files 2025-10-08 10:24:14 +02:00
loic
f204672681 fix label of checkbox 2025-10-02 16:28:02 +02:00
loic
a030a65214 fix all datepickers in modal
fix query for dashboard tab
2025-10-02 14:46:12 +02:00
loic
b6a1526f56 fix ez_datetime 2025-08-19 10:42:28 +02:00
loic
2d3f3df9e8 Remove map location filter 2025-08-19 09:09:12 +02:00
loic
158956117c Add map location filter 2025-08-19 09:07:27 +02:00
loic
31e9cde92e Add customer group filter 2025-08-19 09:02:30 +02:00
loic
9ed9e84298 Add customer group filter 2025-08-19 09:01:13 +02:00
loic
efe50b7613 Add billing address filter 2025-08-19 08:46:00 +02:00
loic
cae5c3d152 Add product filter 2025-08-19 08:36:20 +02:00
loic
a0596374d4 Add product filter 2025-08-06 16:38:44 +02:00
loic
3160d0e58e Add product filter 2025-08-06 16:33:35 +02:00
loic
bbd1b9f795 Upgrade to Ibexa 5 2025-08-06 10:06:36 +02:00
loic
a968a6c8e3 Upgrade to Ibexa 5 2025-07-31 09:19:57 +02:00
loic
99f1770842 Upgrade to Ibexa 5 2025-07-30 17:04:39 +02:00
loic
ac23baf91f Upgrade to Ibexa 5 2025-07-30 17:03:49 +02:00
loic
a0cb937af6 Upgrade to Ibexa 5 2025-07-24 16:15:42 +02:00
loic
04633d2fd3 Upgrade to Ibexa 5 2025-07-24 16:15:15 +02:00
loic
ffdf24fe0c Upgrade to Ibexa 5 2025-07-24 16:08:00 +02:00
loic
2618ba9463 Upgrade to Ibexa 5 2025-07-24 14:19:00 +02:00
loic
c0c571b058 Upgrade to Ibexa 5 2025-07-24 14:14:49 +02:00
loic
278f2fd114 Upgrade to Ibexa 5 2025-07-24 14:06:53 +02:00
loic
6ece645267 Added Dashboard tab 2025-07-04 08:41:40 +02:00
loic
5180108598 Added Dashboard tab 2025-07-04 08:19:00 +02:00
jb cr
08cd3eccd6 prepare publishing 2025-04-02 11:18:21 +02:00
jbcr
9dc90bb001 add make by mention (#6) 2025-04-02 11:15:36 +02:00
AUDUL
4b8554c64a Add oneshot v5 (#3)
* Added possibility to create one shot job from scheduled job
2025-02-18 14:30:40 +01:00
Jérémy J
4b8403b2b0 Updated CHANGELOG 2025-02-04 11:06:20 +01:00
Jérémy J
198b5922a4 Fix controller 2025-02-04 10:32:19 +01:00
Jérémy J
eacd4c5e2c Updated code with Rector 2025-02-04 10:01:38 +01:00
Jérémy J
51132a8a30 Merge branch 'v4.x' into v5.x 2025-02-03 11:01:55 +01:00
Jérémy J
137f9a46b5 Updated dependencies 2025-02-03 10:42:55 +01:00
Jérémy J
c5ea78f37c Fixed replacement phar 2025-01-31 11:02:51 +01:00
Jérémy J
8bf5805589 Renamed bundle to IbexaDataflowBundle 2024-12-13 15:50:47 +01:00
124 changed files with 1628 additions and 1153 deletions

1
.gitignore vendored
View File

@@ -4,4 +4,5 @@ composer.lock
.php_cs.cache
.php_cs
.php-cs-fixer.cache
.php-version
.idea

View File

@@ -1,3 +1,36 @@
# Version 6.1.0
* Add `ibexa_product_specification` comparator
* Add `attributes` in `ProductCreateStructure` and `ProductUpdateStructure`
# Version 6.0.1
* Fix taxonomy comparator
# Version 6.0.0
* Ibexa 5.0+ support
* Comparators for Ibexa Commerce / Experience field types
# Version 5.2.1
* Fixed datepicker in oneshot modal
# Version 5.2.0
* Added Dashboard tab
# Version 5.1.1
* Add branding label
# Version 5.1.0
* Added possibility to create one shot job from scheduled job
# Version 5.0.0
* Renamed bundle to IbexaDataflowBundle
* Replaced every trace of ezdataflow with ibexa_dataflow or ibexa-dataflow
* Added automatic replacement script
# Version 4.3.0
* Replaced date field with date picker
# Version 4.2.0
* Added error count columns to job tables

View File

@@ -1,4 +1,4 @@
Copyright (c) 2019 Code Rhapsodie
Copyright (c) 2024 Code Rhapsodie
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

158
README.md
View File

@@ -8,12 +8,12 @@ Ibexa Dataflow bundle is intended to manage content imports from external data s
> Note: before using this bundle, please read
> the [Code Rhapsodie Dataflow bundle documentation](https://github.com/code-rhapsodie/dataflow-bundle/blob/master/README.md).
> Command line notice: When you use Dataflow commands, **use `--siteaccess` instead of `--connection`** expect
> Command line notice: When you use Dataflow commands, **use `--siteaccess` instead of `--connection`** except
> for `code-rhapsodie:dataflow:dump-schema` command.
| Ibexa Dataflow Version | Ibexa Content Version | Status |
|------------------------|-----------------------|-------------------------------|
| 4.x | 4.x | :white_check_mark: Maintained |
| 6.x | 5.x | :white_check_mark: Maintained |
## User Interface (UI)
@@ -29,12 +29,12 @@ Processes can be set to run either:
### Step 1: Install the bundle via composer
```shell script
$ composer require code-rhapsodie/ezdataflow-bundle
$ composer require code-rhapsodie/ibexa-dataflow-bundle
```
### Step 2: Enable the bundle
> Note: The loading order between the Dataflow bundle and Ez Dataflow bundle is important. Dataflow must be loaded
> Note: The loading order between the Dataflow bundle and Ibexa Dataflow bundle is important. Dataflow must be loaded
> first.
Add those two lines in the `config/bundles.php` file:
@@ -45,7 +45,7 @@ Add those two lines in the `config/bundles.php` file:
return [
// ...
CodeRhapsodie\DataflowBundle\CodeRhapsodieDataflowBundle::class => ['all' => true],
CodeRhapsodie\EzDataflowBundle\CodeRhapsodieEzDataflowBundle::class => ['all' => true],
CodeRhapsodie\IbexaDataflowBundle\CodeRhapsodieIbexaDataflowBundle::class => ['all' => true],
// ...
];
```
@@ -53,10 +53,10 @@ return [
### Step 3: Import bundle routing file
```yaml
# config/routing/ezdataflow.yaml
# config/routing/ibexa_dataflow.yaml
_cr.dataflow:
resource: '@CodeRhapsodieEzDataflowBundle/Resources/config/routing.yaml'
_cr.ibexa_dataflow:
resource: '@CodeRhapsodieIbexaDataflowBundle/Resources/config/routing.yaml'
```
### Step 4: Update the database schema
@@ -75,9 +75,9 @@ By default, the `ContentWriter` will publish contents using the `admin` user. If
sufficient permissions), you can configure it like this:
```yaml
# config/packages/code_rhapsodie_ez_dataflow.yaml
# config/packages/code_rhapsodie_ibexa_dataflow.yaml
code_rhapsodie_ez_dataflow:
code_rhapsodie_ibexa_dataflow:
# Integer values are assumed to be user ids, non-integer values are assumed to be user logins
admin_login_or_id: webmaster
```
@@ -89,7 +89,7 @@ to [Code-Rhapsodie Dataflow type documentation](https://github.com/code-rhapsodi
## Use the ContentWriter
To add or update Ibexa contents, you can use the `CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter` writer.
To add or update Ibexa contents, you can use the `CodeRhapsodie\IbexaDataflowBundle\Writer\ContentWriter` writer.
### Step 1: Inject the dependencies and add the writer
@@ -99,21 +99,15 @@ list like this:
```php
// In your DataflowType
use CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter;
use CodeRhapsodie\IbexaDataflowBundle\Writer\ContentWriter;
use CodeRhapsodie\DataflowBundle\DataflowType\AbstractDataflowType;
[...]
class MyDataflowType extends AbstractDataflowType
{
//[...]
/**
* @var ContentWriter
*/
private $contentWriter;
public function __construct(ContentWriter $contentWriter)
public function __construct(private readonly ContentWriter $contentWriter)
{
$this->contentWriter = $contentWriter;
}
//[...]
protected function buildDataflow(DataflowBuilder $builder, array $options): void
@@ -153,36 +147,26 @@ In this example, I have added a new folder to store all articles.
To get the location id of the parent Ibexa content, go to the admin UI and select the future parent content, click on
the details tabs, and read the "Location id" like this:
![parent folder](src/Resources/doc/dest_folder.jpg)
![parent folder](src/Resources/doc/dest_folder.png)
> Note: the best practice is to define this parent id in your `parameters.yml` file or your `.env.local` file for each
> Note: the best practice is to define this parent id in your `parameters.yaml` file or your `.env.local` file for each
> execution environment.
```php
// In your DataflowType
use CodeRhapsodie\EzDataflowBundle\Factory\ContentStructureFactory;
use CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter;
use CodeRhapsodie\IbexaDataflowBundle\Factory\ContentStructureFactory;
use CodeRhapsodie\IbexaDataflowBundle\Writer\ContentWriter;
use CodeRhapsodie\DataflowBundle\DataflowType\AbstractDataflowType;
[...]
class MyDataflowType extends AbstractDataflowType
{
//[...]
/**
* @var ContentWriter
*/
private $contentWriter;
/**
* @var ContentStructureFactory
*/
private $contentStructureFactory;
public function __construct(ContentWriter $contentWriter, ContentStructureFactory $contentStructureFactory)
{
$this->contentWriter = $contentWriter;
$this->contentStructureFactory = $contentStructureFactory;
public function __construct(
private readonly ContentWriter $contentWriter,
private readonly ContentStructureFactory $contentStructureFactory
) {
}
//[...]
protected function buildDataflow(DataflowBuilder $builder, array $options): void
@@ -197,13 +181,13 @@ class MyDataflowType extends AbstractDataflowType
unset($data['id']);
return $this->contentStructureFactory->transform(
$data,
$remoteId,
'eng-GB',
'article2',
54, //Parent location id
ContentStructureFactoryInterface::MODE_INSERT_OR_UPDATE //Optional value. Other choice : ContentStructureFactoryInterface::MODE_INSERT_ONLY or ContentStructureFactoryInterface::MODE_UPDATE_ONLY
);
$data,
$remoteId,
'eng-GB',
'article2',
54, //Parent location id
ContentStructureFactoryInterface::MODE_INSERT_OR_UPDATE //Optional value. Other choice : ContentStructureFactoryInterface::MODE_INSERT_ONLY or ContentStructureFactoryInterface::MODE_UPDATE_ONLY
);
});
// If you want the writer log
$this->contentWriter->setLogger($this->logger);
@@ -248,27 +232,32 @@ the `NotModifiedContentFilter` to prevent unnecessary overhead.
### Supported field types
- ezstring
- ezauthor
- ezboolean
- ezcountry
- ezdate
- ezdatetime
- ezemail
- ezfloat
- ezisbn
- ezobjectrelation
- ezobjectrelationlist
- ezkeyword
- ezselection
- eztext
- eztime
- ibexa_author
- ibexa_boolean
- ibexa_country
- ibexa_datetime
- ibexa_date
- ibexa_email
- ibexa_float
- ibexa_integer
- ibexa_isbn
- ibexa_keyword
- ibexa_object_relation
- ibexa_object_relation_list
- ibexa_richtext
- ibexa_selection
- ibexa_text
- ibexa_string
- ibexa_time
- eztags
- ibexa_url
- novaseometas
- ezurl
- ezmatrix
- ezgmaplocation
- ezrichtext
- ibexa_matrix
- ibexa_gmap_location
- ibexa_taxonomy_entry_assignment
- ibexa_address
- ibexa_customer_group
- ibexa_product_specification
### Add custom field comparator
@@ -277,7 +266,7 @@ If you want to add support for a field type, simply create your own comparator.
```php
<?php
use CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator;
use CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator;
use Ibexa\Core\FieldType\Value;
//[...]
@@ -295,9 +284,9 @@ class MyFieldComparator extends AbstractFieldComparator
```yaml
# Service declaration
App\FieldComparator\MyFieldComparator:
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'my_field_type_identifier' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'my_field_type_identifier' }
```
# Admin UI
@@ -306,16 +295,16 @@ App\FieldComparator\MyFieldComparator:
You can access the Ibexa Dataflow administration UI from your Ibexa admin back-office.
![Admin menu](src/Resources/doc/ez_dataflow_admin_menu.jpg)
![Admin menu](src/Resources/doc/admin_menu.png)
1. Click to "Admin"
1. Click to "Ibexa Dataflow"
## Scheduled dataflow list
When you access to the Ibexa Dataflow administration UI, you going here:
When you access to the Ibexa Dataflow administration UI, you arrive on the scheduled dataflow list page:
![Scheduled dataflow list](src/Resources/doc/scheduled_list.jpg)
![Scheduled dataflow list](src/Resources/doc/scheduled_list.png)
1. Scheduled dataflow list
1. Button to add a new scheduled dataflow
@@ -333,7 +322,7 @@ Go to the Ibexa Dataflow admin, and click on the "+" orange button.
In the new popin, fill in the fields:
![Add a new schedule](src/Resources/doc/add_new_schedule.jpg)
![Add a new schedule](src/Resources/doc/add_new_schedule.png)
1. Type the Dataflow schedule name
1. Select the Dataflow type. The list is automatically generated from the list of Symfony services with the
@@ -353,15 +342,17 @@ Finally, click on the "Create" button.
When you click on the "History" tab in the Ibexa Dataflow admin UI, the job history for all Dataflow configured and
executed is displayed.
![History list](src/Resources/doc/history_list.jpg)
![History list](src/Resources/doc/history_list.png)
1. The history list
1. This column shows the number of objects that have been processed.
1. Click on the question mark to display the job details.
1. A summary of each job dates and number of items processed.
1. Click on the question mark icon to display the job details.
1. Click on the text icon to display the job exception log.
1. Switch between displaying all jobs, or only non-empty jobs (at least 1 item was processed)
Details of one scheduled job:
![Job execution details](src/Resources/doc/job_successful.jpg)
![Job execution details](src/Resources/doc/job_successful.png)
## One-shot job
@@ -369,23 +360,24 @@ If you don't want to run a Dataflow periodically, you can add a single execution
Go to the Ibexa Dataflow admin UI and click on the "Oneshot" tab.
![Oneshot list](src/Resources/doc/oneshot_list.jpg)
![Oneshot list](src/Resources/doc/oneshot_list.png)
1. This button allows you to define the one-shot job (see below).
1. This column shows the number of objects that have been processed.
1. Click on the question mark to display the job details.
1. This button allows you to create a new one-shot job (see below).
1. A summary of each job dates and number of items processed.
1. Click on the question mark icon to display the job details.
1. Click on the text icon to display the job exception log.
Details of one-shot job:
![onshot details](src/Resources/doc/job_fail.jpg)
![onshot details](src/Resources/doc/job_failed.png)
Here the job has fail.
## Add a one-shot job
Go to the Ibexa Dataflow admin UI and click on the "Oneshot" tab. Click on the "+" orange button to open the adding popin.
Go to the Ibexa Dataflow admin UI and click on the "Oneshot" tab. Click on the "+ Create" button to open the add popin.
![The add one-shot popin](src/Resources/doc/one_shot_job.jpg)
![The add one-shot popin](src/Resources/doc/one_shot_job.png)
1. Type the Dataflow job name
1. Select the Dataflow type. The list is automatically generated from the list of Symfony services with the
@@ -404,13 +396,13 @@ and `Ibexa Dataflow / View` policies in one of their roles.
# Issues and feature requests
Please report issues and request features at https://github.com/code-rhapsodie/ezdataflow-bundle/issues.
Please report issues and request features at https://github.com/code-rhapsodie/ibexa-dataflow-bundle/issues.
# Contributing
Contributions are very welcome. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for
details. Thanks
to [everyone who has contributed](https://github.com/code-rhapsodie/ezdataflow-bundle/graphs/contributors)
to [everyone who has contributed](https://github.com/code-rhapsodie/ibexa-dataflow-bundle/graphs/contributors)
already.
# License

View File

@@ -1,15 +1,28 @@
# From v1.0 to v2.0
In version 5, all references to ezdataflow were replaced by ibexa-dataflow, in namespaces, class names, tags and config keys.
This requires some changes in your application files.
When you use Dataflow commands, use `--siteaccess` instead of `--connection` except for `code-rhapsodie:dataflow:dump-schema`.
## Updating source files
[BC] The return of `CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway::findForScheduled`
and `CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway::findAllOrderedByLabel` has been changed.
The iterable contains an associative array instead of an object.
A script is provided to do all the replacements in your project files for you. Pass as arguments all directories where
replacing is needed.
[BC] In classes `CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway` and
`CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway`, all methods return `Doctrine\ORM\Query` object has
changed to return now a `Doctrine\DBAL\Query\QueryBuilder`
```shell
php vendor/bin/ibexa-dataflow-namespace-changer.phar src/ config/ templates/ translations/
```
[BC] The return type of `CodeRhapsodie\EzDataflowBundle\Factory\ContentStructureFactory::transform` has been changed
from `CodeRhapsodie\EzDataflowBundle\Model\ContentStructure` to `mixed`. In fact only `false` or
`CodeRhapsodie\EzDataflowBundle\Model\ContentStructure` object will be returned.
You should check all changes performed afterward. Here is the list of all the replacement that should be performed:
- all namespaces starting by `CodeRhapsodie\EzDataflowBundle` should now start by `CodeRhapsodie\IbexaDataflowBundle`, anywhere in PHP sources and services definitions
- the class `CodeRhapsodieEzDataflowBundle` should be renamed `CodeRhapsodieIbexaDataflowBundle` in `bundles.php`
- the config key `code_rhapsodie_ezdataflow` should be renamed `code_rhapsodie_ibexa_dataflow` in config files
- all translation keys starting by `ezdataflow` should now start by `ibexa_dataflow` in translation files
- the security policy module `ezdataflow` should be renamed `ibexa_dataflow`
- all template paths containing `ezdataflow` should now contain `ibexa_dataflow`
## Updating database
Run the following command on your database:
```sql
UPDATE ezpolicy SET module_name = 'ibexa_dataflow' WHERE module_name = 'ezdataflow'
```

Binary file not shown.

View File

@@ -3,7 +3,7 @@
"replace": {
"code-rhapsodie/ezdataflow-bundle": "*"
},
"description": "Import/export bundle for Ibexa based on Code-Rhapsodie Dataflow",
"description": "Import / export bundle for Ibexa Content based on Code Rhapsodie Dataflow framework",
"type": "symfony-bundle",
"keywords": ["dataflow", "import", "export", "data processing", "ibexa"],
"license": "MIT",
@@ -29,31 +29,33 @@
},
{
"name": "Other contributors",
"homepage": "https://github.com/code-rhapsodie/ezdataflow-bundle/graphs/contributors"
"homepage": "https://github.com/code-rhapsodie/ibexa-dataflow-bundle/graphs/contributors"
}
],
"autoload": {
"psr-4": {
"CodeRhapsodie\\EzDataflowBundle\\": "src/"
"CodeRhapsodie\\IbexaDataflowBundle\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"CodeRhapsodie\\EzDataflowBundle\\Tests\\": "tests/"
"CodeRhapsodie\\IbexaDataflowBundle\\Tests\\": "tests/"
}
},
"require": {
"php": "^7.4||^8.0",
"php": "^8.3",
"ext-json": "*",
"code-rhapsodie/dataflow-bundle": "^3.0||^4.0",
"code-rhapsodie/dataflow-bundle": "^5.0",
"guzzlehttp/promises": "^2.2",
"http-interop/http-factory-guzzle": "^1.2",
"ibexa/admin-ui": "^4.0",
"ibexa/core": "^4.0"
"ibexa/admin-ui": "^5.0",
"ibexa/core": "^5.0"
},
"require-dev": {
"doctrine/dbal": "^2.0|^3.0",
"phpunit/phpunit": "^7||^8||^9"
"doctrine/dbal": "^3.0",
"phpunit/phpunit": "^12.0",
"rector/rector": "^2.0"
},
"minimum-stability": "dev",
"prefer-stable": true,
@@ -63,9 +65,12 @@
"php-http/discovery": true
}
},
"bin": ["bin/ibexa-dataflow-namespace-changer.phar"],
"extra": {
"branch-alias": {
"dev-v4.x": "4.x-dev"
"dev-v4.x": "4.x-dev",
"dev-v5.x": "5.x-dev",
"dev-v6.x": "6.x-dev"
}
}
}

View File

@@ -14,7 +14,7 @@
<ini name="error_reporting" value="-1"/>
</php>
<testsuites>
<testsuite name="EzDataflow tests suite">
<testsuite name="Ibexa Dataflow tests suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>

19
rector.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\ValueObject\PhpVersion;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/src',
__DIR__ . '/tests',
])
->withPhpVersion(PhpVersion::PHP_83)
// uncomment to reach your current PHP version
->withPhpSets(php83: true)
->withTypeCoverageLevel(0)
->withDeadCodeLevel(0)
->withCodeQualityLevel(0)
->withAttributesSets(symfony: true, doctrine: true);

View File

@@ -1,33 +0,0 @@
<?php
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle;
use CodeRhapsodie\EzDataflowBundle\DependencyInjection\CodeRhapsodieEzDataflowExtension;
use CodeRhapsodie\EzDataflowBundle\DependencyInjection\Compiler\FieldComparatorCompilerPass;
use CodeRhapsodie\EzDataflowBundle\Security\PolicyProvider;
use Ibexa\Bundle\Core\DependencyInjection\IbexaCoreExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class CodeRhapsodieEzDataflowBundle extends Bundle
{
protected $name = 'CodeRhapsodieEzDataflowBundle';
public function getContainerExtension()
{
return new CodeRhapsodieEzDataflowExtension();
}
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new FieldComparatorCompilerPass());
/** @var IbexaCoreExtension $ibexaExtension */
$ibexaExtension = $container->getExtension('ibexa');
$ibexaExtension->addPolicyProvider(new PolicyProvider());
}
}

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace CodeRhapsodie\IbexaDataflowBundle;
use CodeRhapsodie\IbexaDataflowBundle\DependencyInjection\CodeRhapsodieIbexaDataflowExtension;
use CodeRhapsodie\IbexaDataflowBundle\DependencyInjection\Compiler\FieldComparatorCompilerPass;
use CodeRhapsodie\IbexaDataflowBundle\Security\PolicyProvider;
use Ibexa\Bundle\Core\DependencyInjection\IbexaCoreExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class CodeRhapsodieIbexaDataflowBundle extends Bundle
{
public const string VERSION = '6.0.0';
public const string PRODUCT_NAME = 'ibexadataflow';
protected string $name = 'CodeRhapsodieIbexaDataflowBundle';
#[\Override]
public function getContainerExtension(): ?ExtensionInterface
{
return new CodeRhapsodieIbexaDataflowExtension();
}
public function build(ContainerBuilder $container): void
{
parent::build($container);
$container->addCompilerPass(new FieldComparatorCompilerPass());
/** @var IbexaCoreExtension $ibexaExtension */
$ibexaExtension = $container->getExtension('ibexa');
$ibexaExtension->addPolicyProvider(new PolicyProvider());
}
}

View File

@@ -2,161 +2,168 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Controller;
namespace CodeRhapsodie\IbexaDataflowBundle\Controller;
use CodeRhapsodie\DataflowBundle\Entity\Job;
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
use CodeRhapsodie\EzDataflowBundle\Form\CreateOneshotType;
use CodeRhapsodie\EzDataflowBundle\Form\CreateScheduledType;
use CodeRhapsodie\EzDataflowBundle\Form\UpdateScheduledType;
use CodeRhapsodie\EzDataflowBundle\Gateway\ExceptionJSONDecoderAdapter;
use CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway;
use CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway;
use CodeRhapsodie\DataflowBundle\ExceptionsHandler\ExceptionHandlerInterface;
use CodeRhapsodie\DataflowBundle\ExceptionsHandler\NullExceptionHandler;
use CodeRhapsodie\IbexaDataflowBundle\CodeRhapsodieIbexaDataflowBundle;
use CodeRhapsodie\IbexaDataflowBundle\Form\CreateOneshotType;
use CodeRhapsodie\IbexaDataflowBundle\Form\CreateScheduledType;
use CodeRhapsodie\IbexaDataflowBundle\Form\UpdateScheduledType;
use CodeRhapsodie\IbexaDataflowBundle\Gateway\ExceptionJSONDecoderAdapter;
use CodeRhapsodie\IbexaDataflowBundle\Gateway\JobGateway;
use CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway;
use CodeRhapsodie\IbexaDataflowBundle\Gateway\TransformingAdapter;
use Doctrine\DBAL\Query\QueryBuilder;
use Ibexa\Contracts\AdminUi\Controller\Controller;
use Ibexa\Contracts\Core\Ibexa;
use Ibexa\Core\MVC\Symfony\Security\Authorization\Attribute;
use Pagerfanta\Doctrine\DBAL\QueryAdapter;
use Pagerfanta\Pagerfanta;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Attribute\Route;
/**
* @Route("/ezdataflow")
*/
#[Route(path: '/ibexa_dataflow')]
class DashboardController extends Controller
{
/** @var \CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway */
private $jobGateway;
/** @var \CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway */
private $scheduledDataflowGateway;
public function __construct(JobGateway $jobGateway, ScheduledDataflowGateway $scheduledDataflowGateway)
public function __construct(
private readonly JobGateway $jobGateway,
private readonly ScheduledDataflowGateway $scheduledDataflowGateway,
private readonly ExceptionHandlerInterface $exceptionHandler
)
{
$this->jobGateway = $jobGateway;
$this->scheduledDataflowGateway = $scheduledDataflowGateway;
}
/**
* @Route("/", name="coderhapsodie.ezdataflow.main")
*/
#[Route(path: '/', name: 'coderhapsodie.ibexa_dataflow.main')]
public function main(): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
return $this->render('@ibexadesign/ezdataflow/Dashboard/main.html.twig');
$data = [
'product' => CodeRhapsodieIbexaDataflowBundle::PRODUCT_NAME,
'version' => CodeRhapsodieIbexaDataflowBundle::VERSION,
'php' => PHP_VERSION,
'ibexa' => Ibexa::VERSION,
];
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/main.html.twig', [
'link' => 'https://www.code-rhapsodie.fr/product/redirect/'.str_replace('=', '',
base64_encode(json_encode($data))
),
]);
}
public function repeating(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
$newWorkflow = new ScheduledDataflow();
$newWorkflow->setNext((new \DateTimeImmutable())->add(new \DateInterval('PT1H')));
$form = $this->createForm(CreateScheduledType::class, $newWorkflow, [
'action' => $this->generateUrl('coderhapsodie.ezdataflow.workflow.create'),
'action' => $this->generateUrl('coderhapsodie.ibexa_dataflow.workflow.create'),
]);
$updateForm = $this->createForm(UpdateScheduledType::class);
return $this->render('@ibexadesign/ezdataflow/Dashboard/repeating.html.twig', [
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/repeating.html.twig', [
'pager' => $this->getPager($this->scheduledDataflowGateway->getListQueryForAdmin(), $request),
'form' => $form->createView(),
'update_form' => $updateForm->createView(),
]);
}
/**
* @Route("/repeating", name="coderhapsodie.ezdataflow.repeating")
*/
#[Route(path: '/repeating', name: 'coderhapsodie.ibexa_dataflow.repeating')]
public function getRepeatingPage(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
return $this->render('@ibexadesign/ezdataflow/Dashboard/repeating.html.twig', [
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/repeating.html.twig', [
'pager' => $this->getPager($this->scheduledDataflowGateway->getListQueryForAdmin(), $request),
]);
}
public function oneshot(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
$newOneshotJob = new Job();
$newOneshotJob->setRequestedDate((new \DateTime())->add(new \DateInterval('PT1H')));
$form = $this->createForm(CreateOneshotType::class, $newOneshotJob, [
'action' => $this->generateUrl('coderhapsodie.ezdataflow.job.create'),
'action' => $this->generateUrl('coderhapsodie.ibexa_dataflow.job.create'),
]);
return $this->render('@ibexadesign/ezdataflow/Dashboard/oneshot.html.twig', [
'pager' => $this->getPager($this->jobGateway->getOneshotListQueryForAdmin(), $request),
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/oneshot.html.twig', [
'pager' => $this->getPager($this->jobGateway->getOneshotListQueryForAdmin(), $request, Job::class),
'form' => $form->createView(),
]);
}
/**
* @Route("/oneshot", name="coderhapsodie.ezdataflow.oneshot")
*/
#[Route(path: '/oneshot', name: 'coderhapsodie.ibexa_dataflow.oneshot')]
public function getOneshotPage(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
return $this->render('@ibexadesign/ezdataflow/Dashboard/oneshot.html.twig', [
'pager' => $this->getPager($this->jobGateway->getOneshotListQueryForAdmin(), $request),
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/oneshot.html.twig', [
'pager' => $this->getPager($this->jobGateway->getOneshotListQueryForAdmin(), $request, Job::class),
]);
}
public function history(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$filter = (int) $request->query->get('filter', JobGateway::FILTER_NONE);
return $this->render('@ibexadesign/ezdataflow/Dashboard/history.html.twig', [
'pager' => $this->getPager($this->jobGateway->getListQueryForAdmin($filter), $request),
'filter' => $filter,
]);
}
/**
* @Route("/history", name="coderhapsodie.ezdataflow.history")
*/
#[Route(path: '/history', name: 'coderhapsodie.ibexa_dataflow.history')]
public function getHistoryPage(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
$filter = (int) $request->query->get('filter', JobGateway::FILTER_NONE);
return $this->render('@ibexadesign/ezdataflow/Dashboard/history.html.twig', [
'pager' => $this->getPager($this->jobGateway->getListQueryForAdmin($filter), $request),
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/history.html.twig', [
'pager' => $this->getPager($this->jobGateway->getListQueryForAdmin($filter), $request, Job::class),
'filter' => $filter,
]);
}
/**
* @Route("/history/schedule/{id}", name="coderhapsodie.ezdataflow.history.workflow")
*/
#[Route(path: '/history/schedule/{id}', name: 'coderhapsodie.ibexa_dataflow.history.workflow')]
public function getHistoryForScheduled(Request $request, int $id): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
return $this->render('@ibexadesign/ezdataflow/Dashboard/schedule_history.html.twig', [
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/schedule_history.html.twig', [
'id' => $id,
'pager' => $this->getPager($this->jobGateway->getListQueryForScheduleAdmin($id), $request),
'pager' => $this->getPager($this->jobGateway->getListQueryForScheduleAdmin($id), $request, Job::class),
]);
}
private function getPager(QueryBuilder $query, Request $request): Pagerfanta
private function getPager(QueryBuilder $query, Request $request, string $class = null): Pagerfanta
{
$pager = new Pagerfanta(
new ExceptionJSONDecoderAdapter(
new QueryAdapter($query, function ($queryBuilder) {
return $queryBuilder->select('COUNT(DISTINCT id) AS total_results')
->resetQueryPart('orderBy')
->setMaxResults(1);
})
)
$adatapter = new ExceptionJSONDecoderAdapter(
new QueryAdapter($query, fn($queryBuilder) => $queryBuilder->select('COUNT(DISTINCT id) AS total_results')
->resetQueryPart('orderBy')
->setMaxResults(1))
);
if ($class === Job::class && !$this->exceptionHandler instanceof NullExceptionHandler) {
$adatapter = new TransformingAdapter($adatapter, function (array $value) {
$exceptions = $this->exceptionHandler->find((int)$value['id']);
$value['exceptions'] = $exceptions;
$value['total_results'] = \count($exceptions);
return $value;
});
}
$pager = new Pagerfanta($adatapter);
$pager->setMaxPerPage(20);
$pager->setCurrentPage($request->query->get('page', 1));
$pager->setCurrentPage($request->query->getInt('page', 1));
return $pager;
}
public function dashboard(): Response
{
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/dashboard.html.twig', [
'jobs' => $this->jobGateway->getListPendindOrRunning(),
]);
}
}

View File

@@ -2,77 +2,56 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Controller;
namespace CodeRhapsodie\IbexaDataflowBundle\Controller;
use CodeRhapsodie\DataflowBundle\Entity\Job;
use CodeRhapsodie\EzDataflowBundle\Form\CreateOneshotType;
use CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway;
use CodeRhapsodie\IbexaDataflowBundle\Form\CreateOneshotType;
use CodeRhapsodie\IbexaDataflowBundle\Gateway\JobGateway;
use CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway;
use Ibexa\Contracts\AdminUi\Controller\Controller;
use Ibexa\Contracts\AdminUi\Notification\NotificationHandlerInterface;
use Ibexa\Core\MVC\Symfony\Security\Authorization\Attribute;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @Route("/ezdataflow/job")
*/
#[Route(path: '/ibexa_dataflow/job')]
class JobController extends Controller
{
/** @var \CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway */
private $jobGateway;
/** @var \Ibexa\Contracts\AdminUi\Notification\NotificationHandlerInterface */
private $notificationHandler;
/** @var \Symfony\Contracts\Translation\TranslatorInterface */
private $translator;
public function __construct(
JobGateway $jobGateway,
NotificationHandlerInterface $notificationHandler,
TranslatorInterface $translator
) {
$this->jobGateway = $jobGateway;
$this->notificationHandler = $notificationHandler;
$this->translator = $translator;
public function __construct(private readonly JobGateway $jobGateway, private readonly NotificationHandlerInterface $notificationHandler, private readonly TranslatorInterface $translator, private readonly ScheduledDataflowGateway $scheduledDataflowGateway)
{
}
/**
* @Route("/details/{id}", name="coderhapsodie.ezdataflow.job.details")
*/
#[Route(path: '/details/{id}', name: 'coderhapsodie.ibexa_dataflow.job.details')]
public function displayDetails(int $id): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
return $this->render('@ibexadesign/ezdataflow/Item/details.html.twig', [
return $this->render('@ibexadesign/ibexa_dataflow/Item/details.html.twig', [
'item' => $this->jobGateway->find($id),
]);
}
/**
* @Route("/details/log/{id}", name="coderhapsodie.ezdataflow.job.log")
*/
#[Route(path: '/details/log/{id}', name: 'coderhapsodie.ibexa_dataflow.job.log')]
public function displayLog(int $id): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
$item = $this->jobGateway->find($id);
$log = array_map(function ($line) {
return preg_replace('~#\d+~', "\n$0", $line);
}, $item->getExceptions());
$log = array_map(fn($line) => preg_replace('~#\d+~', "\n$0", (string) $line), $item->getExceptions());
return $this->render('@ibexadesign/ezdataflow/Item/log.html.twig', [
return $this->render('@ibexadesign/ibexa_dataflow/Item/log.html.twig', [
'log' => $log,
]);
}
/**
* @Route("/create", name="coderhapsodie.ezdataflow.job.create", methods={"POST"})
*/
#[Route(path: '/create', name: 'coderhapsodie.ibexa_dataflow.job.create', methods: ['POST'])]
public function create(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'edit'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'edit'));
$newOneshot = new Job();
$form = $this->createForm(CreateOneshotType::class, $newOneshot);
@@ -84,24 +63,55 @@ class JobController extends Controller
try {
$this->jobGateway->save($newOneshot);
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ezdataflow.job.create.success'));
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ibexa_dataflow.job.create.success'));
} catch (\Exception $e) {
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.job.create.error',
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ibexa_dataflow.job.create.error',
['message' => $e->getMessage()]));
}
return new JsonResponse([
'redirect' => $this->generateUrl('coderhapsodie.ezdataflow.main', ['_fragment' => 'ibexa-tab-coderhapsodie-ezdataflow-code-rhapsodie-ezdataflow-oneshot'],
'redirect' => $this->generateUrl('coderhapsodie.ibexa_dataflow.main', ['_fragment' => 'ibexa-tab-coderhapsodie-ibexa_dataflow-code-rhapsodie-ibexa_dataflow-oneshot'],
UrlGeneratorInterface::ABSOLUTE_URL),
]);
}
return new JsonResponse([
'form' => $this->renderView('@ibexadesign/ezdataflow/parts/form_modal.html.twig', [
'form' => $this->renderView('@ibexadesign/ibexa_dataflow/parts/form_modal.html.twig', [
'form' => $form->createView(),
'type_action' => 'new',
'mode' => 'oneshot',
]),
]);
}
#[Route(path: '/run-oneshot/{id}', name: 'coderhapsodie.ibexa_dataflow.job.run-oneshot', methods: ['GET'])]
public function runOneShot(int $id): Response
{
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
$scheduledDataflow = $this->scheduledDataflowGateway->find($id);
if ($scheduledDataflow === null) {
throw new NotFoundHttpException();
}
$newOneshotJob = new Job();
$newOneshotJob->setOptions($scheduledDataflow->getOptions());
$newOneshotJob->setLabel("Manual " . $scheduledDataflow->getLabel());
$newOneshotJob->setScheduledDataflowId($scheduledDataflow->getId());
$newOneshotJob->setRequestedDate((new \DateTime())->add(new \DateInterval('PT1H')));
$newOneshotJob->setDataflowType($scheduledDataflow->getDataflowType());
$form = $this->createForm(CreateOneshotType::class, $newOneshotJob, [
'action' => $this->generateUrl('coderhapsodie.ibexa_dataflow.job.create'),
]);
return new JsonResponse([
'form' => $this->renderView('@ibexadesign/ibexa_dataflow/parts/form_modal.html.twig', [
'form' => $form->createView(),
'id' => 'modal-new-oneshot',
'mode' => 'oneshot',
]),
]);
}
}

View File

@@ -2,49 +2,32 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Controller;
namespace CodeRhapsodie\IbexaDataflowBundle\Controller;
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
use CodeRhapsodie\EzDataflowBundle\Form\CreateScheduledType;
use CodeRhapsodie\EzDataflowBundle\Form\UpdateScheduledType;
use CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway;
use CodeRhapsodie\IbexaDataflowBundle\Form\CreateScheduledType;
use CodeRhapsodie\IbexaDataflowBundle\Form\UpdateScheduledType;
use CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway;
use Ibexa\Contracts\AdminUi\Controller\Controller;
use Ibexa\Contracts\AdminUi\Notification\NotificationHandlerInterface;
use Ibexa\Core\MVC\Symfony\Security\Authorization\Attribute;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @Route("/ezdataflow/scheduled_workflow")
*/
#[Route(path: '/ibexa_dataflow/scheduled_workflow')]
class ScheduledDataflowController extends Controller
{
/** @var \Ibexa\Contracts\AdminUi\Notification\NotificationHandlerInterface */
private $notificationHandler;
/** @var \CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway */
private $scheduledDataflowGateway;
/** @var \Symfony\Contracts\Translation\TranslatorInterface */
private $translator;
public function __construct(
NotificationHandlerInterface $notificationHandler,
ScheduledDataflowGateway $scheduledDataflowGateway,
TranslatorInterface $translator
) {
$this->notificationHandler = $notificationHandler;
$this->scheduledDataflowGateway = $scheduledDataflowGateway;
$this->translator = $translator;
public function __construct(private readonly NotificationHandlerInterface $notificationHandler, private readonly ScheduledDataflowGateway $scheduledDataflowGateway, private readonly TranslatorInterface $translator)
{
}
/**
* @Route("/create", name="coderhapsodie.ezdataflow.workflow.create", methods={"POST"})
*/
#[Route(path: '/create', name: 'coderhapsodie.ibexa_dataflow.workflow.create', methods: ['POST'])]
public function create(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'edit'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'edit'));
$newWorkflow = new ScheduledDataflow();
$form = $this->createForm(CreateScheduledType::class, $newWorkflow);
@@ -55,48 +38,44 @@ class ScheduledDataflowController extends Controller
$newWorkflow = $form->getData();
try {
$this->scheduledDataflowGateway->save($newWorkflow);
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ezdataflow.workflow.create.success'));
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ibexa_dataflow.workflow.create.success'));
} catch (\Exception $e) {
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.workflow.create.error',
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ibexa_dataflow.workflow.create.error',
['message' => $e->getMessage()]));
}
return new JsonResponse(['redirect' => $this->generateUrl('coderhapsodie.ezdataflow.main')]);
return new JsonResponse(['redirect' => $this->generateUrl('coderhapsodie.ibexa_dataflow.main', ['_fragment' => 'ibexa-tab-coderhapsodie-ibexa_dataflow-code-rhapsodie-ibexa_dataflow-repeating'])]);
}
return new JsonResponse([
'form' => $this->renderView('@ibexadesign/ezdataflow/parts/form_modal.html.twig', [
'form' => $this->renderView('@ibexadesign/ibexa_dataflow/parts/form_modal.html.twig', [
'form' => $form->createView(),
'type_action' => 'new',
]),
]);
}
/**
* @Route("/{id}/delete", name="coderhapsodie.ezdataflow.workflow.delete", methods={"post"})
*/
#[Route(path: '/{id}/delete', name: 'coderhapsodie.ibexa_dataflow.workflow.delete', methods: ['post'])]
public function delete(int $id): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'edit'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'edit'));
try {
$this->scheduledDataflowGateway->delete($id);
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ezdataflow.workflow.delete.success'));
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ibexa_dataflow.workflow.delete.success'));
} catch (\Exception $e) {
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.workflow.delete.error',
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ibexa_dataflow.workflow.delete.error',
['message' => $e->getMessage()]));
}
return $this->redirectToRoute('coderhapsodie.ezdataflow.main');
return $this->redirectToRoute('coderhapsodie.ibexa_dataflow.main', ['_fragment' => 'ibexa-tab-coderhapsodie-ibexa_dataflow-code-rhapsodie-ibexa_dataflow-repeating']);
}
/**
* @Route("/{id}/edit", name="coderhapsodie.ezdataflow.workflow.edit")
*/
#[Route(path: '/{id}/edit', name: 'coderhapsodie.ibexa_dataflow.workflow.edit')]
public function edit(Request $request, int $id): Response
{
$form = $this->createForm(UpdateScheduledType::class, $this->scheduledDataflowGateway->find($id), [
'action' => $this->generateUrl('coderhapsodie.ezdataflow.workflow.edit', ['id' => $id]),
'action' => $this->generateUrl('coderhapsodie.ibexa_dataflow.workflow.edit', ['id' => $id]),
]);
$form->handleRequest($request);
@@ -106,33 +85,31 @@ class ScheduledDataflowController extends Controller
try {
$this->scheduledDataflowGateway->save($editDataflow);
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ezdataflow.workflow.edit.success'));
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ibexa_dataflow.workflow.edit.success'));
} catch (\Exception $e) {
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.workflow.edit.error',
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ibexa_dataflow.workflow.edit.error',
['message' => $e->getMessage()]));
}
return new JsonResponse(['redirect' => $this->generateUrl('coderhapsodie.ezdataflow.main')]);
return new JsonResponse(['redirect' => $this->generateUrl('coderhapsodie.ibexa_dataflow.main', ['_fragment' => 'ibexa-tab-coderhapsodie-ibexa_dataflow-code-rhapsodie-ibexa_dataflow-repeating'])]);
}
return new JsonResponse([
'form' => $this->renderView('@ibexadesign/ezdataflow/parts/form_modal.html.twig', [
'form' => $this->renderView('@ibexadesign/ibexa_dataflow/parts/form_modal.html.twig', [
'form' => $form->createView(),
'type_action' => 'edit',
]),
]);
}
/**
* @Route("/{id}/enable", name="coderhapsodie.ezdataflow.workflow.enable")
*/
#[Route(path: '/{id}/enable', name: 'coderhapsodie.ibexa_dataflow.workflow.enable')]
public function enableDataflow(int $id): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'edit'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'edit'));
$this->changeDataflowStatus($id, true);
return $this->redirectToRoute('coderhapsodie.ezdataflow.main');
return $this->redirectToRoute('coderhapsodie.ibexa_dataflow.main', ['_fragment' => 'ibexa-tab-coderhapsodie-ibexa_dataflow-code-rhapsodie-ibexa_dataflow-repeating']);
}
private function changeDataflowStatus(int $id, bool $status)
@@ -149,15 +126,13 @@ class ScheduledDataflowController extends Controller
}
}
/**
* @Route("/{id}/disable", name="coderhapsodie.ezdataflow.workflow.disable")
*/
#[Route(path: '/{id}/disable', name: 'coderhapsodie.ibexa_dataflow.workflow.disable')]
public function disableDataflow(int $id): Response
{
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'edit'));
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'edit'));
$this->changeDataflowStatus($id, false);
return $this->redirectToRoute('coderhapsodie.ezdataflow.main');
return $this->redirectToRoute('coderhapsodie.ibexa_dataflow.main', ['_fragment' => 'ibexa-tab-coderhapsodie-ibexa_dataflow-code-rhapsodie-ibexa_dataflow-repeating']);
}
}

View File

@@ -2,36 +2,21 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\Content;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\Content;
use CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFillerInterface;
use CodeRhapsodie\EzDataflowBundle\Matcher\LocationMatcherInterface;
use CodeRhapsodie\EzDataflowBundle\Model\ContentCreateStructure;
use CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFillerInterface;
use CodeRhapsodie\IbexaDataflowBundle\Matcher\LocationMatcherInterface;
use CodeRhapsodie\IbexaDataflowBundle\Model\ContentCreateStructure;
use Ibexa\Contracts\Core\Repository\ContentService;
use Ibexa\Contracts\Core\Repository\ContentTypeService;
use Ibexa\Contracts\Core\Repository\Repository;
use Ibexa\Contracts\Core\Repository\Values\Content\Content;
use Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct;
class ContentCreator implements ContentCreatorInterface
readonly class ContentCreator implements ContentCreatorInterface
{
/** @var \Ibexa\Contracts\Core\Repository\ContentService */
private $contentService;
/** @var \Ibexa\Contracts\Core\Repository\ContentTypeService */
private $contentTypeService;
/** @var \CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFillerInterface */
private $filler;
/** @var \CodeRhapsodie\EzDataflowBundle\Matcher\LocationMatcherInterface */
private $matcher;
public function __construct(ContentService $contentService, ContentTypeService $contentTypeService, ContentStructFieldFillerInterface $filler, LocationMatcherInterface $matcher)
public function __construct(private ContentService $contentService, private ContentTypeService $contentTypeService, private ContentStructFieldFillerInterface $filler, private LocationMatcherInterface $matcher, private Repository $repository)
{
$this->contentService = $contentService;
$this->contentTypeService = $contentTypeService;
$this->filler = $filler;
$this->matcher = $matcher;
}
/**
@@ -48,9 +33,20 @@ class ContentCreator implements ContentCreatorInterface
$contentCreateStruct = $this->contentService->newContentCreateStruct($contentType, $structure->getLanguageCode());
$contentCreateStruct->remoteId = $structure->getRemoteId();
$this->filler->fillFields($contentType, $contentCreateStruct, $structure->getFields());
$content = $this->contentService->createContent($contentCreateStruct, $this->getLocationCreateStructs($structure->getLocations()));
return $this->contentService->publishVersion($content->versionInfo);
$this->repository->beginTransaction();
try {
$content = $this->contentService->createContent($contentCreateStruct, $this->getLocationCreateStructs($structure->getLocations()));
$content = $this->contentService->publishVersion($content->versionInfo);
$this->repository->commit();
return $content;
} catch (\Exception $exception) {
$this->repository->rollback();
throw $exception;
}
}
/**

View File

@@ -2,9 +2,9 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\Content;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\Content;
use CodeRhapsodie\EzDataflowBundle\Model\ContentCreateStructure;
use CodeRhapsodie\IbexaDataflowBundle\Model\ContentCreateStructure;
use Ibexa\Contracts\Core\Repository\Values\Content\Content;
interface ContentCreatorInterface

View File

@@ -2,35 +2,24 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\Content;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\Content;
use CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFillerInterface;
use CodeRhapsodie\EzDataflowBundle\Exception\NoMatchFoundException;
use CodeRhapsodie\EzDataflowBundle\Model\ContentUpdateStructure;
use CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFillerInterface;
use CodeRhapsodie\IbexaDataflowBundle\Exception\NoMatchFoundException;
use CodeRhapsodie\IbexaDataflowBundle\Model\ContentUpdateStructure;
use Ibexa\Contracts\Core\Repository\ContentService;
use Ibexa\Contracts\Core\Repository\ContentTypeService;
use Ibexa\Contracts\Core\Repository\Repository;
use Ibexa\Contracts\Core\Repository\Values\Content\Content;
class ContentUpdater implements ContentUpdaterInterface
readonly class ContentUpdater implements ContentUpdaterInterface
{
/** @var \Ibexa\Contracts\Core\Repository\ContentService */
private $contentService;
/** @var \Ibexa\Contracts\Core\Repository\ContentTypeService */
private $contentTypeService;
/** @var \CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFillerInterface */
private $filler;
public function __construct(ContentService $contentService, ContentTypeService $contentTypeService, ContentStructFieldFillerInterface $filler)
public function __construct(private ContentService $contentService, private ContentTypeService $contentTypeService, private ContentStructFieldFillerInterface $filler, private Repository $repository)
{
$this->contentService = $contentService;
$this->contentTypeService = $contentTypeService;
$this->filler = $filler;
}
/**
* @throws \CodeRhapsodie\EzDataflowBundle\Exception\NoMatchFoundException
* @throws \CodeRhapsodie\IbexaDataflowBundle\Exception\NoMatchFoundException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException
@@ -56,9 +45,18 @@ class ContentUpdater implements ContentUpdaterInterface
$structure->getFields()
);
$draft = $this->contentService->createContentDraft($content->contentInfo);
$this->contentService->updateContent($draft->versionInfo, $contentUpdateStruct);
$this->repository->beginTransaction();
try {
$draft = $this->contentService->createContentDraft($content->contentInfo);
$this->contentService->updateContent($draft->versionInfo, $contentUpdateStruct);
$content = $this->contentService->publishVersion($draft->versionInfo);
return $this->contentService->publishVersion($draft->versionInfo);
$this->repository->commit();
return $content;
} catch (\Exception $e) {
$this->repository->rollback();
throw $e;
}
}
}

View File

@@ -2,9 +2,9 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\Content;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\Content;
use CodeRhapsodie\EzDataflowBundle\Model\ContentUpdateStructure;
use CodeRhapsodie\IbexaDataflowBundle\Model\ContentUpdateStructure;
use Ibexa\Contracts\Core\Repository\Values\Content\Content;
interface ContentUpdaterInterface

View File

@@ -2,32 +2,31 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\Field;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\Field;
use CodeRhapsodie\EzDataflowBundle\Exception\UnknownFieldException;
use CodeRhapsodie\EzDataflowBundle\Exception\UnsupportedFieldTypeException;
use CodeRhapsodie\IbexaDataflowBundle\Exception\UnknownFieldException;
use CodeRhapsodie\IbexaDataflowBundle\Exception\UnsupportedFieldTypeException;
use Ibexa\Contracts\Core\FieldType\Value;
use Ibexa\Contracts\Core\Repository\Values\Content\ContentStruct;
use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType;
class ContentStructFieldFiller implements ContentStructFieldFillerInterface
{
/** @var FieldValueCreatorInterface[] */
private $fieldValueCreators;
/**
* ContentStructFieldFiller constructor.
*/
public function __construct(iterable $fieldValueCreators)
public function __construct(
/** @var FieldValueCreatorInterface[] */
private readonly iterable $fieldValueCreators
)
{
$this->fieldValueCreators = $fieldValueCreators;
}
/**
* {@inheritdoc}
*
* @throws \CodeRhapsodie\EzDataflowBundle\Exception\UnknownFieldException
* @throws \CodeRhapsodie\EzDataflowBundle\Exception\UnsupportedFieldTypeException
* @throws \CodeRhapsodie\IbexaDataflowBundle\Exception\UnknownFieldException
* @throws \CodeRhapsodie\IbexaDataflowBundle\Exception\UnsupportedFieldTypeException
*/
public function fillFields(ContentType $contentType, ContentStruct $contentStruct, array $fieldHashes): void
{
@@ -47,7 +46,7 @@ class ContentStructFieldFiller implements ContentStructFieldFillerInterface
/**
* @param mixed $hash
*
* @throws \CodeRhapsodie\EzDataflowBundle\Exception\UnsupportedFieldTypeException
* @throws \CodeRhapsodie\IbexaDataflowBundle\Exception\UnsupportedFieldTypeException
*/
private function createFieldValue(string $fieldTypeIdentifier, $hash): Value
{

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\Field;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\Field;
use Ibexa\Contracts\Core\Repository\Values\Content\ContentStruct;
use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType;

View File

@@ -2,19 +2,15 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\Field;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\Field;
use Ibexa\Contracts\Core\FieldType\Value;
use Ibexa\Contracts\Core\Repository\FieldTypeService;
class DefaultFieldValueCreator implements FieldValueCreatorInterface
{
/** @var \Ibexa\Contracts\Core\Repository\FieldTypeService */
private $fieldTypeService;
public function __construct(FieldTypeService $fieldTypeService)
public function __construct(private readonly FieldTypeService $fieldTypeService)
{
$this->fieldTypeService = $fieldTypeService;
}
public function supports(string $fieldTypeIdentifier): bool

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\Field;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\Field;
use Ibexa\Contracts\Core\FieldType\Value;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;
use Ibexa\Contracts\Core\Repository\FieldTypeService;
@@ -10,12 +10,8 @@ use Ibexa\Contracts\Core\Repository\Values\Content\Field;
abstract class AbstractFieldComparator implements FieldComparatorInterface
{
/** @var \Ibexa\Contracts\Core\Repository\FieldTypeService */
private $fieldTypeService;
public function __construct(FieldTypeService $fieldTypeService)
public function __construct(private readonly FieldTypeService $fieldTypeService)
{
$this->fieldTypeService = $fieldTypeService;
}
public function compare(Field $field, $hash): bool

View File

@@ -0,0 +1,18 @@
<?php
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;
class BillingAddressComparator extends AbstractFieldComparator
{
/**
* @param \Ibexa\FieldTypeAddress\FieldType\Value $currentValue
* @param \Ibexa\FieldTypeAddress\FieldType\Value $newValue
*/
protected function compareValues(Value $currentValue, Value $newValue): bool
{
return empty(array_diff_assoc($currentValue->fields, $newValue->fields)) && $currentValue->name === $newValue->name && $currentValue->country === $newValue->country;
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;
class CustomerGroupComparator extends AbstractFieldComparator
{
/**
* @param \Ibexa\ProductCatalog\FieldType\CustomerGroup\Value $currentValue
* @param \Ibexa\ProductCatalog\FieldType\CustomerGroup\Value $newValue
*/
protected function compareValues(Value $currentValue, Value $newValue): bool
{
return $currentValue->getCustomerGroup()->getIdentifier() === $newValue->getCustomerGroup()->getIdentifier();
}
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\Repository\Values\Content\Field;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\Repository\Values\Content\Field;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;
class ProductSpecificationComparator extends AbstractFieldComparator
{
protected function compareValues(Value $currentValue, Value $newValue): bool
{
$currentAttributes = $currentValue->getAttributes();
$newAttributes = $newValue->getAttributes();
if ($newValue->isCodeChanged() || $currentValue->isVirtual() !== $newValue->isVirtual() || \count($currentAttributes) !== \count($newAttributes)) {
return false;
}
sort($currentAttributes);
sort($newAttributes);
return $currentAttributes === $newAttributes;
}
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;

View File

@@ -0,0 +1,44 @@
<?php
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;
use Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry;
class TaxonomyEntryAssignmentComparator extends AbstractFieldComparator
{
/**
* @param \Ibexa\Taxonomy\FieldType\TaxonomyEntryAssignment\Value $currentValue
* @param \Ibexa\Taxonomy\FieldType\TaxonomyEntryAssignment\Value $newValue
*/
protected function compareValues(Value $currentValue, Value $newValue): bool
{
return $currentValue->getTaxonomy() === $newValue->getTaxonomy() && $this->compareEntries($currentValue->getTaxonomyEntries(), $newValue->getTaxonomyEntries());
}
/**
* @param array<TaxonomyEntry> $currentEntries
* @param array<TaxonomyEntry> $newEntries
*/
private function compareEntries(array $currentEntries, array $newEntries): bool
{
$currentEntriesId = array_map(function (TaxonomyEntry $currentEntry) {
return $currentEntry->id;
}, $currentEntries);
$newEntriesId = array_map(function (TaxonomyEntry $newEntry) {
return $newEntry->id;
}, $newEntries);
if (\count($currentEntriesId) !== \count($newEntriesId)) {
return false;
}
sort($currentEntriesId);
sort($newEntriesId);
return $currentEntriesId === $newEntriesId;
}
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
namespace CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator;
use Ibexa\Contracts\Core\FieldType\Value;

View File

@@ -2,29 +2,29 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\DependencyInjection;
namespace CodeRhapsodie\IbexaDataflowBundle\DependencyInjection;
use CodeRhapsodie\EzDataflowBundle\Core\Field\FieldValueCreatorInterface;
use CodeRhapsodie\IbexaDataflowBundle\Core\Field\FieldValueCreatorInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
class CodeRhapsodieEzDataflowExtension extends Extension
class CodeRhapsodieIbexaDataflowExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
public function load(array $configs, ContainerBuilder $container): void
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$container->setParameter('coderhapsodie.ezdataflow.admin_login_or_id', $config['admin_login_or_id']);
$container->setParameter('coderhapsodie.ibexa_dataflow.admin_login_or_id', $config['admin_login_or_id']);
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yaml');
$container
->registerForAutoconfiguration(FieldValueCreatorInterface::class)
->addTag('coderhapsodie.ezdataflow.field_value_creator')
->addTag('coderhapsodie.ibexa_dataflow.field_value_creator')
;
}
}

View File

@@ -2,16 +2,16 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\DependencyInjection\Compiler;
namespace CodeRhapsodie\IbexaDataflowBundle\DependencyInjection\Compiler;
use CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\DelegatorFieldComparator;
use CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\DelegatorFieldComparator;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class FieldComparatorCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
public function process(ContainerBuilder $container): void
{
if (!$container->has(DelegatorFieldComparator::class)) {
return;
@@ -19,10 +19,10 @@ class FieldComparatorCompilerPass implements CompilerPassInterface
$delegatorDef = $container->findDefinition(DelegatorFieldComparator::class);
foreach ($container->findTaggedServiceIds('coderhapsodie.ezdataflow.field_comparator') as $id => $tags) {
foreach ($container->findTaggedServiceIds('coderhapsodie.ibexa_dataflow.field_comparator') as $id => $tags) {
foreach ($tags as $attributes) {
if (!isset($attributes['fieldType'])) {
throw new \InvalidArgumentException(sprintf('Service "%s" must define the "fieldType" attribute on "coderhapsodie.ezdataflow.field_comparator" tags.', $id));
throw new \InvalidArgumentException(sprintf('Service "%s" must define the "fieldType" attribute on "coderhapsodie.ibexa_dataflow.field_comparator" tags.', $id));
}
$delegatorDef->addMethodCall(

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\DependencyInjection;
namespace CodeRhapsodie\IbexaDataflowBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
@@ -12,9 +12,9 @@ class Configuration implements ConfigurationInterface
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('code_rhapsodie_ez_dataflow');
$treeBuilder = new TreeBuilder('code_rhapsodie_ibexa_dataflow');
$rootNode = $treeBuilder->getRootNode();
$rootNode

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\EventSubscriber;
namespace CodeRhapsodie\IbexaDataflowBundle\EventSubscriber;
use Ibexa\AdminUi\Menu\Event\ConfigureMenuEvent;
use Ibexa\AdminUi\Menu\MainMenuBuilder;
@@ -13,12 +13,12 @@ class MenuSubscriber implements EventSubscriberInterface
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
public static function getSubscribedEvents(): array
{
return [ConfigureMenuEvent::MAIN_MENU => 'onConfigureMenu'];
}
public function onConfigureMenu(ConfigureMenuEvent $event)
public function onConfigureMenu(ConfigureMenuEvent $event): void
{
/** @var \Knp\Menu\ItemInterface $menu */
$menu = $event->getMenu();
@@ -27,10 +27,10 @@ class MenuSubscriber implements EventSubscriberInterface
}
$menu[MainMenuBuilder::ITEM_ADMIN]->addChild(
'ezdataflow_dashboard',
'ibexa_dataflow_dashboard',
[
'label' => 'coderhapsodie.ezdataflow',
'route' => 'coderhapsodie.ezdataflow.main',
'label' => 'coderhapsodie.ibexa_dataflow',
'route' => 'coderhapsodie.ibexa_dataflow.main',
]
);
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Exception;
namespace CodeRhapsodie\IbexaDataflowBundle\Exception;
class InvalidArgumentTypeException extends \Exception
{
@@ -26,7 +26,7 @@ class InvalidArgumentTypeException extends \Exception
return new self(sprintf(
'Expected argument of type %s, %s received instead',
$expectedString,
is_object($received) ? get_class($received) : gettype($received)
get_debug_type($received)
));
}
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Exception;
namespace CodeRhapsodie\IbexaDataflowBundle\Exception;
class NoMatchFoundException extends \Exception
{

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Exception;
namespace CodeRhapsodie\IbexaDataflowBundle\Exception;
class UnknownFieldException extends \Exception
{

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Exception;
namespace CodeRhapsodie\IbexaDataflowBundle\Exception;
class UnsupportedFieldTypeException extends \Exception
{

View File

@@ -2,35 +2,26 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Factory;
namespace CodeRhapsodie\IbexaDataflowBundle\Factory;
use CodeRhapsodie\EzDataflowBundle\Model\ContentCreateStructure;
use CodeRhapsodie\EzDataflowBundle\Model\ContentUpdateStructure;
use CodeRhapsodie\IbexaDataflowBundle\Model\ContentCreateStructure;
use CodeRhapsodie\IbexaDataflowBundle\Model\ContentUpdateStructure;
use Ibexa\Contracts\Core\Repository\ContentService;
use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException;
final class ContentStructureFactory implements ContentStructureFactoryInterface
final readonly class ContentStructureFactory implements ContentStructureFactoryInterface
{
/**
* @var \Ibexa\Contracts\Core\Repository\ContentService
*/
private $contentService;
/**
* ContentStructureFactory constructor.
*/
public function __construct(ContentService $contentService)
public function __construct(private ContentService $contentService)
{
$this->contentService = $contentService;
}
/**
* @param mixed $parentLocations
* @param int $mode One of the constant ContentStructureFactoryInterface::MODE_*
*
* @return false|\CodeRhapsodie\EzDataflowBundle\Model\ContentStructure
* @return false|\CodeRhapsodie\IbexaDataflowBundle\Model\ContentStructure
*
* @throws \CodeRhapsodie\EzDataflowBundle\Exception\InvalidArgumentTypeException
* @throws \CodeRhapsodie\IbexaDataflowBundle\Exception\InvalidArgumentTypeException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
*/
public function transform(array $data, string $remoteId, string $language, string $contentType, $parentLocations, int $mode = ContentStructureFactoryInterface::MODE_INSERT_OR_UPDATE)
@@ -42,7 +33,7 @@ final class ContentStructureFactory implements ContentStructureFactoryInterface
}
return ContentUpdateStructure::createForContentId($content->id, $language, $data);
} catch (NotFoundException $e) {
} catch (NotFoundException) {
// The content doesn't exist yet, so it will be created.
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Factory;
namespace CodeRhapsodie\IbexaDataflowBundle\Factory;
interface ContentStructureFactoryInterface
{
@@ -14,7 +14,7 @@ interface ContentStructureFactoryInterface
* @param int|string $parentLocations Int for location id or string for remote location id
* @param int $mode ContentStructureFactoryInterface
*
* @return false|\CodeRhapsodie\EzDataflowBundle\Model\ContentStructure
* @return false|\CodeRhapsodie\IbexaDataflowBundle\Model\ContentStructure
*/
public function transform(array $data, string $remoteId, string $language, string $contentType, $parentLocations, int $mode = ContentStructureFactoryInterface::MODE_INSERT_OR_UPDATE);
}

View File

@@ -2,10 +2,10 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Filter;
namespace CodeRhapsodie\IbexaDataflowBundle\Filter;
use CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface;
use CodeRhapsodie\EzDataflowBundle\Model\ContentUpdateStructure;
use CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\FieldComparatorInterface;
use CodeRhapsodie\IbexaDataflowBundle\Model\ContentUpdateStructure;
use Ibexa\Contracts\Core\Repository\ContentService;
use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException;
use Psr\Log\LoggerAwareTrait;
@@ -17,16 +17,8 @@ class NotModifiedContentFilter
{
use LoggerAwareTrait;
/** @var \Ibexa\Contracts\Core\Repository\ContentService */
private $contentService;
/** @var \CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface */
private $comparator;
public function __construct(ContentService $contentService, FieldComparatorInterface $comparator)
public function __construct(private ContentService $contentService, private FieldComparatorInterface $comparator)
{
$this->contentService = $contentService;
$this->comparator = $comparator;
}
public function __invoke($data)
@@ -40,7 +32,7 @@ class NotModifiedContentFilter
} else {
try {
$content = $this->contentService->loadContentByRemoteId($data->getRemoteId(), [$data->getLanguageCode()]);
} catch (NotFoundException $e) {
} catch (NotFoundException) {
// New translation
return $data;
}
@@ -60,7 +52,7 @@ class NotModifiedContentFilter
return false;
}
private function log(string $level, string $message, array $context = [])
private function log(string $level, string $message, array $context = []): void
{
if (null === $this->logger) {
return;

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace CodeRhapsodie\IbexaDataflowBundle\Filter;
use CodeRhapsodie\IbexaDataflowBundle\Model\ContentUpdateStructure;
use CodeRhapsodie\IbexaDataflowBundle\Model\ProductUpdateStructure;
use Doctrine\DBAL\Connection;
readonly class NotModifiedProductFilter
{
public function __construct(private NotModifiedContentFilter $notModifiedContentFilter, private Connection $connection)
{
}
public function __invoke(mixed $data)
{
if (!$data instanceof ProductUpdateStructure) {
return $data;
}
$contentId = $this->connection->executeQuery('SELECT content_id FROM ibexa_product_specification where code = :code', ['code' => $data->getCode()])
->fetchFirstColumn();
if (empty($contentId)) {
return $data;
}
$result = $this->notModifiedContentFilter->__invoke(ContentUpdateStructure::createForContentId($contentId[0], $data->getLanguageCode(), $data->getFields()));
if ($result === false) {
$data->setUpdateContent(false);
}
$stockData = $this->connection->executeQuery('SELECT stock FROM ibexa_product_specification_availability WHERE product_code = :code', ['code' => $data->getCode()])->fetchFirstColumn();
if (!empty($stockData) && ($data->getStock() === $stockData[0] || ($data->getStock() === 0 && $stockData[0] === null))) {
$data->setUpdateStock(false);
}
return $data;
}
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Form;
namespace CodeRhapsodie\IbexaDataflowBundle\Form;
use CodeRhapsodie\DataflowBundle\Entity\Job;
use Symfony\Component\Form\AbstractType;
@@ -12,7 +12,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class CreateOneshotType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('label', TextType::class, [
@@ -35,7 +35,7 @@ class CreateOneshotType extends AbstractType
;
}
public function configureOptions(OptionsResolver $resolver)
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Job::class,

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Form;
namespace CodeRhapsodie\IbexaDataflowBundle\Form;
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
use Symfony\Component\Form\AbstractType;
@@ -13,7 +13,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class CreateScheduledType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('label', TextType::class, [
@@ -47,7 +47,7 @@ class CreateScheduledType extends AbstractType
;
}
public function configureOptions(OptionsResolver $resolver)
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ScheduledDataflow::class,

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Form;
namespace CodeRhapsodie\IbexaDataflowBundle\Form;
use CodeRhapsodie\DataflowBundle\Registry\DataflowTypeRegistryInterface;
use Symfony\Component\Form\AbstractType;
@@ -11,20 +11,17 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class DataflowTypeChoiceType extends AbstractType
{
/** @var \CodeRhapsodie\DataflowBundle\Registry\DataflowTypeRegistryInterface */
private $registry;
public function __construct(DataflowTypeRegistryInterface $registry)
public function __construct(private readonly DataflowTypeRegistryInterface $registry)
{
$this->registry = $registry;
}
public function getParent()
#[\Override]
public function getParent(): string
{
return ChoiceType::class;
}
public function configureOptions(OptionsResolver $resolver)
public function configureOptions(OptionsResolver $resolver): void
{
$choices = [];
foreach ($this->registry->listDataflowTypes() as $fqcn => $dataflowType) {

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Form;
namespace CodeRhapsodie\IbexaDataflowBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
@@ -12,12 +12,14 @@ use Symfony\Component\Form\Extension\Core\Type\TextType;
*/
class FrequencyType extends AbstractType
{
public function getParent()
#[\Override]
public function getParent(): string
{
return TextType::class;
}
public function getBlockPrefix()
#[\Override]
public function getBlockPrefix(): string
{
return 'coderhapsodie_port_frequency';
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Form;
namespace CodeRhapsodie\IbexaDataflowBundle\Form;
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
use Symfony\Component\Form\AbstractType;
@@ -12,7 +12,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class UpdateScheduledType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('label', TextType::class, [
@@ -37,7 +37,7 @@ class UpdateScheduledType extends AbstractType
;
}
public function configureOptions(OptionsResolver $resolver)
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ScheduledDataflow::class,

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Form;
namespace CodeRhapsodie\IbexaDataflowBundle\Form;
use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException;
use Ibexa\Contracts\Core\Repository\UserPreferenceService;
@@ -10,15 +10,11 @@ use Symfony\Component\Form\DataTransformerInterface;
class UserTimezoneAwareDateTimeTransformer implements DataTransformerInterface
{
/** @var \Ibexa\Contracts\Core\Repository\UserPreferenceService */
private $userPreferenceService;
public function __construct(UserPreferenceService $userPreferenceService)
public function __construct(private readonly UserPreferenceService $userPreferenceService)
{
$this->userPreferenceService = $userPreferenceService;
}
public function transform($value)
public function transform($value): mixed
{
if (!$value instanceof \DateTimeInterface) {
return $value;
@@ -27,7 +23,7 @@ class UserTimezoneAwareDateTimeTransformer implements DataTransformerInterface
return (new \DateTime('now', $this->userTimezone()))->setTimestamp($value->getTimestamp());
}
public function reverseTransform($value)
public function reverseTransform($value): mixed
{
if (!$value instanceof \DateTimeInterface) {
return $value;
@@ -42,7 +38,7 @@ class UserTimezoneAwareDateTimeTransformer implements DataTransformerInterface
{
try {
$tz = $this->userPreferenceService->getUserPreference('timezone')->value ?? 'UTC';
} catch (NotFoundException $e) {
} catch (NotFoundException) {
$tz = 'UTC';
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Form;
namespace CodeRhapsodie\IbexaDataflowBundle\Form;
use Ibexa\AdminUi\Form\Type\DateTimePickerType;
use Ibexa\Contracts\Core\Repository\UserPreferenceService;
@@ -11,20 +11,17 @@ use Symfony\Component\Form\FormBuilderInterface;
class UserTimezoneAwareDateTimeType extends AbstractType
{
/** @var \Ibexa\Contracts\Core\Repository\UserPreferenceService */
private $userPreferenceService;
public function __construct(UserPreferenceService $userPreferenceService)
public function __construct(private readonly UserPreferenceService $userPreferenceService)
{
$this->userPreferenceService = $userPreferenceService;
}
public function getParent()
#[\Override]
public function getParent(): string
{
return DateTimePickerType::class;
}
public function buildForm(FormBuilderInterface $builder, array $options)
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addModelTransformer(new UserTimezoneAwareDateTimeTransformer($this->userPreferenceService));
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Form;
namespace CodeRhapsodie\IbexaDataflowBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
@@ -17,12 +17,13 @@ use Symfony\Component\Yaml\Yaml;
*/
class YamlType extends AbstractType
{
public function getParent()
#[\Override]
public function getParent(): string
{
return TextareaType::class;
}
public function buildForm(FormBuilderInterface $builder, array $options)
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addModelTransformer(new CallbackTransformer(
function ($optionsAsArray) {
@@ -51,7 +52,8 @@ class YamlType extends AbstractType
));
}
public function getBlockPrefix()
#[\Override]
public function getBlockPrefix(): string
{
return 'coderhapsodie_port_yaml';
}

View File

@@ -2,31 +2,27 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Gateway;
namespace CodeRhapsodie\IbexaDataflowBundle\Gateway;
use Pagerfanta\Adapter\AdapterInterface;
class ExceptionJSONDecoderAdapter implements AdapterInterface
{
/** @var AdapterInterface */
private $adapter;
public function __construct(AdapterInterface $adapter)
public function __construct(private readonly AdapterInterface $adapter)
{
$this->adapter = $adapter;
}
public function getNbResults()
public function getNbResults(): int
{
return $this->adapter->getNbResults();
}
public function getSlice($offset, $length)
public function getSlice($offset, $length): iterable
{
$slice = $this->adapter->getSlice($offset, $length);
array_walk($slice, static function (&$value) {
array_walk($slice, static function (&$value): void {
if (isset($value['exceptions'])) {
$value['exceptions'] = json_decode($value['exceptions'], true, 512, JSON_THROW_ON_ERROR);
$value['exceptions'] = json_decode((string) $value['exceptions'], true, 512, JSON_THROW_ON_ERROR);
}
});

View File

@@ -2,28 +2,25 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Gateway;
namespace CodeRhapsodie\IbexaDataflowBundle\Gateway;
use CodeRhapsodie\DataflowBundle\Entity\Job;
use CodeRhapsodie\DataflowBundle\Gateway\JobGateway as JobGatewayDataflow;
use CodeRhapsodie\DataflowBundle\Repository\JobRepository;
use Doctrine\DBAL\Query\QueryBuilder;
final class JobGateway
final readonly class JobGateway
{
public const FILTER_NONE = 0;
public const FILTER_NON_EMPTY = 1;
public const int FILTER_NONE = 0;
public const int FILTER_NON_EMPTY = 1;
/** @var \CodeRhapsodie\DataflowBundle\Repository\JobRepository */
private $jobRepository;
public function __construct(JobRepository $jobRepository)
public function __construct(private JobRepository $jobRepository, private JobGatewayDataflow $jobGateway)
{
$this->jobRepository = $jobRepository;
}
public function find(int $id): ?Job
{
return $this->jobRepository->find($id);
return $this->jobGateway->find($id);
}
public function getOneshotListQueryForAdmin(): QueryBuilder
@@ -56,6 +53,14 @@ final class JobGateway
public function save(Job $job)
{
$this->jobRepository->save($job);
$this->jobGateway->save($job);
}
public function getListPendindOrRunning(): array
{
$qb = $this->jobRepository->createQueryBuilder('w');
return $qb->andWhere($qb->expr()->in('w.status', [Job::STATUS_RUNNING, Job::STATUS_PENDING, Job::STATUS_QUEUED]))
->orderBy('w.requested_date', 'ASC')
->fetchAllAssociative();
}
}

View File

@@ -2,20 +2,16 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Gateway;
namespace CodeRhapsodie\IbexaDataflowBundle\Gateway;
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
use CodeRhapsodie\DataflowBundle\Repository\ScheduledDataflowRepository;
use Doctrine\DBAL\Query\QueryBuilder;
final class ScheduledDataflowGateway
final readonly class ScheduledDataflowGateway
{
/** @var \CodeRhapsodie\DataflowBundle\Repository\ScheduledDataflowRepository */
private $scheduledDataflowRepository;
public function __construct(ScheduledDataflowRepository $scheduledDataflowRepository)
public function __construct(private ScheduledDataflowRepository $scheduledDataflowRepository)
{
$this->scheduledDataflowRepository = $scheduledDataflowRepository;
}
public function find(int $id): ?ScheduledDataflow

View File

@@ -0,0 +1,65 @@
<?php declare(strict_types=1);
namespace CodeRhapsodie\IbexaDataflowBundle\Gateway;
use Pagerfanta\Adapter\AdapterInterface;
/**
* Adapter which transforms the result of other adapter.
*
* @template T
* @template Transformed
*
* @implements AdapterInterface<Transformed>
*/
class TransformingAdapter implements AdapterInterface
{
/**
* @var AdapterInterface<T>
*/
private AdapterInterface $adapter;
/**
* @var callable
*
* @phpstan-var callable(T, array-key): Transformed
*/
private $transformer;
/**
* @param AdapterInterface<T> $adapter
*
* @phpstan-param callable(T, array-key): Transformed $transformer
*/
public function __construct(AdapterInterface $adapter, callable $transformer)
{
$this->adapter = $adapter;
$this->transformer = $transformer;
}
/**
* @phpstan-return int<0, max>
*/
public function getNbResults(): int
{
return $this->adapter->getNbResults();
}
/**
* @phpstan-param int<0, max> $offset
* @phpstan-param int<0, max> $length
*
* @return iterable<array-key, Transformed>
*/
public function getSlice(int $offset, int $length): iterable
{
$transformer = $this->transformer;
$data = [];
foreach ($this->adapter->getSlice($offset, $length) as $key => $item) {
$data[] = $transformer($item, $key);
}
return $data;
}
}

View File

@@ -2,27 +2,23 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Matcher;
namespace CodeRhapsodie\IbexaDataflowBundle\Matcher;
use CodeRhapsodie\EzDataflowBundle\Exception\NoMatchFoundException;
use CodeRhapsodie\IbexaDataflowBundle\Exception\NoMatchFoundException;
use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException;
use Ibexa\Contracts\Core\Repository\LocationService;
use Ibexa\Contracts\Core\Repository\Values\Content\Location;
class LocationMatcher implements LocationMatcherInterface
{
/** @var \Ibexa\Contracts\Core\Repository\LocationService */
private $locationService;
public function __construct(LocationService $locationService)
public function __construct(private readonly LocationService $locationService)
{
$this->locationService = $locationService;
}
/**
* @param mixed $valueToMatch
*
* @throws \CodeRhapsodie\EzDataflowBundle\Exception\NoMatchFoundException
* @throws \CodeRhapsodie\IbexaDataflowBundle\Exception\NoMatchFoundException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
*/
public function matchLocation($valueToMatch): Location

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Matcher;
namespace CodeRhapsodie\IbexaDataflowBundle\Matcher;
use Ibexa\Contracts\Core\Repository\Values\Content\Location;

View File

@@ -2,19 +2,15 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Model;
namespace CodeRhapsodie\IbexaDataflowBundle\Model;
use CodeRhapsodie\EzDataflowBundle\Exception\InvalidArgumentTypeException;
use CodeRhapsodie\IbexaDataflowBundle\Exception\InvalidArgumentTypeException;
use Ibexa\Contracts\Core\Repository\Values\Content\Location;
use Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct;
class ContentCreateStructure extends ContentStructure
{
/** @var string */
protected $contentTypeIdentifier;
/** @var array */
protected $locations;
protected array $locations;
/**
* ContentCreateStructure constructor.
@@ -28,11 +24,10 @@ class ContentCreateStructure extends ContentStructure
* <li>a LocationCreateStruct object</li>
* </ul>
*
* @throws \CodeRhapsodie\EzDataflowBundle\Exception\InvalidArgumentTypeException
* @throws \CodeRhapsodie\IbexaDataflowBundle\Exception\InvalidArgumentTypeException
*/
public function __construct(string $contentTypeIdentifier, string $languageCode, array $locations, array $fields, ?string $remoteId = null)
public function __construct(protected string $contentTypeIdentifier, string $languageCode, array $locations, array $fields, ?string $remoteId = null)
{
$this->contentTypeIdentifier = $contentTypeIdentifier;
$this->languageCode = $languageCode;
$this->setLocations($locations);
$this->fields = $fields;
@@ -50,9 +45,9 @@ class ContentCreateStructure extends ContentStructure
}
/**
* @throws \CodeRhapsodie\EzDataflowBundle\Exception\InvalidArgumentTypeException
* @throws \CodeRhapsodie\IbexaDataflowBundle\Exception\InvalidArgumentTypeException
*/
private function setLocations(array $locations)
private function setLocations(array $locations): void
{
foreach ($locations as $locationOrIdOrRemoteIdOrStruct) {
if (!is_int($locationOrIdOrRemoteIdOrStruct)

View File

@@ -2,18 +2,15 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Model;
namespace CodeRhapsodie\IbexaDataflowBundle\Model;
abstract class ContentStructure
{
/** @var string|null */
protected $remoteId;
protected ?string $remoteId = null;
/** @var string */
protected $languageCode;
protected string $languageCode;
/** @var array */
protected $fields;
protected array $fields;
public function getRemoteId(): ?string
{

View File

@@ -2,12 +2,11 @@
declare(strict_types=1);
namespace CodeRhapsodie\EzDataflowBundle\Model;
namespace CodeRhapsodie\IbexaDataflowBundle\Model;
class ContentUpdateStructure extends ContentStructure
{
/** @var int|null */
protected $id;
protected ?int $id = null;
private function __construct(string $languageCode, array $fields)
{

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace CodeRhapsodie\IbexaDataflowBundle\Model;
class ProductCreateStructure extends ProductStructure
{
public function __construct(string $code, array $fields, string $languageCode, int $stock = 0, array $attributes = [])
{
$this->code = $code;
$this->fields = $fields;
$this->languageCode = $languageCode;
$this->stock = $stock;
$this->attributes = $attributes;
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace CodeRhapsodie\IbexaDataflowBundle\Model;
abstract class ProductStructure
{
protected string $code;
protected array $fields;
protected string $languageCode;
protected int $stock;
protected array $attributes;
public function getCode(): string
{
return $this->code;
}
public function getFields(): array
{
return $this->fields;
}
public function getLanguageCode(): string
{
return $this->languageCode;
}
public function getStock(): int
{
return $this->stock;
}
public function getAttributes(): array
{
return $this->attributes;
}
}

View File

@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace CodeRhapsodie\IbexaDataflowBundle\Model;
class ProductUpdateStructure extends ProductStructure
{
protected bool $updateContent = true;
protected bool $updateStock = true;
public function __construct(string $code, array $fields, string $languageCode, int $stock = 0, array $attributes = [])
{
$this->code = $code;
$this->fields = $fields;
$this->languageCode = $languageCode;
$this->stock = $stock;
$this->attributes = $attributes;
}
public function isUpdateContent(): bool
{
return $this->updateContent;
}
public function isUpdateStock(): bool
{
return $this->updateStock;
}
public function setUpdateContent(bool $updateContent): void
{
$this->updateContent = $updateContent;
}
public function setUpdateStock(bool $updateStock): void
{
$this->updateStock = $updateStock;
}
}

View File

@@ -1,3 +1,3 @@
ezdataflow:
ibexa_dataflow:
view: ~
edit: ~

View File

@@ -1,3 +1,4 @@
coderhapsodie.ezdataflow.controllers:
coderhapsodie.ibexa_dataflow.controllers:
resource: '../../Controller/'
type: annotation
type: attribute

View File

@@ -4,174 +4,178 @@ imports:
services:
_defaults:
public: false
autowire: true
autoconfigure: true
coderhapsodie.dataflow.connection: "@ibexa.persistence.connection"
CodeRhapsodie\EzDataflowBundle\Controller\DashboardController:
CodeRhapsodie\IbexaDataflowBundle\Controller\DashboardController:
public: true
tags:
- { name: controller.service_arguments }
arguments:
$jobGateway: '@CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway'
$scheduledDataflowGateway: '@CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway'
calls:
- ['setContainer', ['@service_container']]
- ['performAccessCheck', []]
$jobGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\JobGateway'
$scheduledDataflowGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway'
$exceptionHandler: '@CodeRhapsodie\DataflowBundle\ExceptionsHandler\ExceptionHandlerInterface'
CodeRhapsodie\EzDataflowBundle\Controller\ScheduledDataflowController:
CodeRhapsodie\IbexaDataflowBundle\Controller\ScheduledDataflowController:
public: true
tags:
- { name: controller.service_arguments }
arguments:
$notificationHandler: '@Ibexa\Contracts\AdminUi\Notification\NotificationHandlerInterface'
$scheduledDataflowGateway: '@CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway'
$scheduledDataflowGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway'
$translator: '@translator'
calls:
- [ 'setContainer', [ '@service_container' ] ]
- [ 'performAccessCheck', [ ] ]
CodeRhapsodie\EzDataflowBundle\Controller\JobController:
CodeRhapsodie\IbexaDataflowBundle\Controller\JobController:
public: true
tags:
- { name: controller.service_arguments }
arguments:
$jobGateway: '@CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway'
$jobGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\JobGateway'
$notificationHandler: '@Ibexa\Contracts\AdminUi\Notification\NotificationHandlerInterface'
$translator: '@translator'
calls:
- [ 'setContainer', [ '@service_container' ] ]
- [ 'performAccessCheck', [ ] ]
$scheduledDataflowGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway'
CodeRhapsodie\EzDataflowBundle\Writer\RepositoryWriter:
CodeRhapsodie\IbexaDataflowBundle\Writer\RepositoryWriter:
abstract: true
calls:
- ['setUserSwitcher', ['@CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcherInterface']]
- ['setUserSwitcher', ['@CodeRhapsodie\IbexaDataflowBundle\UserSwitcher\UserSwitcherInterface']]
CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter:
parent: 'CodeRhapsodie\EzDataflowBundle\Writer\RepositoryWriter'
CodeRhapsodie\IbexaDataflowBundle\Writer\ContentWriter:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Writer\RepositoryWriter'
public: false
arguments:
$creator: '@CodeRhapsodie\EzDataflowBundle\Core\Content\ContentCreatorInterface'
$updater: '@CodeRhapsodie\EzDataflowBundle\Core\Content\ContentUpdaterInterface'
$creator: '@CodeRhapsodie\IbexaDataflowBundle\Core\Content\ContentCreatorInterface'
$updater: '@CodeRhapsodie\IbexaDataflowBundle\Core\Content\ContentUpdaterInterface'
CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcherInterface: '@CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcher'
CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcher:
CodeRhapsodie\IbexaDataflowBundle\UserSwitcher\UserSwitcherInterface: '@CodeRhapsodie\IbexaDataflowBundle\UserSwitcher\UserSwitcher'
CodeRhapsodie\IbexaDataflowBundle\UserSwitcher\UserSwitcher:
arguments:
$permissionResolver: '@Ibexa\Contracts\Core\Repository\PermissionResolver'
$userService: '@Ibexa\Contracts\Core\Repository\UserService'
$adminLoginOrId: '%coderhapsodie.ezdataflow.admin_login_or_id%'
$adminLoginOrId: '%coderhapsodie.ibexa_dataflow.admin_login_or_id%'
CodeRhapsodie\EzDataflowBundle\Core\Content\ContentCreatorInterface: '@CodeRhapsodie\EzDataflowBundle\Core\Content\ContentCreator'
CodeRhapsodie\EzDataflowBundle\Core\Content\ContentCreator:
CodeRhapsodie\IbexaDataflowBundle\Core\Content\ContentCreatorInterface: '@CodeRhapsodie\IbexaDataflowBundle\Core\Content\ContentCreator'
CodeRhapsodie\IbexaDataflowBundle\Core\Content\ContentCreator:
arguments:
$contentService: '@Ibexa\Contracts\Core\Repository\ContentService'
$contentTypeService: '@Ibexa\Contracts\Core\Repository\ContentTypeService'
$filler: '@CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFillerInterface'
$matcher: '@CodeRhapsodie\EzDataflowBundle\Matcher\LocationMatcherInterface'
$filler: '@CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFillerInterface'
$matcher: '@CodeRhapsodie\IbexaDataflowBundle\Matcher\LocationMatcherInterface'
CodeRhapsodie\EzDataflowBundle\Core\Content\ContentUpdaterInterface: '@CodeRhapsodie\EzDataflowBundle\Core\Content\ContentUpdater'
CodeRhapsodie\EzDataflowBundle\Core\Content\ContentUpdater:
CodeRhapsodie\IbexaDataflowBundle\Core\Content\ContentUpdaterInterface: '@CodeRhapsodie\IbexaDataflowBundle\Core\Content\ContentUpdater'
CodeRhapsodie\IbexaDataflowBundle\Core\Content\ContentUpdater:
arguments:
$contentService: '@Ibexa\Contracts\Core\Repository\ContentService'
$contentTypeService: '@Ibexa\Contracts\Core\Repository\ContentTypeService'
$filler: '@CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFillerInterface'
$filler: '@CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFillerInterface'
$repository: '@Ibexa\Core\Event\Repository'
CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFillerInterface: '@CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFiller'
CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFiller:
CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFillerInterface: '@CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFiller'
CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFiller:
arguments:
$fieldValueCreators: !tagged 'coderhapsodie.ezdataflow.field_value_creator'
$fieldValueCreators: !tagged_iterator 'coderhapsodie.ibexa_dataflow.field_value_creator'
CodeRhapsodie\EzDataflowBundle\Matcher\LocationMatcherInterface: '@CodeRhapsodie\EzDataflowBundle\Matcher\LocationMatcher'
CodeRhapsodie\EzDataflowBundle\Matcher\LocationMatcher:
CodeRhapsodie\IbexaDataflowBundle\Matcher\LocationMatcherInterface: '@CodeRhapsodie\IbexaDataflowBundle\Matcher\LocationMatcher'
CodeRhapsodie\IbexaDataflowBundle\Matcher\LocationMatcher:
arguments:
$locationService: '@Ibexa\Contracts\Core\Repository\LocationService'
CodeRhapsodie\EzDataflowBundle\Core\Field\DefaultFieldValueCreator:
CodeRhapsodie\IbexaDataflowBundle\Core\Field\DefaultFieldValueCreator:
arguments:
$fieldTypeService: '@Ibexa\Contracts\Core\Repository\FieldTypeService'
tags:
- { name: 'coderhapsodie.ezdataflow.field_value_creator', priority: -1000 }
- { name: 'coderhapsodie.ibexa_dataflow.field_value_creator', priority: -1000 }
CodeRhapsodie\EzDataflowBundle\EventSubscriber\MenuSubscriber:
CodeRhapsodie\IbexaDataflowBundle\EventSubscriber\MenuSubscriber:
tags: ['kernel.event_subscriber']
CodeRhapsodie\EzDataflowBundle\Factory\ContentStructureFactoryInterface: '@CodeRhapsodie\EzDataflowBundle\Factory\ContentStructureFactory'
CodeRhapsodie\IbexaDataflowBundle\Factory\ContentStructureFactoryInterface: '@CodeRhapsodie\IbexaDataflowBundle\Factory\ContentStructureFactory'
CodeRhapsodie\EzDataflowBundle\Factory\ContentStructureFactory:
CodeRhapsodie\IbexaDataflowBundle\Factory\ContentStructureFactory:
arguments:
$contentService: '@Ibexa\Contracts\Core\Repository\ContentService'
CodeRhapsodie\EzDataflowBundle\Form\DataflowTypeChoiceType:
CodeRhapsodie\IbexaDataflowBundle\Form\DataflowTypeChoiceType:
arguments:
$registry: '@CodeRhapsodie\DataflowBundle\Registry\DataflowTypeRegistryInterface'
tags: ['form.type']
CodeRhapsodie\EzDataflowBundle\Form\CreateScheduledType:
CodeRhapsodie\IbexaDataflowBundle\Form\CreateScheduledType:
tags: ['form.type']
CodeRhapsodie\EzDataflowBundle\Form\UpdateScheduledType:
CodeRhapsodie\IbexaDataflowBundle\Form\UpdateScheduledType:
tags: ['form.type']
CodeRhapsodie\EzDataflowBundle\Form\CreateOneshotType:
CodeRhapsodie\IbexaDataflowBundle\Form\CreateOneshotType:
tags: ['form.type']
CodeRhapsodie\EzDataflowBundle\Form\UserTimezoneAwareDateTimeType:
CodeRhapsodie\IbexaDataflowBundle\Form\UserTimezoneAwareDateTimeType:
arguments:
$userPreferenceService: '@Ibexa\Contracts\Core\Repository\UserPreferenceService'
tags: ['form.type']
CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway:
CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway:
arguments:
$scheduledDataflowRepository: '@CodeRhapsodie\DataflowBundle\Repository\ScheduledDataflowRepository'
CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway:
CodeRhapsodie\IbexaDataflowBundle\Gateway\JobGateway:
arguments:
$jobRepository: '@CodeRhapsodie\DataflowBundle\Repository\JobRepository'
$jobGateway: '@CodeRhapsodie\DataflowBundle\Gateway\JobGateway'
CodeRhapsodie\EzDataflowBundle\Tab\RepeatingTab:
CodeRhapsodie\IbexaDataflowBundle\Tab\DashboardTab:
parent: Ibexa\Contracts\AdminUi\Tab\AbstractTab
public: false
arguments:
$httpKernelRuntime: '@twig.runtime.httpkernel'
tags:
- {name: ibexa.admin_ui.tab, group: coderhapsodie-ezdataflow}
- { name: ibexa.admin_ui.tab, group: coderhapsodie-ibexa_dataflow }
CodeRhapsodie\EzDataflowBundle\Tab\OneshotTab:
CodeRhapsodie\IbexaDataflowBundle\Tab\RepeatingTab:
parent: Ibexa\Contracts\AdminUi\Tab\AbstractTab
public: false
arguments:
$httpKernelRuntime: '@twig.runtime.httpkernel'
tags:
- {name: ibexa.admin_ui.tab, group: coderhapsodie-ezdataflow}
- {name: ibexa.admin_ui.tab, group: coderhapsodie-ibexa_dataflow}
CodeRhapsodie\EzDataflowBundle\Tab\HistoryTab:
CodeRhapsodie\IbexaDataflowBundle\Tab\OneshotTab:
parent: Ibexa\Contracts\AdminUi\Tab\AbstractTab
public: false
arguments:
$httpKernelRuntime: '@twig.runtime.httpkernel'
tags:
- {name: ibexa.admin_ui.tab, group: coderhapsodie-ezdataflow}
- {name: ibexa.admin_ui.tab, group: coderhapsodie-ibexa_dataflow}
CodeRhapsodie\IbexaDataflowBundle\Tab\HistoryTab:
parent: Ibexa\Contracts\AdminUi\Tab\AbstractTab
public: false
arguments:
$httpKernelRuntime: '@twig.runtime.httpkernel'
tags:
- {name: ibexa.admin_ui.tab, group: coderhapsodie-ibexa_dataflow}
CodeRhapsodie\EzDataflowBundle\Filter\NotModifiedContentFilter:
CodeRhapsodie\IbexaDataflowBundle\Filter\NotModifiedContentFilter:
arguments:
$contentService: '@Ibexa\Contracts\Core\Repository\ContentService'
$comparator: '@CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface'
$comparator: '@CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\FieldComparatorInterface'
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface: '@CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\DelegatorFieldComparator'
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\DelegatorFieldComparator:
CodeRhapsodie\IbexaDataflowBundle\Filter\NotModifiedProductFilter:
arguments:
$notModifiedContentFilter: '@CodeRhapsodie\IbexaDataflowBundle\Filter\NotModifiedContentFilter'
$connection: '@ibexa.persistence.connection'
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator:
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\FieldComparatorInterface: '@CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\DelegatorFieldComparator'
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\DelegatorFieldComparator:
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator:
arguments:
$fieldTypeService: '@Ibexa\Contracts\Core\Repository\FieldTypeService'
abstract: true
_cr.admin_tabs.ezdataflow_group:
_cr.admin_tabs.ibexa_dataflow_group:
parent: Ibexa\AdminUi\Component\TabsComponent
autowire: true
autoconfigure: false
public: false
arguments:
$groupIdentifier: 'coderhapsodie-ezdataflow'
$groupIdentifier: 'coderhapsodie-ibexa_dataflow'
tags:
- { name: ibexa.admin_ui.component, group: 'coderhapsodie-ezdataflow' }
- { name: ibexa.admin_ui.component, group: 'coderhapsodie-ibexa_dataflow' }

View File

@@ -1,42 +1,62 @@
services:
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\SimpleFieldComparator:
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\SimpleFieldComparator:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezauthor' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezboolean' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezcountry' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezdate' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezdatetime' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezemail' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezfloat' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezinteger' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezisbn' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezkeyword' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezobjectrelation' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezobjectrelationlist' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezrichtext' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezselection' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'eztext' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezstring' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'eztime' }
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'eztags' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_author' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_boolean' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_country' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_datetime' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_date' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_email' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_float' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_integer' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_isbn' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_keyword' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_object_relation' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_object_relation_list' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_richtext' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_selection' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_text' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_string' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_time' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'eztags' }
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\UrlFieldComparator:
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\UrlFieldComparator:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezurl' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_url' }
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\NovaSEOMetasFieldComparator:
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\NovaSEOMetasFieldComparator:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'novaseometas' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'novaseometas' }
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\MatrixFieldComparator:
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\MatrixFieldComparator:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezmatrix' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_matrix' }
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\MapLocationFieldComparator:
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\MapLocationFieldComparator:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezgmaplocation' }
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_gmap_location' }
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\TaxonomyEntryAssignmentComparator:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_taxonomy_entry_assignment' }
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\BillingAddressComparator:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_address' }
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\CustomerGroupComparator:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_customer_group' }
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\ProductSpecificationComparator:
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
tags:
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_product_specification' }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -1,4 +1,4 @@
role.policy.ezdataflow: Ibexa Dataflow
role.policy.ezdataflow.all_functions: Ibexa Dataflow / All functions
role.policy.ezdataflow.view: Ibexa Dataflow / View
role.policy.ezdataflow.edit: Ibexa Dataflow / Edit
role.policy.ibexa_dataflow: Ibexa Dataflow
role.policy.ibexa_dataflow.all_functions: Ibexa Dataflow / All functions
role.policy.ibexa_dataflow.view: Ibexa Dataflow / View
role.policy.ibexa_dataflow.edit: Ibexa Dataflow / Edit

View File

@@ -1,4 +1,4 @@
role.policy.ezdataflow: Ibexa Dataflow
role.policy.ezdataflow.all_functions: Ibexa Dataflow / Toutes les fonctions
role.policy.ezdataflow.view: Ibexa Dataflow / Consultation
role.policy.ezdataflow.edit: Ibexa Dataflow / Modification
role.policy.ibexa_dataflow: Ibexa Dataflow
role.policy.ibexa_dataflow.all_functions: Ibexa Dataflow / Toutes les fonctions
role.policy.ibexa_dataflow.view: Ibexa Dataflow / Consultation
role.policy.ibexa_dataflow.edit: Ibexa Dataflow / Modification

View File

@@ -1 +1 @@
coderhapsodie.ezdataflow: Ibexa Dataflow
coderhapsodie.ibexa_dataflow: Ibexa Dataflow

View File

@@ -1 +1 @@
coderhapsodie.ezdataflow: Ibexa Dataflow
coderhapsodie.ibexa_dataflow: Ibexa Dataflow

View File

@@ -1 +1 @@
coderhapsodie.ezdataflow: Ibexa Dataflow
coderhapsodie.ibexa_dataflow: Ibexa Dataflow

View File

@@ -1 +1 @@
coderhapsodie.ezdataflow: Ibexa Dataflow
coderhapsodie.ibexa_dataflow: Ibexa Dataflow

View File

@@ -1,67 +1,68 @@
coderhapsodie.ezdataflow: Ibexa Dataflow
coderhapsodie.ezdataflow.yes: Yes
coderhapsodie.ezdataflow.no: No
coderhapsodie.ezdataflow.repeating: Repeating
coderhapsodie.ezdataflow.repeating.title: Repeating
coderhapsodie.ezdataflow.oneshot: Oneshot
coderhapsodie.ezdataflow.oneshot.title: Oneshot
coderhapsodie.ezdataflow.oneshot.list.title: 'Oneshot dataflow list'
coderhapsodie.ezdataflow.workflow.list.title: 'Scheduled dataflow list'
coderhapsodie.ezdataflow.history: History
coderhapsodie.ezdataflow.workflow.list.name: Name
coderhapsodie.ezdataflow.workflow.list.frequency: Frequency
coderhapsodie.ezdataflow.workflow.list.next_execution: 'Next execution'
coderhapsodie.ezdataflow.workflow.list.enabled: 'Enabled?'
coderhapsodie.ezdataflow.workflow.list.history: History
coderhapsodie.ezdataflow.workflow.list.edit: Edit
coderhapsodie.ezdataflow.workflow.list.disable: Disable
coderhapsodie.ezdataflow.workflow.list.enable: Enable
coderhapsodie.ezdataflow.history.title: History
coderhapsodie.ezdataflow.history.list.title: 'Executions list'
coderhapsodie.ezdataflow.history.list.name: Name
coderhapsodie.ezdataflow.history.list.request: 'Requested on'
coderhapsodie.ezdataflow.history.list.count: 'Number of successes'
coderhapsodie.ezdataflow.history.list.errors: 'Number of errors'
coderhapsodie.ezdataflow.history.list.start: 'Started on'
coderhapsodie.ezdataflow.history.list.end: 'Finished on'
coderhapsodie.ezdataflow.history.list.view: 'View details'
coderhapsodie.ezdataflow.history.list.status: Status
coderhapsodie.ezdataflow.history.filter.label: Filter results
coderhapsodie.ezdataflow.history.filter.none: All results
coderhapsodie.ezdataflow.history.filter.non_empty_only: Only non empty
coderhapsodie.ezdataflow.history.filter.with_error_only: Only with errors
coderhapsodie.ezdataflow.job.status.pending: Pending
coderhapsodie.ezdataflow.job.status.running: Running
coderhapsodie.ezdataflow.job.status.complete: Completed
coderhapsodie.ezdataflow.job.status.unknown: Unknown
coderhapsodie.ezdataflow.history.job.title: 'Job'
coderhapsodie.ezdataflow.history.details.title: 'Job details'
coderhapsodie.ezdataflow.history.details.name: Name
coderhapsodie.ezdataflow.history.details.request: 'Requested on'
coderhapsodie.ezdataflow.history.details.status: Status
coderhapsodie.ezdataflow.history.details.start: 'Started on'
coderhapsodie.ezdataflow.history.details.end: 'Finished on'
coderhapsodie.ezdataflow.history.details.count: 'Items successfully processed'
coderhapsodie.ezdataflow.history.details.options: 'Run options'
coderhapsodie.ezdataflow.history.details.errors: Errors
coderhapsodie.ezdataflow.history.details.type: 'Name of the dataflow executed'
coderhapsodie.ezdataflow.history.details.log: 'View log'
coderhapsodie.ezdataflow.workflow.repeating.new.title: 'Add a new repeating dataflow'
coderhapsodie.ezdataflow.workflow.new.cancel: Cancel
coderhapsodie.ezdataflow.workflow.new.submit: Create
coderhapsodie.ezdataflow.history.list.empty: 'No execution yet.'
coderhapsodie.ezdataflow.workflow.list.empty: 'No repeating workflow configured yet'
coderhapsodie.ezdataflow.workflow.history.title: 'Execution history'
coderhapsodie.ezdataflow.workflow.log.title: 'Execution log'
coderhapsodie.ezdataflow.workflow.list.delete: Delete
coderhapsodie.ezdataflow.workflow.delete: 'Are you sure you want to delete this dataflow schedule?'
coderhapsodie.ezdataflow.workflow.create.success: 'Dataflow schedule successfully added.'
coderhapsodie.ezdataflow.workflow.create.error: 'An error occurred during the dataflow schedule creation: "%message%".'
coderhapsodie.ezdataflow.workflow.delete.success: 'Dataflow schedule successfully deleted.'
coderhapsodie.ezdataflow.workflow.delete.error: 'An error occurred during the dataflow schedule deletion: "%message%".'
coderhapsodie.ezdataflow.workflow.oneshot.new.title: 'New oneshot job'
coderhapsodie.ezdataflow.job.create.success: 'Job successfully added.'
coderhapsodie.ezdataflow.job.create.error: 'An error occured during the job creation: "%message%".'
coderhapsodie.ibexa_dataflow: Ibexa Dataflow
coderhapsodie.ibexa_dataflow.yes: Yes
coderhapsodie.ibexa_dataflow.no: No
coderhapsodie.ibexa_dataflow.repeating: Repeating
coderhapsodie.ibexa_dataflow.repeating.title: Repeating
coderhapsodie.ibexa_dataflow.oneshot: Oneshot
coderhapsodie.ibexa_dataflow.oneshot.title: Oneshot
coderhapsodie.ibexa_dataflow.oneshot.list.title: 'Oneshot dataflow list'
coderhapsodie.ibexa_dataflow.workflow.list.title: 'Scheduled dataflow list'
coderhapsodie.ibexa_dataflow.history: History
coderhapsodie.ibexa_dataflow.workflow.list.name: Name
coderhapsodie.ibexa_dataflow.workflow.list.frequency: Frequency
coderhapsodie.ibexa_dataflow.workflow.list.next_execution: 'Next execution'
coderhapsodie.ibexa_dataflow.workflow.list.enabled: 'Enabled?'
coderhapsodie.ibexa_dataflow.workflow.list.history: History
coderhapsodie.ibexa_dataflow.workflow.list.edit: Edit
coderhapsodie.ibexa_dataflow.workflow.list.disable: Disable
coderhapsodie.ibexa_dataflow.workflow.list.enable: Enable
coderhapsodie.ibexa_dataflow.workflow.list.runonce: Run now
coderhapsodie.ibexa_dataflow.history.title: History
coderhapsodie.ibexa_dataflow.history.list.title: 'Executions list'
coderhapsodie.ibexa_dataflow.history.list.name: Name
coderhapsodie.ibexa_dataflow.history.list.request: 'Requested on'
coderhapsodie.ibexa_dataflow.history.list.count: 'Number of successes'
coderhapsodie.ibexa_dataflow.history.list.errors: 'Number of errors'
coderhapsodie.ibexa_dataflow.history.list.start: 'Started on'
coderhapsodie.ibexa_dataflow.history.list.end: 'Finished on'
coderhapsodie.ibexa_dataflow.history.list.view: 'View details'
coderhapsodie.ibexa_dataflow.history.list.status: Status
coderhapsodie.ibexa_dataflow.history.filter.label: Filter results
coderhapsodie.ibexa_dataflow.history.filter.none: All results
coderhapsodie.ibexa_dataflow.history.filter.non_empty_only: Only non empty
coderhapsodie.ibexa_dataflow.history.filter.with_error_only: Only with errors
coderhapsodie.ibexa_dataflow.job.status.pending: Pending
coderhapsodie.ibexa_dataflow.job.status.running: Running
coderhapsodie.ibexa_dataflow.job.status.complete: Completed
coderhapsodie.ibexa_dataflow.job.status.unknown: Unknown
coderhapsodie.ibexa_dataflow.history.job.title: 'Job'
coderhapsodie.ibexa_dataflow.history.details.title: 'Job details'
coderhapsodie.ibexa_dataflow.history.details.name: Name
coderhapsodie.ibexa_dataflow.history.details.request: 'Requested on'
coderhapsodie.ibexa_dataflow.history.details.status: Status
coderhapsodie.ibexa_dataflow.history.details.start: 'Started on'
coderhapsodie.ibexa_dataflow.history.details.end: 'Finished on'
coderhapsodie.ibexa_dataflow.history.details.count: 'Items successfully processed'
coderhapsodie.ibexa_dataflow.history.details.options: 'Run options'
coderhapsodie.ibexa_dataflow.history.details.errors: Errors
coderhapsodie.ibexa_dataflow.history.details.type: 'Name of the dataflow executed'
coderhapsodie.ibexa_dataflow.history.details.log: 'View log'
coderhapsodie.ibexa_dataflow.workflow.repeating.new.title: 'Add a new repeating dataflow'
coderhapsodie.ibexa_dataflow.workflow.new.cancel: Cancel
coderhapsodie.ibexa_dataflow.workflow.new.submit: Create
coderhapsodie.ibexa_dataflow.history.list.empty: 'No execution yet.'
coderhapsodie.ibexa_dataflow.workflow.list.empty: 'No repeating workflow configured yet'
coderhapsodie.ibexa_dataflow.workflow.history.title: 'Execution history'
coderhapsodie.ibexa_dataflow.workflow.log.title: 'Execution log'
coderhapsodie.ibexa_dataflow.workflow.list.delete: Delete
coderhapsodie.ibexa_dataflow.workflow.delete: 'Are you sure you want to delete this dataflow schedule?'
coderhapsodie.ibexa_dataflow.workflow.create.success: 'Dataflow schedule successfully added.'
coderhapsodie.ibexa_dataflow.workflow.create.error: 'An error occurred during the dataflow schedule creation: "%message%".'
coderhapsodie.ibexa_dataflow.workflow.delete.success: 'Dataflow schedule successfully deleted.'
coderhapsodie.ibexa_dataflow.workflow.delete.error: 'An error occurred during the dataflow schedule deletion: "%message%".'
coderhapsodie.ibexa_dataflow.workflow.oneshot.new.title: 'New oneshot job'
coderhapsodie.ibexa_dataflow.job.create.success: 'Job successfully added.'
coderhapsodie.ibexa_dataflow.job.create.error: 'An error occured during the job creation: "%message%".'
coderhapsodie.dataflow.label: 'Scheduled dataflow name'
coderhapsodie.dataflow.oneshot.label: 'One-shot job name'
coderhapsodie.dataflow.dataflowType: 'Select the dataflow to run'
@@ -76,9 +77,13 @@ coderhapsodie.dataflow.frequency.title: 'Enter an interval in a format compatibl
coderhapsodie.dataflow.frequency.placeholder: 'Example: 1 year 2 months 3 weeks 4 days 5 hours 6 minutes'
coderhapsodie.dataflow.create.next: 'First run'
coderhapsodie.dataflow.create.enabled: Enabled?
coderhapsodie.ezdataflow.workflow.repeating.edit.title: "Dataflow schedule edit"
coderhapsodie.ezdataflow.workflow.edit.submit: Save
coderhapsodie.ibexa_dataflow.workflow.repeating.edit.title: "Dataflow schedule edit"
coderhapsodie.ibexa_dataflow.workflow.edit.submit: Save
coderhapsodie.dataflow.update.next: 'Next execution'
coderhapsodie.ezdataflow.workflow.edit.success: 'Dataflow schedule successfully updated.'
coderhapsodie.ezdataflow.workflow.edit.error: 'An error occurred during the dataflow schedule update: "%message%".'
coderhapsodie.ezdataflow.notfound: 'Requested data is not found'
coderhapsodie.ibexa_dataflow.workflow.edit.success: 'Dataflow schedule successfully updated.'
coderhapsodie.ibexa_dataflow.workflow.edit.error: 'An error occurred during the dataflow schedule update: "%message%".'
coderhapsodie.ibexa_dataflow.notfound: 'Requested data is not found'
coderhapsodie.ibexa_dataflow.powered_by: 'Powered by'
coderhapsodie.ibexa_dataflow.made_by: 'Made by'
coderhapsodie.ibexa_dataflow.dashboard: Dashboard
coderhapsodie.ibexa_dataflow.dashboard.title: Running or waiting tasks

View File

@@ -1,67 +1,68 @@
coderhapsodie.ezdataflow: Ibexa Dataflow
coderhapsodie.ezdataflow.yes: Oui
coderhapsodie.ezdataflow.no: Non
coderhapsodie.ezdataflow.repeating: Récurrent
coderhapsodie.ezdataflow.repeating.title: Récurrent
coderhapsodie.ezdataflow.oneshot: Ponctuel
coderhapsodie.ezdataflow.oneshot.title: Ponctuel
coderhapsodie.ezdataflow.oneshot.list.title: 'Liste des exécutions ponctuelles de dataflow'
coderhapsodie.ezdataflow.workflow.list.title: 'Liste des programmations des dataflow'
coderhapsodie.ezdataflow.history: Historique
coderhapsodie.ezdataflow.workflow.list.name: Nom
coderhapsodie.ezdataflow.workflow.list.frequency: Fréquence
coderhapsodie.ezdataflow.workflow.list.next_execution: 'Prochaine exécution'
coderhapsodie.ezdataflow.workflow.list.enabled: 'Activé ?'
coderhapsodie.ezdataflow.workflow.list.history: Historique
coderhapsodie.ezdataflow.workflow.list.edit: Éditer
coderhapsodie.ezdataflow.workflow.list.disable: Désactiver
coderhapsodie.ezdataflow.workflow.list.enable: Activer
coderhapsodie.ezdataflow.history.title: Historique
coderhapsodie.ezdataflow.history.list.title: 'Liste des exécutions'
coderhapsodie.ezdataflow.history.list.name: Nom
coderhapsodie.ezdataflow.history.list.request: 'Demandé le'
coderhapsodie.ezdataflow.history.list.count: 'Nombre de succès'
coderhapsodie.ezdataflow.history.list.errors: 'Nombre d''erreurs'
coderhapsodie.ezdataflow.history.list.start: 'Commencé le'
coderhapsodie.ezdataflow.history.list.end: 'Terminé le'
coderhapsodie.ezdataflow.history.list.view: 'Voir le détail'
coderhapsodie.ezdataflow.history.list.status: État
coderhapsodie.ezdataflow.history.filter.label: Filtrer les résultats
coderhapsodie.ezdataflow.history.filter.none: Tous les résultats
coderhapsodie.ezdataflow.history.filter.non_empty_only: Seulement non vides
coderhapsodie.ezdataflow.history.filter.with_error_only: Seulement avec erreurs
coderhapsodie.ezdataflow.job.status.pending: 'En attente'
coderhapsodie.ezdataflow.job.status.running: 'En cours'
coderhapsodie.ezdataflow.job.status.complete: Terminé
coderhapsodie.ezdataflow.job.status.unknown: Inconnu
coderhapsodie.ezdataflow.history.job.title: 'Exécution'
coderhapsodie.ezdataflow.history.details.title: 'Détails de l''exécution'
coderhapsodie.ezdataflow.history.details.name: Nom
coderhapsodie.ezdataflow.history.details.request: 'Demandé le'
coderhapsodie.ezdataflow.history.details.status: État
coderhapsodie.ezdataflow.history.details.start: 'Commencé le'
coderhapsodie.ezdataflow.history.details.end: 'Terminé le'
coderhapsodie.ezdataflow.history.details.count: 'Nombre d''objets mis à jour'
coderhapsodie.ezdataflow.history.details.options: 'Options de lancement'
coderhapsodie.ezdataflow.history.details.errors: Erreurs
coderhapsodie.ezdataflow.history.details.type: 'Nom du dataflow exécuté'
coderhapsodie.ezdataflow.history.details.log: 'Voir le log'
coderhapsodie.ezdataflow.workflow.repeating.new.title: 'Nouvel programmation d''un dataflow récurrent'
coderhapsodie.ezdataflow.workflow.new.cancel: Annuler
coderhapsodie.ezdataflow.workflow.new.submit: Créer
coderhapsodie.ezdataflow.history.list.empty: 'Aucune exécution pour le moment.'
coderhapsodie.ezdataflow.workflow.list.empty: 'Aucun dataflow n''a été programmé.'
coderhapsodie.ezdataflow.workflow.history.title: 'Historique des exécutions'
coderhapsodie.ezdataflow.workflow.log.title: 'Log de l''exécution'
coderhapsodie.ezdataflow.workflow.list.delete: Supprimer
coderhapsodie.ezdataflow.workflow.delete: 'Êtes-vous sûr de vouloir supprimer ce dataflow ?'
coderhapsodie.ezdataflow.workflow.create.success: 'La programmation du dataflow a bien été ajoutée.'
coderhapsodie.ezdataflow.workflow.create.error: 'Une erreur est survenue lors de l''ajout de la programmation du dataflow : "%message%".'
coderhapsodie.ezdataflow.workflow.delete.success: 'La programmation du dataflow a bien été supprimée.'
coderhapsodie.ezdataflow.workflow.delete.error: 'Une erreur est survenue lors de la suppression de la programmation du dataflow : "%message%".'
coderhapsodie.ezdataflow.workflow.oneshot.new.title: 'Nouvelle exécution ponctuelle'
coderhapsodie.ezdataflow.job.create.success: 'Votre exécution a bien été ajoutée.'
coderhapsodie.ezdataflow.job.create.error: 'Une erreur est survenue lors de l''ajout de l''exécution : "%message%".'
coderhapsodie.ibexa_dataflow: Ibexa Dataflow
coderhapsodie.ibexa_dataflow.yes: Oui
coderhapsodie.ibexa_dataflow.no: Non
coderhapsodie.ibexa_dataflow.repeating: Récurrent
coderhapsodie.ibexa_dataflow.repeating.title: Récurrent
coderhapsodie.ibexa_dataflow.oneshot: Ponctuel
coderhapsodie.ibexa_dataflow.oneshot.title: Ponctuel
coderhapsodie.ibexa_dataflow.oneshot.list.title: 'Liste des exécutions ponctuelles de dataflow'
coderhapsodie.ibexa_dataflow.workflow.list.title: 'Liste des programmations des dataflow'
coderhapsodie.ibexa_dataflow.history: Historique
coderhapsodie.ibexa_dataflow.workflow.list.name: Nom
coderhapsodie.ibexa_dataflow.workflow.list.frequency: Fréquence
coderhapsodie.ibexa_dataflow.workflow.list.next_execution: 'Prochaine exécution'
coderhapsodie.ibexa_dataflow.workflow.list.enabled: 'Activé ?'
coderhapsodie.ibexa_dataflow.workflow.list.history: Historique
coderhapsodie.ibexa_dataflow.workflow.list.edit: Éditer
coderhapsodie.ibexa_dataflow.workflow.list.disable: Désactiver
coderhapsodie.ibexa_dataflow.workflow.list.enable: Activer
coderhapsodie.ibexa_dataflow.workflow.list.runonce: Lancer maintenant
coderhapsodie.ibexa_dataflow.history.title: Historique
coderhapsodie.ibexa_dataflow.history.list.title: 'Liste des exécutions'
coderhapsodie.ibexa_dataflow.history.list.name: Nom
coderhapsodie.ibexa_dataflow.history.list.request: 'Demandé le'
coderhapsodie.ibexa_dataflow.history.list.count: 'Nombre de succès'
coderhapsodie.ibexa_dataflow.history.list.errors: 'Nombre d''erreurs'
coderhapsodie.ibexa_dataflow.history.list.start: 'Commencé le'
coderhapsodie.ibexa_dataflow.history.list.end: 'Terminé le'
coderhapsodie.ibexa_dataflow.history.list.view: 'Voir le détail'
coderhapsodie.ibexa_dataflow.history.list.status: État
coderhapsodie.ibexa_dataflow.history.filter.label: Filtrer les résultats
coderhapsodie.ibexa_dataflow.history.filter.none: Tous les résultats
coderhapsodie.ibexa_dataflow.history.filter.non_empty_only: Seulement non vides
coderhapsodie.ibexa_dataflow.history.filter.with_error_only: Seulement avec erreurs
coderhapsodie.ibexa_dataflow.job.status.pending: 'En attente'
coderhapsodie.ibexa_dataflow.job.status.running: 'En cours'
coderhapsodie.ibexa_dataflow.job.status.complete: Terminé
coderhapsodie.ibexa_dataflow.job.status.unknown: Inconnu
coderhapsodie.ibexa_dataflow.history.job.title: 'Exécution'
coderhapsodie.ibexa_dataflow.history.details.title: 'Détails de l''exécution'
coderhapsodie.ibexa_dataflow.history.details.name: Nom
coderhapsodie.ibexa_dataflow.history.details.request: 'Demandé le'
coderhapsodie.ibexa_dataflow.history.details.status: État
coderhapsodie.ibexa_dataflow.history.details.start: 'Commencé le'
coderhapsodie.ibexa_dataflow.history.details.end: 'Terminé le'
coderhapsodie.ibexa_dataflow.history.details.count: 'Nombre d''objets mis à jour'
coderhapsodie.ibexa_dataflow.history.details.options: 'Options de lancement'
coderhapsodie.ibexa_dataflow.history.details.errors: Erreurs
coderhapsodie.ibexa_dataflow.history.details.type: 'Nom du dataflow exécuté'
coderhapsodie.ibexa_dataflow.history.details.log: 'Voir le log'
coderhapsodie.ibexa_dataflow.workflow.repeating.new.title: 'Nouvel programmation d''un dataflow récurrent'
coderhapsodie.ibexa_dataflow.workflow.new.cancel: Annuler
coderhapsodie.ibexa_dataflow.workflow.new.submit: Créer
coderhapsodie.ibexa_dataflow.history.list.empty: 'Aucune exécution pour le moment.'
coderhapsodie.ibexa_dataflow.workflow.list.empty: 'Aucun dataflow n''a été programmé.'
coderhapsodie.ibexa_dataflow.workflow.history.title: 'Historique des exécutions'
coderhapsodie.ibexa_dataflow.workflow.log.title: 'Log de l''exécution'
coderhapsodie.ibexa_dataflow.workflow.list.delete: Supprimer
coderhapsodie.ibexa_dataflow.workflow.delete: 'Êtes-vous sûr de vouloir supprimer ce dataflow ?'
coderhapsodie.ibexa_dataflow.workflow.create.success: 'La programmation du dataflow a bien été ajoutée.'
coderhapsodie.ibexa_dataflow.workflow.create.error: 'Une erreur est survenue lors de l''ajout de la programmation du dataflow : "%message%".'
coderhapsodie.ibexa_dataflow.workflow.delete.success: 'La programmation du dataflow a bien été supprimée.'
coderhapsodie.ibexa_dataflow.workflow.delete.error: 'Une erreur est survenue lors de la suppression de la programmation du dataflow : "%message%".'
coderhapsodie.ibexa_dataflow.workflow.oneshot.new.title: 'Nouvelle exécution ponctuelle'
coderhapsodie.ibexa_dataflow.job.create.success: 'Votre exécution a bien été ajoutée.'
coderhapsodie.ibexa_dataflow.job.create.error: 'Une erreur est survenue lors de l''ajout de l''exécution : "%message%".'
coderhapsodie.dataflow.label: 'Nom de la programmation du dataflow'
coderhapsodie.dataflow.oneshot.label: 'Nom de l''exécution ponctuelle du dataflow'
coderhapsodie.dataflow.dataflowType: 'Dataflow à exécuter'
@@ -74,9 +75,13 @@ coderhapsodie.dataflow.frequency.title: 'Entrez un intervalle compatible avec st
coderhapsodie.dataflow.frequency.placeholder: 'Exemple: 1 year 2 months 3 weeks 4 days 5 hours 6 minutes'
coderhapsodie.dataflow.create.next: 'Première exécution'
coderhapsodie.dataflow.create.enabled: 'Activé ?'
coderhapsodie.ezdataflow.workflow.repeating.edit.title: "Édition de la programmation d'un dataflow"
coderhapsodie.ezdataflow.workflow.edit.submit: Sauvegarder
coderhapsodie.ibexa_dataflow.workflow.repeating.edit.title: "Édition de la programmation d'un dataflow"
coderhapsodie.ibexa_dataflow.workflow.edit.submit: Sauvegarder
coderhapsodie.dataflow.update.next: 'Prochaine exécution'
coderhapsodie.ezdataflow.workflow.edit.success: 'La programmation du dataflow a été mise à jour avec succès.'
coderhapsodie.ezdataflow.workflow.edit.error: 'Une erreur est survenue lors de la modification de la programmation du dataflow : "%message%".'
coderhapsodie.ezdataflow.notfound: 'Les données demandées sont introuvables'
coderhapsodie.ibexa_dataflow.workflow.edit.success: 'La programmation du dataflow a été mise à jour avec succès.'
coderhapsodie.ibexa_dataflow.workflow.edit.error: 'Une erreur est survenue lors de la modification de la programmation du dataflow : "%message%".'
coderhapsodie.ibexa_dataflow.notfound: 'Les données demandées sont introuvables'
coderhapsodie.ibexa_dataflow.powered_by: 'Propulsé par'
coderhapsodie.ibexa_dataflow.made_by: 'Fabriqué par'
coderhapsodie.ibexa_dataflow.dashboard: Dashboard
coderhapsodie.ibexa_dataflow.dashboard.title: Tâches en cours ou en attente

View File

@@ -1,112 +0,0 @@
{% extends "@ibexadesign/ui/layout.html.twig" %}
{% block body_class %}ibexa-ezdataflow{% endblock %}
{% block breadcrumbs %}
{% include '@ibexadesign/ui/breadcrumbs.html.twig' with { items: [
{ value: 'breadcrumb.admin'|trans(domain='messages')|desc('Admin') },
{ value: 'coderhapsodie.ezdataflow'|trans|desc('EzDataflow') }
]} %}
{% endblock %}
{% block header %}
{% include '@ibexadesign/ui/page_title.html.twig' with {
title: 'coderhapsodie.ezdataflow'|trans|desc('EzDataflow'),
} %}
{% endblock %}
{% block content %}
{{ ibexa_render_component_group('coderhapsodie-ezdataflow', {'filter': app.request.query.get('filter', 0)}) }}
{% embed '@ibexadesign/ui/component/modal/modal.html.twig' with {
id: 'modal-history-details',
attr_dialog: {'style': 'max-width: 75vw;'},
title: 'coderhapsodie.ezdataflow.history.job.title'|trans,
} %}
{% block body_content '' %}
{% endembed %}
{% embed '@ibexadesign/ui/component/modal/modal.html.twig' with {
id: 'modal-history-log',
attr_dialog: {'style': 'max-width: 75vw;'},
title: 'coderhapsodie.ezdataflow.workflow.log.title'|trans,
} %}
{% block body_content '' %}
{% endembed %}
{% embed '@ibexadesign/ui/component/modal/modal.html.twig' with {
id: 'modal-history',
attr_dialog: {'style': 'max-width: 75vw;'},
title: 'coderhapsodie.ezdataflow.workflow.history.title'|trans,
} %}
{% block body_content '' %}
{% endembed %}
<script>
document.addEventListener('DOMContentLoaded', () => {
const bindModalLinks = (modalId, linkSelector) => {
const modal = document.getElementById(modalId);
const modalBody = modal.querySelector('.modal-body');
document.addEventListener('click', (e) => {
const link = e.target.closest(linkSelector);
if (link) {
e.preventDefault();
modalBody.innerHTML = '';
fetch(link.href)
.then((r) => r.text())
.then((content) => {
modalBody.innerHTML = content;
})
;
return;
}
})
}
bindModalLinks('modal-history-details', '.modal-history-details');
bindModalLinks('modal-history-log', '.modal-history-log');
bindModalLinks('modal-history', '.modal-history');
const labels = document.getElementById('ibexa-tab-label-coderhapsodie-ezdataflow-code-rhapsodie-ezdataflow-repeating')
.closest('ul').querySelectorAll('li.ibexa-tabs__tab');
const tabs = document.getElementById('ibexa-tab-coderhapsodie-ezdataflow-code-rhapsodie-ezdataflow-repeating')
.closest('.tab-content').querySelectorAll('.tab-pane');
// Manage ajax pagination
document.addEventListener('click', (e) => {
const link = e.target.closest('.ibexa-pagination a');
if (!link) {
return;
}
const block = link.closest('.ibexa-pagination').parentNode.parentNode;
const display = block.querySelector('.ibexa-table');
const pagination = block.querySelector('.pag');
const loader = document.querySelector('#' + block.dataset.loader);
e.preventDefault();
loader.hidden = false;
display.innerHTML = '';
pagination.innerHTML = '';
fetch(link.href)
.then((r) => r.text())
.then((content) => {
const node = document.createElement('div');
node.innerHTML = content;
display.innerHTML = node.querySelector('#' + block.id).querySelector('.ibexa-table').innerHTML;
pagination.innerHTML = node.querySelector('#' + block.id).querySelector('.pag').innerHTML;
loader.hidden = true;
})
;
});
});
</script>
{% endblock %}
{% block stylesheets %}
{{ parent() }}
<style>
.ezdataflow-date .ibexa-dropdown {
min-width: 0;
}
</style>
{% endblock %}

View File

@@ -1,5 +0,0 @@
{% include '@ibexadesign/ezdataflow/parts/tab/job_list.html.twig' with {
identifier: 'ezdataflow_schedule_history_results',
paginate_route: 'coderhapsodie.ezdataflow.history.workflow',
paginate_params: {id: id}
} %}

View File

@@ -1,59 +0,0 @@
{% import '@ibexadesign/ezdataflow/macros.twig' as macros %}
{% block content %}
<div class="container ez-main-container history-details-aware">
{% if item is not null %}
<h2>{{ 'coderhapsodie.ezdataflow.history.job.title'|trans }}{{ item.id }}</h2>
<table class="table ez-table ez-table--list">
<thead>
<tr>
<th colspan="2">
{{ 'coderhapsodie.ezdataflow.history.details.title'|trans }}
</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ 'coderhapsodie.ezdataflow.history.details.name'|trans }}</td>
<td>{{ item.label }}</td>
</tr>
<tr>
<td>{{ 'coderhapsodie.ezdataflow.history.details.request'|trans }}</td>
<td>{{ date(item.requestedDate)|ibexa_short_datetime }}</td>
</tr>
<tr>
<td>{{ 'coderhapsodie.ezdataflow.history.details.status'|trans }}</td>
<td>{{ macros.translateStatus(item.status) }}</td>
</tr>
<tr>
<td>{{ 'coderhapsodie.ezdataflow.history.details.start'|trans }}</td>
<td>{{ item.startTime ? date(item.startTime)|ibexa_short_datetime : '—' }}</td>
</tr>
<tr>
<td>{{ 'coderhapsodie.ezdataflow.history.details.end'|trans }}</td>
<td>{{ item.endTime ? date(item.endTime)|ibexa_short_datetime : '—' }}</td>
</tr>
<tr>
<td>{{ 'coderhapsodie.ezdataflow.history.details.count'|trans }}</td>
<td>{{ item.count }}</td>
</tr>
<tr>
<td>{{ 'coderhapsodie.ezdataflow.history.details.errors'|trans }}</td>
<td>{{ item.exceptions|length }}</td>
</tr>
<tr>
<td>{{ 'coderhapsodie.ezdataflow.history.details.type'|trans }}</td>
<td>{{ item.dataflowType }}</td>
</tr>
<tr>
<td>{{ 'coderhapsodie.ezdataflow.history.details.options'|trans }}</td>
<td>{{ item.options|json_encode }}</td>
</tr>
</tbody>
</table>
{% else %}
<p class="ez-table-no-content">{{ 'coderhapsodie.ezdataflow.notfound'|trans }}</p>
{% endif %}
</div>
{% endblock %}

View File

@@ -1,11 +0,0 @@
{% macro translateStatus(status) %}
{% if status == 0 %}
{{ 'coderhapsodie.ezdataflow.job.status.pending'|trans }}
{% elseif status == 1 %}
{{ 'coderhapsodie.ezdataflow.job.status.running'|trans }}
{% elseif status == 2 %}
{{ 'coderhapsodie.ezdataflow.job.status.complete'|trans }}
{% else %}
{{ 'coderhapsodie.ezdataflow.job.status.unknown'|trans }}
{% endif %}
{% endmacro %}

View File

@@ -0,0 +1,5 @@
{%- block content -%}
{% include '@ibexadesign/ibexa_dataflow/parts/tab/dashboard_list.html.twig' with {
identifier: 'ibexa_dataflow_schedule_dashboard_results',
} %}
{%- endblock -%}

View File

@@ -2,16 +2,16 @@
{% set choices = [
{
'value': 0,
'label': 'coderhapsodie.ezdataflow.history.filter.none'|trans,
'label': 'coderhapsodie.ibexa_dataflow.history.filter.none'|trans,
},
{
'value': 1,
'label': 'coderhapsodie.ezdataflow.history.filter.non_empty_only'|trans,
'label': 'coderhapsodie.ibexa_dataflow.history.filter.non_empty_only'|trans,
},
] %}
{% set source %}
<select id="ezdataflow_history_filter" class="form-control ibexa-input">
<select id="ibexa_dataflow_history_filter" class="form-control ibexa-input">
{% for choice in choices %}
<option value="{{ choice.value }}">
{{ choice.label }}
@@ -28,32 +28,32 @@
}) }}
{% endset %}
{{ include('@ibexadesign/ezdataflow/parts/tab/job_list.html.twig', {
identifier: 'ezdataflow_history_results',
paginate_route: 'coderhapsodie.ezdataflow.history',
{{ include('@ibexadesign/ibexa_dataflow/parts/tab/job_list.html.twig', {
identifier: 'ibexa_dataflow_history_results',
paginate_route: 'coderhapsodie.ibexa_dataflow.history',
paginate_params: {'filter': filter},
headline: 'coderhapsodie.ezdataflow.history.title'|trans,
headline: 'coderhapsodie.ibexa_dataflow.history.title'|trans,
actions: actions
}) }}
<script>
document.addEventListener('DOMContentLoaded', function () {
// Manage ajax pagination
document.getElementById('ezdataflow_history_filter').addEventListener('change', function (e) {
document.getElementById('ibexa_dataflow_history_filter').addEventListener('change', function (e) {
e.preventDefault();
const loading = document.getElementById('loading_ezdataflow_history_results');
const results = document.getElementById('ezdataflow_history_results').querySelector('.ibexa-table');
const pagination = document.getElementById('ezdataflow_history_results').querySelector('.pag');
const loading = document.getElementById('loading_ibexa_dataflow_history_results');
const results = document.getElementById('ibexa_dataflow_history_results').querySelector('.ibexa-table');
const pagination = document.getElementById('ibexa_dataflow_history_results').querySelector('.pag');
loading.hidden = false;
results.innerHTML = '';
pagination.innerHTML = '';
fetch('{{ path('coderhapsodie.ezdataflow.history') }}?filter=' + this.value)
fetch('{{ path('coderhapsodie.ibexa_dataflow.history') }}?filter=' + this.value)
.then((r) => r.text())
.then((content) => {
const node = document.createElement('div');
node.innerHTML = content;
results.innerHTML = node.querySelector('#ezdataflow_history_results .ibexa-table').innerHTML;
pagination.innerHTML = node.querySelector('#ezdataflow_history_results .pag').innerHTML;
results.innerHTML = node.querySelector('#ibexa_dataflow_history_results .ibexa-table').innerHTML;
pagination.innerHTML = node.querySelector('#ibexa_dataflow_history_results .pag').innerHTML;
loading.hidden = true;
})
;

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More