mirror of
https://github.com/code-rhapsodie/ezdataflow-bundle.git
synced 2026-03-24 14:42:06 +01:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d631e6555e |
55
.github/workflows/php.yml
vendored
55
.github/workflows/php.yml
vendored
@@ -1,55 +0,0 @@
|
||||
name: PHP Composer
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version: [7.3, 7.4, 8.0, 8.1]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP ${{ matrix.php-version }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
extensions: xdebug
|
||||
- name: PHP Version
|
||||
run: php -v
|
||||
|
||||
- name: PHP Lint
|
||||
run: find . -type f -name '*.php' -exec php -l {} \; | (! grep -v "No syntax errors detected" )
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate --strict
|
||||
|
||||
- name: Cache Composer packages
|
||||
id: composer-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: vendor
|
||||
key: ${{ runner.os }}-php${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-php${{ matrix.php-version }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer update --prefer-dist --no-progress --no-scripts
|
||||
|
||||
- name: PHPUnit
|
||||
run: php -d xdebug.mode=coverage vendor/bin/phpunit --log-junit junit.xml
|
||||
|
||||
- name: Publish Unit Test Results
|
||||
uses: EnricoMi/publish-unit-test-result-action@v1
|
||||
if: always()
|
||||
with:
|
||||
files: junit.xml
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,4 +3,3 @@ composer.lock
|
||||
.phpunit.result.cache
|
||||
.php_cs.cache
|
||||
.php_cs
|
||||
.php-cs-fixer.cache
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
$finder = PhpCsFixer\Finder::create()->in(__DIR__.'/src');
|
||||
|
||||
return (new PhpCsFixer\Config())
|
||||
return PhpCsFixer\Config::create()
|
||||
->setRules([
|
||||
'@Symfony' => true,
|
||||
'declare_strict_types' => true,
|
||||
38
CHANGELOG.md
38
CHANGELOG.md
@@ -1,41 +1,3 @@
|
||||
# Version 3.2.0
|
||||
|
||||
* Fixed History page pagination is hidden by footer on Ibexa 3.3 #38
|
||||
* Added filter on history page to filter out jobs with 0 items
|
||||
* Date and times will now be displayed using the user defined timezone, and stored using php timezone
|
||||
|
||||
# Version 3.1.0
|
||||
|
||||
* Allow `LocationCreateStruct` objects inside the `$locations` argument of `ContentCreateStructure` to have more control over the created locations.
|
||||
|
||||
# Version 3.0.1
|
||||
|
||||
* Bump minimum PHP version to PHP 7.3 like code-rhapsodie/dataflow-bundle dependency.
|
||||
* Allow PHP 8.x.
|
||||
* Add GitHub Action to run tests.
|
||||
|
||||
# Version 3.0.0
|
||||
|
||||
* Add compatibility with Ibexa Content 3.3
|
||||
* Add compatibility with Symfony 5.x
|
||||
|
||||
# Version 2.3.0
|
||||
|
||||
* Added a button to display exceptions / log in a modal
|
||||
* Add log in `CodeRhapsodie\EzDataflowBundle\Filter\NotModifiedContentFilter` and `CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter`
|
||||
|
||||
# Version 2.2.0
|
||||
|
||||
* Added `NotModifiedContentFilter` and a bunch of `FieldComparator` classes
|
||||
|
||||
# version 2.1.0
|
||||
|
||||
* ContentWriter return created content
|
||||
|
||||
# version 2.0.1
|
||||
|
||||
* Enclosure js code into anonymous function
|
||||
|
||||
# version 2.0.0
|
||||
|
||||
* Update to use Dataflow v2.0+
|
||||
|
||||
88
README.md
88
README.md
@@ -178,7 +178,7 @@ class MyDataflowType extends AbstractDataflowType
|
||||
/**
|
||||
* @var ContentStructureFactory
|
||||
*/
|
||||
private $contentStructureFactory;
|
||||
private contentStructureFactory;
|
||||
|
||||
public function __construct(ContentWriter $contentWriter, ContentStructureFactory $contentStructureFactory)
|
||||
{
|
||||
@@ -206,8 +206,6 @@ class MyDataflowType extends AbstractDataflowType
|
||||
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);
|
||||
$builder->addWriter($this->contentWriter);
|
||||
}
|
||||
}
|
||||
@@ -215,85 +213,6 @@ class MyDataflowType extends AbstractDataflowType
|
||||
|
||||
This example uses `ContentStructureFactory` to check if the content exists and returns the adequate `ContentStrucure` to pass to the content writer.
|
||||
|
||||
## Use the NotModifiedContentFilter
|
||||
|
||||
When updating contents, you might want to ignore contents where the update would not result in any actual changes in fields values. In that case, you can add the `NotModifiedContentFilter` as one of your steps.
|
||||
|
||||
```php
|
||||
// In your DataflowType
|
||||
public function __construct(NotModifiedContentFilter $notModifiedContentFilter)
|
||||
{
|
||||
$this->notModifiedContentFilter = $notModifiedContentFilter;
|
||||
}
|
||||
|
||||
//[...]
|
||||
protected function buildDataflow(DataflowBuilder $builder, array $options): void
|
||||
{
|
||||
//[...]
|
||||
// If you want the filter log
|
||||
$this->notModifiedContentFilter->setLogger($this->logger);
|
||||
$builder->addStep($this->notModifiedContentFilter);
|
||||
//[...]
|
||||
}
|
||||
```
|
||||
|
||||
This filter compares each field value in the `ContentUpdateStructure` received to the fields values in the existing content object. If all values are identical, this filter will return `false`, otherwise, the `ContentUpdateStructure` will be returned as is.
|
||||
|
||||
Not all field types are supported by this filter. Il a field type is not supported, values will be assumed different. If your dataflow is dealing with content types containing unsupported field types, it is better to simply not use the `NotModifiedContentFilter` to prevent unnecessary overhead.
|
||||
|
||||
### Supported field types
|
||||
- ezstring
|
||||
- ezauthor
|
||||
- ezboolean
|
||||
- ezcountry
|
||||
- ezdate
|
||||
- ezdatetime
|
||||
- ezemail
|
||||
- ezfloat
|
||||
- ezisbn
|
||||
- ezobjectrelation
|
||||
- ezobjectrelationlist
|
||||
- ezkeyword
|
||||
- ezselection
|
||||
- eztext
|
||||
- eztime
|
||||
- eztags
|
||||
- novaseometas
|
||||
- ezurl
|
||||
- ezmatrix
|
||||
- ezgmaplocation
|
||||
- ezrichtext
|
||||
|
||||
### Add custom field comparator
|
||||
|
||||
If you want to add support for a field type, simply create your own comparator.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator;
|
||||
use eZ\Publish\Core\FieldType\Value;
|
||||
//[...]
|
||||
|
||||
class MyFieldComparator extends AbstractFieldComparator
|
||||
{
|
||||
//[...]
|
||||
protected function compareValues(Value $currentValue, Value $newValue): bool
|
||||
{
|
||||
// Return true if values are identical, false if values are different.
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Service declaration
|
||||
App\FieldComparator\MyFieldComparator:
|
||||
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
tags:
|
||||
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'my_field_type_identifier' }
|
||||
```
|
||||
|
||||
# Admin UI
|
||||
|
||||
## Access to the eZ Dataflow UI
|
||||
@@ -383,10 +302,6 @@ Go to the eZ Dataflow admin UI and click on the "Oneshot" tab. Click on the "+"
|
||||
|
||||
Finally, click on the "Create" button.
|
||||
|
||||
# Rights
|
||||
|
||||
If a non-administrator user needs read-only access to the dataflow interface, add the `Setup / Administrate` and `eZ 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.
|
||||
@@ -400,3 +315,4 @@ already.
|
||||
# License
|
||||
|
||||
This package is licensed under the [MIT license](LICENSE).
|
||||
|
||||
|
||||
@@ -41,22 +41,18 @@
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3||^8.0",
|
||||
"code-rhapsodie/dataflow-bundle": "^3.0||^4.0",
|
||||
"ezsystems/ezplatform-admin-ui": "^2.3",
|
||||
"ezsystems/ezplatform-kernel": "^1.3"
|
||||
"code-rhapsodie/dataflow-bundle": "^2.0 || dev-master",
|
||||
"ezsystems/ezplatform-admin-ui": "^1.0",
|
||||
"ezsystems/ezpublish-kernel": "^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7||^8||^9",
|
||||
"phpunit/phpunit": "^7||^8",
|
||||
"doctrine/dbal": "^2.0"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"php-http/discovery": true
|
||||
}
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
||||
49
phpunit.xml
49
phpunit.xml
@@ -1,21 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version = '1.0' encoding = 'UTF-8'?>
|
||||
|
||||
<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" backupStaticAttributes="false" bootstrap="tests/bootstrap.php" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" colors="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
|
||||
<coverage>
|
||||
<include>
|
||||
<directory>./src/</directory>
|
||||
</include>
|
||||
<exclude>
|
||||
<directory>tests/</directory>
|
||||
<directory>vendor/</directory>
|
||||
</exclude>
|
||||
</coverage>
|
||||
<php>
|
||||
<ini name="error_reporting" value="-1"/>
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="EzDataflow tests suite">
|
||||
<directory suffix="Test.php">./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<phpunit
|
||||
backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="Tests/bootstrap.php"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
colors="false"
|
||||
>
|
||||
<php>
|
||||
<ini name="error_reporting" value="-1" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Port tests suite">
|
||||
<directory suffix="Test.php">./Tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./</directory>
|
||||
<exclude>
|
||||
<directory>Tests/</directory>
|
||||
<directory>vendor/</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
</phpunit>
|
||||
|
||||
@@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
namespace CodeRhapsodie\EzDataflowBundle;
|
||||
|
||||
use CodeRhapsodie\EzDataflowBundle\DependencyInjection\CodeRhapsodieEzDataflowExtension;
|
||||
use CodeRhapsodie\EzDataflowBundle\DependencyInjection\Compiler\FieldComparatorCompilerPass;
|
||||
use CodeRhapsodie\EzDataflowBundle\Security\PolicyProvider;
|
||||
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\EzPublishCoreExtension;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
@@ -24,8 +23,6 @@ class CodeRhapsodieEzDataflowBundle extends Bundle
|
||||
{
|
||||
parent::build($container);
|
||||
|
||||
$container->addCompilerPass(new FieldComparatorCompilerPass());
|
||||
|
||||
/** @var EzPublishCoreExtension $eZExtension */
|
||||
$eZExtension = $container->getExtension('ezpublish');
|
||||
$eZExtension->addPolicyProvider(new PolicyProvider());
|
||||
|
||||
@@ -4,14 +4,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Controller;
|
||||
|
||||
use CodeRhapsodie\DataflowBundle\Entity\Job;
|
||||
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
|
||||
use CodeRhapsodie\EzDataflowBundle\Form\CreateOneshotType;
|
||||
use CodeRhapsodie\EzDataflowBundle\Form\CreateScheduledType;
|
||||
use CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway;
|
||||
use CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway;
|
||||
use CodeRhapsodie\DataflowBundle\Entity\Job;
|
||||
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
use eZ\Publish\Core\MVC\Symfony\Security\Authorization\Attribute;
|
||||
use EzSystems\EzPlatformAdminUi\Notification\NotificationHandlerInterface;
|
||||
use EzSystems\EzPlatformAdminUiBundle\Controller\Controller;
|
||||
use Pagerfanta\Adapter\DoctrineDbalAdapter;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
@@ -26,17 +27,22 @@ class DashboardController extends Controller
|
||||
{
|
||||
/** @var JobGateway */
|
||||
private $jobGateway;
|
||||
/** @var NotificationHandlerInterface */
|
||||
private $notificationHandler;
|
||||
/** @var ScheduledDataflowGateway */
|
||||
private $scheduledDataflowGateway;
|
||||
|
||||
public function __construct(JobGateway $jobGateway, ScheduledDataflowGateway $scheduledDataflowGateway)
|
||||
public function __construct(JobGateway $jobGateway, NotificationHandlerInterface $notificationHandler, ScheduledDataflowGateway $scheduledDataflowGateway)
|
||||
{
|
||||
$this->jobGateway = $jobGateway;
|
||||
$this->notificationHandler = $notificationHandler;
|
||||
$this->scheduledDataflowGateway = $scheduledDataflowGateway;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/", name="coderhapsodie.ezdataflow.main")
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function main(): Response
|
||||
{
|
||||
@@ -63,6 +69,10 @@ class DashboardController extends Controller
|
||||
|
||||
/**
|
||||
* @Route("/repeating", name="coderhapsodie.ezdataflow.repeating")
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getRepeatingPage(Request $request): Response
|
||||
{
|
||||
@@ -91,6 +101,10 @@ class DashboardController extends Controller
|
||||
|
||||
/**
|
||||
* @Route("/oneshot", name="coderhapsodie.ezdataflow.oneshot")
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getOneshotPage(Request $request): Response
|
||||
{
|
||||
@@ -104,30 +118,35 @@ class DashboardController extends Controller
|
||||
public function history(Request $request): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
|
||||
$filter = (int) $request->query->get('filter', JobGateway::FILTER_NONE);
|
||||
|
||||
return $this->render('@ezdesign/ezdataflow/Dashboard/history.html.twig', [
|
||||
'pager' => $this->getPager($this->jobGateway->getListQueryForAdmin($filter), $request),
|
||||
'filter' => $filter,
|
||||
'pager' => $this->getPager($this->jobGateway->getListQueryForAdmin(), $request),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/history", name="coderhapsodie.ezdataflow.history")
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getHistoryPage(Request $request): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
|
||||
$filter = (int) $request->query->get('filter', JobGateway::FILTER_NONE);
|
||||
|
||||
return $this->render('@ezdesign/ezdataflow/Dashboard/history.html.twig', [
|
||||
'pager' => $this->getPager($this->jobGateway->getListQueryForAdmin($filter), $request),
|
||||
'filter' => $filter,
|
||||
'pager' => $this->getPager($this->jobGateway->getListQueryForAdmin(), $request),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/history/schedule/{id}", name="coderhapsodie.ezdataflow.history.workflow")
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getHistoryForScheduled(Request $request, int $id): Response
|
||||
{
|
||||
@@ -143,7 +162,6 @@ class DashboardController extends Controller
|
||||
{
|
||||
$pager = new Pagerfanta(new DoctrineDbalAdapter($query, function ($queryBuilder) {
|
||||
return $queryBuilder->select('COUNT(DISTINCT id) AS total_results')
|
||||
->resetQueryPart('orderBy')
|
||||
->setMaxResults(1);
|
||||
}));
|
||||
$pager->setMaxPerPage(20);
|
||||
|
||||
@@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @Route("/ezdataflow/job")
|
||||
@@ -26,7 +26,7 @@ class JobController extends Controller
|
||||
private $jobGateway;
|
||||
/** @var NotificationHandlerInterface */
|
||||
private $notificationHandler;
|
||||
/** @var Symfony\Component\Translation\TranslatorInterface|Symfony\Contracts\Translation\TranslatorInterface */
|
||||
/** @var TranslatorInterface */
|
||||
private $translator;
|
||||
|
||||
public function __construct(
|
||||
@@ -41,6 +41,10 @@ class JobController extends Controller
|
||||
|
||||
/**
|
||||
* @Route("/details/{id}", name="coderhapsodie.ezdataflow.job.details")
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function displayDetails(int $id): Response
|
||||
{
|
||||
@@ -51,24 +55,12 @@ class JobController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/details/log/{id}", name="coderhapsodie.ezdataflow.job.log")
|
||||
*/
|
||||
public function displayLog(int $id): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'view'));
|
||||
$item = $this->jobGateway->find($id);
|
||||
$log = array_map(function ($line) {
|
||||
return preg_replace('~#\d+~', "\n$0", $line);
|
||||
}, $item->getExceptions());
|
||||
|
||||
return $this->render('@ezdesign/ezdataflow/Item/log.html.twig', [
|
||||
'log' => $log,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/create", name="coderhapsodie.ezdataflow.job.create", methods={"POST"})
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function create(Request $request): Response
|
||||
{
|
||||
|
||||
@@ -4,11 +4,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Controller;
|
||||
|
||||
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
|
||||
use CodeRhapsodie\EzDataflowBundle\Form\CreateScheduledType;
|
||||
use CodeRhapsodie\EzDataflowBundle\Form\UpdateScheduledType;
|
||||
use CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway;
|
||||
use CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway;
|
||||
use CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway;
|
||||
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
|
||||
use eZ\Publish\Core\MVC\Symfony\Security\Authorization\Attribute;
|
||||
use EzSystems\EzPlatformAdminUi\Notification\NotificationHandlerInterface;
|
||||
use EzSystems\EzPlatformAdminUiBundle\Controller\Controller;
|
||||
@@ -16,7 +16,7 @@ use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @Route("/ezdataflow/scheduled_workflow")
|
||||
@@ -32,12 +32,8 @@ class ScheduledDataflowController extends Controller
|
||||
/** @var TranslatorInterface */
|
||||
private $translator;
|
||||
|
||||
public function __construct(
|
||||
JobGateway $jobGateway,
|
||||
NotificationHandlerInterface $notificationHandler,
|
||||
ScheduledDataflowGateway $scheduledDataflowGateway,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
public function __construct(JobGateway $jobGateway, NotificationHandlerInterface $notificationHandler, ScheduledDataflowGateway $scheduledDataflowGateway, TranslatorInterface $translator)
|
||||
{
|
||||
$this->jobGateway = $jobGateway;
|
||||
$this->notificationHandler = $notificationHandler;
|
||||
$this->scheduledDataflowGateway = $scheduledDataflowGateway;
|
||||
@@ -46,6 +42,10 @@ class ScheduledDataflowController extends Controller
|
||||
|
||||
/**
|
||||
* @Route("/create", name="coderhapsodie.ezdataflow.workflow.create", methods={"POST"})
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function create(Request $request): Response
|
||||
{
|
||||
@@ -58,12 +58,12 @@ class ScheduledDataflowController extends Controller
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
/** @var ScheduledDataflow $newWorkflow */
|
||||
$newWorkflow = $form->getData();
|
||||
|
||||
try {
|
||||
$this->scheduledDataflowGateway->save($newWorkflow);
|
||||
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ezdataflow.workflow.create.success'));
|
||||
} catch (\Exception $e) {
|
||||
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.workflow.create.error',
|
||||
['message' => $e->getMessage()]));
|
||||
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.workflow.create.error', ['message' => $e->getMessage()]));
|
||||
}
|
||||
|
||||
return new JsonResponse(['redirect' => $this->generateUrl('coderhapsodie.ezdataflow.main')]);
|
||||
@@ -79,6 +79,10 @@ class ScheduledDataflowController extends Controller
|
||||
|
||||
/**
|
||||
* @Route("/{id}/delete", name="coderhapsodie.ezdataflow.workflow.delete", methods={"post"})
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function delete(int $id): Response
|
||||
{
|
||||
@@ -90,8 +94,7 @@ class ScheduledDataflowController extends Controller
|
||||
|
||||
return new JsonResponse(['code' => 200]);
|
||||
} catch (\Exception $e) {
|
||||
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.workflow.delete.error',
|
||||
['message' => $e->getMessage()]));
|
||||
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.workflow.delete.error', ['message' => $e->getMessage()]));
|
||||
|
||||
return new JsonResponse(['code' => $e->getCode()]);
|
||||
}
|
||||
@@ -99,6 +102,11 @@ class ScheduledDataflowController extends Controller
|
||||
|
||||
/**
|
||||
* @Route("/{id}/edit", name="coderhapsodie.ezdataflow.workflow.edit")
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function edit(Request $request, int $id): Response
|
||||
{
|
||||
@@ -115,8 +123,7 @@ class ScheduledDataflowController extends Controller
|
||||
$this->scheduledDataflowGateway->save($editDataflow);
|
||||
$this->notificationHandler->success($this->translator->trans('coderhapsodie.ezdataflow.workflow.edit.success'));
|
||||
} catch (\Exception $e) {
|
||||
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.workflow.edit.error',
|
||||
['message' => $e->getMessage()]));
|
||||
$this->notificationHandler->error($this->translator->trans('coderhapsodie.ezdataflow.workflow.edit.error', ['message' => $e->getMessage()]));
|
||||
}
|
||||
|
||||
return new JsonResponse(['redirect' => $this->generateUrl('coderhapsodie.ezdataflow.main')]);
|
||||
@@ -132,6 +139,10 @@ class ScheduledDataflowController extends Controller
|
||||
|
||||
/**
|
||||
* @Route("/{id}/enable", name="coderhapsodie.ezdataflow.workflow.enable")
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function enableDataflow(int $id): Response
|
||||
{
|
||||
@@ -142,6 +153,22 @@ class ScheduledDataflowController extends Controller
|
||||
return $this->redirectToRoute('coderhapsodie.ezdataflow.main');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{id}/disable", name="coderhapsodie.ezdataflow.workflow.disable")
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function disableDataflow(int $id): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'edit'));
|
||||
|
||||
$this->changeDataflowStatus($id, false);
|
||||
|
||||
return $this->redirectToRoute('coderhapsodie.ezdataflow.main');
|
||||
}
|
||||
|
||||
private function changeDataflowStatus(int $id, bool $status)
|
||||
{
|
||||
try {
|
||||
@@ -155,16 +182,4 @@ class ScheduledDataflowController extends Controller
|
||||
$this->notificationHandler->error(sprintf('An error occured : "%s".', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{id}/disable", name="coderhapsodie.ezdataflow.workflow.disable")
|
||||
*/
|
||||
public function disableDataflow(int $id): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted(new Attribute('ezdataflow', 'edit'));
|
||||
|
||||
$this->changeDataflowStatus($id, false);
|
||||
|
||||
return $this->redirectToRoute('coderhapsodie.ezdataflow.main');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ class ContentCreator implements ContentCreatorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContentCreateStructure $structure
|
||||
*
|
||||
* @return Content
|
||||
*
|
||||
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
|
||||
* @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
|
||||
* @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException
|
||||
@@ -54,21 +58,17 @@ class ContentCreator implements ContentCreatorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $locations
|
||||
*
|
||||
* @return LocationCreateStruct[]
|
||||
*/
|
||||
private function getLocationCreateStructs(array $locations): array
|
||||
{
|
||||
$locationCreateStructs = [];
|
||||
|
||||
foreach ($locations as $locationOrIdOrRemoteIdOrStruct) {
|
||||
if ($locationOrIdOrRemoteIdOrStruct instanceof LocationCreateStruct) {
|
||||
$locationCreateStructs[] = $locationOrIdOrRemoteIdOrStruct;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($locations as $locationOrIdOrRemoteId) {
|
||||
$locationCreateStructs[] = new LocationCreateStruct([
|
||||
'parentLocationId' => $this->matcher->matchLocation($locationOrIdOrRemoteIdOrStruct)->id,
|
||||
'parentLocationId' => $this->matcher->matchLocation($locationOrIdOrRemoteId)->id,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@ class ContentUpdater implements ContentUpdaterInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContentUpdateStructure $structure
|
||||
*
|
||||
* @return Content
|
||||
*
|
||||
* @throws NoMatchFoundException
|
||||
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
|
||||
* @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
|
||||
|
||||
@@ -17,6 +17,8 @@ class ContentStructFieldFiller implements ContentStructFieldFillerInterface
|
||||
|
||||
/**
|
||||
* ContentStructFieldFiller constructor.
|
||||
*
|
||||
* @param iterable $fieldValueCreators
|
||||
*/
|
||||
public function __construct(iterable $fieldValueCreators)
|
||||
{
|
||||
@@ -45,7 +47,10 @@ class ContentStructFieldFiller implements ContentStructFieldFillerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $hash
|
||||
* @param string $fieldTypeIdentifier
|
||||
* @param mixed $hash
|
||||
*
|
||||
* @return Value
|
||||
*
|
||||
* @throws UnsupportedFieldTypeException
|
||||
*/
|
||||
|
||||
@@ -9,5 +9,10 @@ use eZ\Publish\API\Repository\Values\ContentType\ContentType;
|
||||
|
||||
interface ContentStructFieldFillerInterface
|
||||
{
|
||||
/**
|
||||
* @param ContentType $contentType
|
||||
* @param ContentStruct $contentStruct
|
||||
* @param array $fieldHashes
|
||||
*/
|
||||
public function fillFields(ContentType $contentType, ContentStruct $contentStruct, array $fieldHashes): void;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Core\Field;
|
||||
|
||||
use eZ\Publish\API\Repository\FieldType;
|
||||
use eZ\Publish\API\Repository\FieldTypeService;
|
||||
use eZ\Publish\Core\FieldType\Value;
|
||||
|
||||
@@ -12,6 +13,9 @@ class DefaultFieldValueCreator implements FieldValueCreatorInterface
|
||||
/** @var FieldTypeService */
|
||||
private $fieldTypeService;
|
||||
|
||||
/** @var FieldType[] */
|
||||
private $fieldTypes = [];
|
||||
|
||||
public function __construct(FieldTypeService $fieldTypeService)
|
||||
{
|
||||
$this->fieldTypeService = $fieldTypeService;
|
||||
@@ -24,6 +28,22 @@ class DefaultFieldValueCreator implements FieldValueCreatorInterface
|
||||
|
||||
public function createValue(string $fieldTypeIdentifier, $hash): Value
|
||||
{
|
||||
return $this->fieldTypeService->getFieldType($fieldTypeIdentifier)->fromHash($hash);
|
||||
return $this->getFieldType($fieldTypeIdentifier)->fromHash($hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fieldTypeIdentifier
|
||||
*
|
||||
* @return FieldType
|
||||
*
|
||||
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
|
||||
*/
|
||||
private function getFieldType(string $fieldTypeIdentifier): FieldType
|
||||
{
|
||||
if (!isset($this->fieldTypes[$fieldTypeIdentifier])) {
|
||||
$this->fieldTypes[$fieldTypeIdentifier] = $this->fieldTypeService->getFieldType($fieldTypeIdentifier);
|
||||
}
|
||||
|
||||
return $this->fieldTypes[$fieldTypeIdentifier];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,18 @@ use eZ\Publish\Core\FieldType\Value;
|
||||
|
||||
interface FieldValueCreatorInterface
|
||||
{
|
||||
/**
|
||||
* @param string $fieldTypeIdentifier
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supports(string $fieldTypeIdentifier): bool;
|
||||
|
||||
/**
|
||||
* @param mixed $hash
|
||||
* @param string $fieldTypeIdentifier
|
||||
* @param mixed $hash
|
||||
*
|
||||
* @return Value
|
||||
*/
|
||||
public function createValue(string $fieldTypeIdentifier, $hash): Value;
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
|
||||
|
||||
use eZ\Publish\API\Repository\FieldTypeService;
|
||||
use eZ\Publish\API\Repository\Values\Content\Field;
|
||||
use eZ\Publish\Core\FieldType\Value;
|
||||
|
||||
abstract class AbstractFieldComparator implements FieldComparatorInterface
|
||||
{
|
||||
/** @var FieldTypeService */
|
||||
private $fieldTypeService;
|
||||
|
||||
public function __construct(FieldTypeService $fieldTypeService)
|
||||
{
|
||||
$this->fieldTypeService = $fieldTypeService;
|
||||
}
|
||||
|
||||
public function compare(Field $field, $hash): bool
|
||||
{
|
||||
$newValue = $this->fieldTypeService->getFieldType($field->fieldTypeIdentifier)->fromHash($hash);
|
||||
|
||||
return $this->compareValues($field->value, $newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if values are equals, false otherwise.
|
||||
*/
|
||||
abstract protected function compareValues(Value $currentValue, Value $newValue): bool;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
|
||||
|
||||
use eZ\Publish\API\Repository\Values\Content\Field;
|
||||
|
||||
class DelegatorFieldComparator implements FieldComparatorInterface
|
||||
{
|
||||
/** @var FieldComparatorInterface[] */
|
||||
private $delegates;
|
||||
|
||||
/**
|
||||
* FieldComparator constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->delegates = [];
|
||||
}
|
||||
|
||||
public function compare(Field $field, $hash): bool
|
||||
{
|
||||
if (isset($this->delegates[$field->fieldTypeIdentifier])) {
|
||||
return $this->delegates[$field->fieldTypeIdentifier]->compare($field, $hash);
|
||||
}
|
||||
|
||||
// No comparator to handle this field type, we assume the value is different.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function registerDelegateFieldComparator(FieldComparatorInterface $typedFieldComparator, string $fieldTypeIdentifier): void
|
||||
{
|
||||
$this->delegates[$fieldTypeIdentifier] = $typedFieldComparator;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
|
||||
|
||||
use eZ\Publish\API\Repository\Values\Content\Field;
|
||||
|
||||
interface FieldComparatorInterface
|
||||
{
|
||||
/**
|
||||
* @return bool true if identical, false otherwise
|
||||
*/
|
||||
public function compare(Field $field, $hash): bool;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
|
||||
|
||||
use eZ\Publish\Core\FieldType\Value;
|
||||
|
||||
class MapLocationFieldComparator extends AbstractFieldComparator
|
||||
{
|
||||
protected function compareValues(Value $currentValue, Value $newValue): bool
|
||||
{
|
||||
return (string) $currentValue === (string) $newValue
|
||||
&& (float) $currentValue->longitude === (float) $newValue->longitude
|
||||
&& (float) $currentValue->latitude === (float) $newValue->latitude
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
|
||||
|
||||
use eZ\Publish\Core\FieldType\Value;
|
||||
|
||||
class MatrixFieldComparator extends AbstractFieldComparator
|
||||
{
|
||||
protected function compareValues(Value $currentValue, Value $newValue): bool
|
||||
{
|
||||
if (count($currentValue->rows) !== count($newValue->rows)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($newValue->rows as $index => $row) {
|
||||
if (count($currentValue->rows[$index]->getCells()) !== count($row->getCells())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty(array_diff_assoc($currentValue->rows[$index]->getCells(), $row->getCells()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
|
||||
|
||||
use eZ\Publish\Core\FieldType\Value;
|
||||
|
||||
class NovaSEOMetasFieldComparator extends AbstractFieldComparator
|
||||
{
|
||||
protected function compareValues(Value $currentValue, Value $newValue): bool
|
||||
{
|
||||
$map = [];
|
||||
foreach ($currentValue->metas as $meta) {
|
||||
$map[$meta->getName()] = $meta->getContent();
|
||||
}
|
||||
|
||||
foreach ($newValue->metas as $meta) {
|
||||
if (!isset($map[$meta->getName()]) || $map[$meta->getName()] !== $meta->getContent()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return count($currentValue->metas) === count($newValue->metas);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
|
||||
|
||||
use eZ\Publish\Core\FieldType\Value;
|
||||
|
||||
class SimpleFieldComparator extends AbstractFieldComparator
|
||||
{
|
||||
protected function compareValues(Value $currentValue, Value $newValue): bool
|
||||
{
|
||||
return (string) $currentValue === (string) $newValue;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Core\FieldComparator;
|
||||
|
||||
use eZ\Publish\Core\FieldType\Value;
|
||||
|
||||
class UrlFieldComparator extends AbstractFieldComparator
|
||||
{
|
||||
protected function compareValues(Value $currentValue, Value $newValue): bool
|
||||
{
|
||||
return $currentValue->link === $newValue->link && $currentValue->text === $newValue->text;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\DependencyInjection\Compiler;
|
||||
|
||||
use CodeRhapsodie\EzDataflowBundle\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)
|
||||
{
|
||||
if (!$container->has(DelegatorFieldComparator::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$delegatorDef = $container->findDefinition(DelegatorFieldComparator::class);
|
||||
|
||||
foreach ($container->findTaggedServiceIds('coderhapsodie.ezdataflow.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));
|
||||
}
|
||||
|
||||
$delegatorDef->addMethodCall(
|
||||
'registerDelegateFieldComparator',
|
||||
[new Reference($id), $attributes['fieldType']]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ class InvalidArgumentTypeException extends \Exception
|
||||
/**
|
||||
* @param string|array $expectedTypes
|
||||
* @param mixed $received
|
||||
*
|
||||
* @return InvalidArgumentTypeException
|
||||
*/
|
||||
public static function create($expectedTypes, $received): self
|
||||
{
|
||||
|
||||
@@ -6,6 +6,12 @@ namespace CodeRhapsodie\EzDataflowBundle\Exception;
|
||||
|
||||
class UnknownFieldException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @param string $fieldIdentifier
|
||||
* @param string $contentTypeIdentifier
|
||||
*
|
||||
* @return UnknownFieldException
|
||||
*/
|
||||
public static function create(string $fieldIdentifier, string $contentTypeIdentifier): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
|
||||
@@ -19,6 +19,8 @@ final class ContentStructureFactory implements ContentStructureFactoryInterface
|
||||
|
||||
/**
|
||||
* ContentStructureFactory constructor.
|
||||
*
|
||||
* @param ContentService $contentService
|
||||
*/
|
||||
public function __construct(ContentService $contentService)
|
||||
{
|
||||
@@ -26,8 +28,12 @@ final class ContentStructureFactory implements ContentStructureFactoryInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $parentLocations
|
||||
* @param int $mode One of the constant ContentStructureFactoryInterface::MODE_*
|
||||
* @param array $data
|
||||
* @param string $remoteId
|
||||
* @param string $language
|
||||
* @param string $contentType
|
||||
* @param mixed $parentLocations
|
||||
* @param int $mode One of the constant ContentStructureFactoryInterface::MODE_*
|
||||
*
|
||||
* @return false|ContentStructure
|
||||
*
|
||||
|
||||
@@ -11,6 +11,10 @@ interface ContentStructureFactoryInterface
|
||||
public const MODE_UPDATE_ONLY = 3;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param string $remoteId
|
||||
* @param string $language
|
||||
* @param string $contentType
|
||||
* @param int|string $parentLocations Int for location id or string for remote location id
|
||||
* @param int $mode ContentStructureFactoryInterface
|
||||
*
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Filter;
|
||||
|
||||
use CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface;
|
||||
use CodeRhapsodie\EzDataflowBundle\Model\ContentUpdateStructure;
|
||||
use eZ\Publish\API\Repository\ContentService;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* Filters ContentUpdateStructure that would not result in any actual changes in the content.
|
||||
*/
|
||||
class NotModifiedContentFilter
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/** @var ContentService */
|
||||
private $contentService;
|
||||
|
||||
/** @var FieldComparatorInterface */
|
||||
private $comparator;
|
||||
|
||||
public function __construct(ContentService $contentService, FieldComparatorInterface $comparator)
|
||||
{
|
||||
$this->contentService = $contentService;
|
||||
$this->comparator = $comparator;
|
||||
}
|
||||
|
||||
public function __invoke($data)
|
||||
{
|
||||
if (!$data instanceof ContentUpdateStructure) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($data->getId()) {
|
||||
$content = $this->contentService->loadContent($data->getId(), [$data->getLanguageCode()]);
|
||||
} else {
|
||||
$content = $this->contentService->loadContentByRemoteId($data->getRemoteId(), [$data->getLanguageCode()]);
|
||||
}
|
||||
|
||||
foreach ($data->getFields() as $identifier => $hash) {
|
||||
$field = $content->getField($identifier, $data->getLanguageCode());
|
||||
if (null === $field || !$this->comparator->compare($field, $hash)) {
|
||||
// At least one field is different, continue the dataflow.
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
// All fields are identical, filter this item out.
|
||||
$this->log('info', 'Not modified content skipped', ['id' => $data->getId(), 'remote_id' => $data->getRemoteId()]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function log(string $level, string $message, array $context = [])
|
||||
{
|
||||
if (null === $this->logger) {
|
||||
return;
|
||||
}
|
||||
$this->logger->log($level, $message, $context);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ namespace CodeRhapsodie\EzDataflowBundle\Form;
|
||||
|
||||
use CodeRhapsodie\DataflowBundle\Entity\Job;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
@@ -29,7 +30,7 @@ class CreateOneshotType extends AbstractType
|
||||
'placeholder' => 'coderhapsodie.dataflow.options.placeholder',
|
||||
],
|
||||
])
|
||||
->add('requestedDate', UserTimezoneAwareDateTimeType::class, [
|
||||
->add('requestedDate', DateTimeType::class, [
|
||||
'label' => 'coderhapsodie.dataflow.requestedDate',
|
||||
'years' => range(date('Y'), date('Y') + 5),
|
||||
])
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace CodeRhapsodie\EzDataflowBundle\Form;
|
||||
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
@@ -37,7 +38,7 @@ class CreateScheduledType extends AbstractType
|
||||
],
|
||||
'label' => 'coderhapsodie.dataflow.frequency',
|
||||
])
|
||||
->add('next', UserTimezoneAwareDateTimeType::class, [
|
||||
->add('next', DateTimeType::class, [
|
||||
'years' => range(date('Y'), date('Y') + 5),
|
||||
'label' => 'coderhapsodie.dataflow.create.next',
|
||||
])
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace CodeRhapsodie\EzDataflowBundle\Form;
|
||||
|
||||
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
@@ -31,7 +32,7 @@ class UpdateScheduledType extends AbstractType
|
||||
],
|
||||
'label' => 'coderhapsodie.dataflow.frequency',
|
||||
])
|
||||
->add('next', UserTimezoneAwareDateTimeType::class, [
|
||||
->add('next', DateTimeType::class, [
|
||||
'years' => range(date('Y'), date('Y') + 5),
|
||||
'label' => 'coderhapsodie.dataflow.update.next',
|
||||
])
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Form;
|
||||
|
||||
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
|
||||
use eZ\Publish\API\Repository\UserPreferenceService;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
|
||||
class UserTimezoneAwareDateTimeTransformer implements DataTransformerInterface
|
||||
{
|
||||
/** @var UserPreferenceService */
|
||||
private $userPreferenceService;
|
||||
|
||||
public function __construct(UserPreferenceService $userPreferenceService)
|
||||
{
|
||||
$this->userPreferenceService = $userPreferenceService;
|
||||
}
|
||||
|
||||
public function transform($value)
|
||||
{
|
||||
if (!$value instanceof \DateTimeInterface) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return (new \DateTime('now', $this->userTimezone()))->setTimestamp($value->getTimestamp());
|
||||
}
|
||||
|
||||
public function reverseTransform($value)
|
||||
{
|
||||
if (!$value instanceof \DateTimeInterface) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$dateTimeWithUserTimeZone = new \DateTime($value->format('Y-m-d H:i:s'), $this->userTimezone());
|
||||
|
||||
return (new \DateTime())->setTimestamp($dateTimeWithUserTimeZone->getTimestamp());
|
||||
}
|
||||
|
||||
private function userTimezone(): \DateTimeZone
|
||||
{
|
||||
try {
|
||||
$tz = $this->userPreferenceService->getUserPreference('timezone')->value ?? 'UTC';
|
||||
} catch (NotFoundException $e) {
|
||||
$tz = 'UTC';
|
||||
}
|
||||
|
||||
return new \DateTimeZone($tz);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Form;
|
||||
|
||||
use eZ\Publish\API\Repository\UserPreferenceService;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class UserTimezoneAwareDateTimeType extends AbstractType
|
||||
{
|
||||
/** @var UserPreferenceService */
|
||||
private $userPreferenceService;
|
||||
|
||||
public function __construct(UserPreferenceService $userPreferenceService)
|
||||
{
|
||||
$this->userPreferenceService = $userPreferenceService;
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return DateTimeType::class;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->addModelTransformer(new UserTimezoneAwareDateTimeTransformer($this->userPreferenceService));
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,6 @@ use Doctrine\DBAL\Query\QueryBuilder;
|
||||
|
||||
final class JobGateway
|
||||
{
|
||||
public const FILTER_NONE = 0;
|
||||
public const FILTER_NON_EMPTY = 1;
|
||||
|
||||
/** @var JobRepository */
|
||||
private $jobRepository;
|
||||
|
||||
@@ -33,17 +30,10 @@ final class JobGateway
|
||||
->addOrderBy('i.requested_date', 'DESC');
|
||||
}
|
||||
|
||||
public function getListQueryForAdmin(int $filter): QueryBuilder
|
||||
public function getListQueryForAdmin(): QueryBuilder
|
||||
{
|
||||
$qb = $this->jobRepository->createQueryBuilder('w')
|
||||
->addOrderBy('w.requested_date', 'DESC')
|
||||
;
|
||||
|
||||
if (self::FILTER_NON_EMPTY === $filter) {
|
||||
$qb->andWhere('w.count > 0');
|
||||
}
|
||||
|
||||
return $qb;
|
||||
return $this->jobRepository->createQueryBuilder('w')
|
||||
->addOrderBy('w.requested_date', 'DESC');
|
||||
}
|
||||
|
||||
public function getListQueryForScheduleAdmin(int $id): QueryBuilder
|
||||
@@ -54,6 +44,9 @@ final class JobGateway
|
||||
->addOrderBy('w.requested_date', 'DESC');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Job $job
|
||||
*/
|
||||
public function save(Job $job)
|
||||
{
|
||||
$this->jobRepository->save($job);
|
||||
|
||||
@@ -29,12 +29,17 @@ final class ScheduledDataflowGateway
|
||||
->addOrderBy('s.label', 'ASC');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ScheduledDataflow $scheduledDataflow
|
||||
*/
|
||||
public function save(ScheduledDataflow $scheduledDataflow)
|
||||
{
|
||||
$this->scheduledDataflowRepository->save($scheduledDataflow);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function delete(int $id): void
|
||||
|
||||
@@ -22,6 +22,8 @@ class LocationMatcher implements LocationMatcherInterface
|
||||
/**
|
||||
* @param mixed $valueToMatch
|
||||
*
|
||||
* @return Location
|
||||
*
|
||||
* @throws NoMatchFoundException
|
||||
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
|
||||
*/
|
||||
|
||||
@@ -10,6 +10,8 @@ interface LocationMatcherInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $valueToMatch
|
||||
*
|
||||
* @return Location
|
||||
*/
|
||||
public function matchLocation($valueToMatch): Location;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ namespace CodeRhapsodie\EzDataflowBundle\Model;
|
||||
|
||||
use CodeRhapsodie\EzDataflowBundle\Exception\InvalidArgumentTypeException;
|
||||
use eZ\Publish\API\Repository\Values\Content\Location;
|
||||
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
|
||||
|
||||
class ContentCreateStructure extends ContentStructure
|
||||
{
|
||||
@@ -19,14 +18,17 @@ class ContentCreateStructure extends ContentStructure
|
||||
/**
|
||||
* ContentCreateStructure constructor.
|
||||
*
|
||||
* @param array $locations
|
||||
* A location can be any of the following:
|
||||
* <ul>
|
||||
* <li>an integer, the id of the Location object</li>
|
||||
* <li>a string, the remote id of the Location object</li>
|
||||
* <li>a Location object</li>
|
||||
* <li>a LocationCreateStruct object</li>
|
||||
* </ul>
|
||||
* @param string $contentTypeIdentifier
|
||||
* @param string $languageCode
|
||||
* @param array $locations
|
||||
* A location can be any of the following:
|
||||
* <ul>
|
||||
* <li>an integer, the id of the Location object</li>
|
||||
* <li>a string, the remote id of the Location object</li>
|
||||
* <li>a Location object</li>
|
||||
* </ul>
|
||||
* @param array $fields
|
||||
* @param string|null $remoteId
|
||||
*
|
||||
* @throws InvalidArgumentTypeException
|
||||
*/
|
||||
@@ -39,28 +41,35 @@ class ContentCreateStructure extends ContentStructure
|
||||
$this->remoteId = $remoteId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getContentTypeIdentifier(): string
|
||||
{
|
||||
return $this->contentTypeIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getLocations(): array
|
||||
{
|
||||
return $this->locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $locations
|
||||
*
|
||||
* @throws InvalidArgumentTypeException
|
||||
*/
|
||||
private function setLocations(array $locations)
|
||||
{
|
||||
foreach ($locations as $locationOrIdOrRemoteIdOrStruct) {
|
||||
if (!is_int($locationOrIdOrRemoteIdOrStruct)
|
||||
&& !is_string($locationOrIdOrRemoteIdOrStruct)
|
||||
&& !$locationOrIdOrRemoteIdOrStruct instanceof Location
|
||||
&& !$locationOrIdOrRemoteIdOrStruct instanceof LocationCreateStruct
|
||||
foreach ($locations as $locationOrIdOrRemoteId) {
|
||||
if (!is_int($locationOrIdOrRemoteId)
|
||||
&& !is_string($locationOrIdOrRemoteId)
|
||||
&& !$locationOrIdOrRemoteId instanceof Location
|
||||
) {
|
||||
throw InvalidArgumentTypeException::create(['int', 'string', Location::class, LocationCreateStruct::class], $locationOrIdOrRemoteIdOrStruct);
|
||||
throw InvalidArgumentTypeException::create(['int', 'string', Location::class], $locationOrIdOrRemoteId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,16 +15,25 @@ abstract class ContentStructure
|
||||
/** @var array */
|
||||
protected $fields;
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRemoteId(): ?string
|
||||
{
|
||||
return $this->remoteId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguageCode(): string
|
||||
{
|
||||
return $this->languageCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getFields(): array
|
||||
{
|
||||
return $this->fields;
|
||||
|
||||
@@ -15,6 +15,13 @@ class ContentUpdateStructure extends ContentStructure
|
||||
$this->fields = $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $languageCode
|
||||
* @param array $fields
|
||||
*
|
||||
* @return ContentUpdateStructure
|
||||
*/
|
||||
public static function createForContentId(int $id, string $languageCode, array $fields): self
|
||||
{
|
||||
$struct = new self($languageCode, $fields);
|
||||
@@ -23,6 +30,13 @@ class ContentUpdateStructure extends ContentStructure
|
||||
return $struct;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $remoteId
|
||||
* @param string $languageCode
|
||||
* @param array $fields
|
||||
*
|
||||
* @return ContentUpdateStructure
|
||||
*/
|
||||
public static function createForContentRemoteId(string $remoteId, string $languageCode, array $fields): self
|
||||
{
|
||||
$struct = new self($languageCode, $fields);
|
||||
@@ -31,6 +45,9 @@ class ContentUpdateStructure extends ContentStructure
|
||||
return $struct;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
imports:
|
||||
- { resource: services/comparators.yaml }
|
||||
|
||||
services:
|
||||
_defaults:
|
||||
public: false
|
||||
@@ -9,39 +6,25 @@ services:
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Controller\DashboardController:
|
||||
public: true
|
||||
tags:
|
||||
- { name: controller.service_arguments }
|
||||
arguments:
|
||||
$jobGateway: '@CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway'
|
||||
$notificationHandler: '@EzSystems\EzPlatformAdminUi\Notification\NotificationHandlerInterface'
|
||||
$scheduledDataflowGateway: '@CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway'
|
||||
calls:
|
||||
- ['setContainer', ['@service_container']]
|
||||
- ['performAccessCheck', []]
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Controller\ScheduledDataflowController:
|
||||
public: true
|
||||
tags:
|
||||
- { name: controller.service_arguments }
|
||||
arguments:
|
||||
$jobGateway: '@CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway'
|
||||
$notificationHandler: '@EzSystems\EzPlatformAdminUi\Notification\NotificationHandlerInterface'
|
||||
$scheduledDataflowGateway: '@CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway'
|
||||
$translator: '@translator'
|
||||
calls:
|
||||
- [ 'setContainer', [ '@service_container' ] ]
|
||||
- [ 'performAccessCheck', [ ] ]
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Controller\JobController:
|
||||
public: true
|
||||
tags:
|
||||
- { name: controller.service_arguments }
|
||||
arguments:
|
||||
$jobGateway: '@CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway'
|
||||
$notificationHandler: '@EzSystems\EzPlatformAdminUi\Notification\NotificationHandlerInterface'
|
||||
$translator: '@translator'
|
||||
calls:
|
||||
- [ 'setContainer', [ '@service_container' ] ]
|
||||
- [ 'performAccessCheck', [ ] ]
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Writer\RepositoryWriter:
|
||||
abstract: true
|
||||
@@ -116,11 +99,6 @@ services:
|
||||
CodeRhapsodie\EzDataflowBundle\Form\CreateOneshotType:
|
||||
tags: ['form.type']
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Form\UserTimezoneAwareDateTimeType:
|
||||
arguments:
|
||||
$userPreferenceService: '@eZ\Publish\API\Repository\UserPreferenceService'
|
||||
tags: ['form.type']
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway:
|
||||
arguments:
|
||||
$scheduledDataflowRepository: '@CodeRhapsodie\DataflowBundle\Repository\ScheduledDataflowRepository'
|
||||
@@ -132,48 +110,17 @@ services:
|
||||
CodeRhapsodie\EzDataflowBundle\Tab\RepeatingTab:
|
||||
parent: EzSystems\EzPlatformAdminUi\Tab\AbstractTab
|
||||
public: false
|
||||
arguments:
|
||||
$httpKernelRuntime: '@twig.runtime.httpkernel'
|
||||
tags:
|
||||
- {name: ezplatform.tab, group: coderhapsodie-ezdataflow}
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Tab\OneshotTab:
|
||||
parent: EzSystems\EzPlatformAdminUi\Tab\AbstractTab
|
||||
public: false
|
||||
arguments:
|
||||
$httpKernelRuntime: '@twig.runtime.httpkernel'
|
||||
tags:
|
||||
- {name: ezplatform.tab, group: coderhapsodie-ezdataflow}
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Tab\HistoryTab:
|
||||
parent: EzSystems\EzPlatformAdminUi\Tab\AbstractTab
|
||||
public: false
|
||||
arguments:
|
||||
$httpKernelRuntime: '@twig.runtime.httpkernel'
|
||||
tags:
|
||||
- {name: ezplatform.tab, group: coderhapsodie-ezdataflow}
|
||||
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Filter\NotModifiedContentFilter:
|
||||
arguments:
|
||||
$contentService: '@eZ\Publish\API\Repository\ContentService'
|
||||
$comparator: '@CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface'
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface: '@CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\DelegatorFieldComparator'
|
||||
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\DelegatorFieldComparator:
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator:
|
||||
arguments:
|
||||
$fieldTypeService: '@eZ\Publish\API\Repository\FieldTypeService'
|
||||
abstract: true
|
||||
|
||||
_cr.admin_tabs.ezdataflow_group:
|
||||
parent: EzSystems\EzPlatformAdminUi\Component\TabsComponent
|
||||
autowire: true
|
||||
autoconfigure: false
|
||||
public: false
|
||||
arguments:
|
||||
$template: '@@ezdesign/ezdataflow/parts/tab/ezdataflow.html.twig'
|
||||
$groupIdentifier: 'coderhapsodie-ezdataflow'
|
||||
tags:
|
||||
- { name: ezplatform.admin_ui.component, group: 'coderhapsodie-ezdataflow' }
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
services:
|
||||
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\SimpleFieldComparator:
|
||||
parent: 'CodeRhapsodie\EzDataflowBundle\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' }
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\UrlFieldComparator:
|
||||
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
tags:
|
||||
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezurl' }
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\NovaSEOMetasFieldComparator:
|
||||
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
tags:
|
||||
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'novaseometas' }
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\MatrixFieldComparator:
|
||||
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
tags:
|
||||
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezmatrix' }
|
||||
|
||||
CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\MapLocationFieldComparator:
|
||||
parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
tags:
|
||||
- { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'ezgmaplocation' }
|
||||
@@ -21,15 +21,10 @@ 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: 'Items count'
|
||||
coderhapsodie.ezdataflow.history.list.error_count: 'Errors count'
|
||||
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
|
||||
@@ -41,18 +36,16 @@ 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.count: 'Items count'
|
||||
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.'
|
||||
|
||||
@@ -40,26 +40,24 @@ 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.create.error: 'Une erreur est survenue lors de l''ajout de la programamtion du dataflow : "%message%".'
|
||||
coderhapsodie.ezdataflow.workflow.delete.success: 'La programmation du dataflow a bien été supprimé.'
|
||||
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.dataflow.label: 'Nom de la programmation du dataflow'
|
||||
coderhapsodie.dataflow.label: 'Nom de la programamtion du dataflow'
|
||||
coderhapsodie.dataflow.oneshot.label: 'Nom de l''exécution ponctuelle du dataflow'
|
||||
coderhapsodie.dataflow.dataflowType: 'Dataflow à exécuter'
|
||||
coderhapsodie.dataflow.dataflowType: 'Dataflow a exécuter'
|
||||
coderhapsodie.dataflow.options: 'Options passées au dataflow (YAML)'
|
||||
coderhapsodie.dataflow.options.title: 'Entrez les options comme un tableau clé/valeur YAML'
|
||||
coderhapsodie.dataflow.options.placeholder: "option1: valeur1\noption2: valeur2\n"
|
||||
@@ -72,6 +70,6 @@ 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.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.success: 'La programmation du dataflow a été mis à 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'
|
||||
|
||||
@@ -2,34 +2,6 @@
|
||||
|
||||
<div class="ez-table-header">
|
||||
<div class="ez-table-header__headline">{{ 'coderhapsodie.ezdataflow.history.list.title'|trans }}</div>
|
||||
<div class="ez-table-header__tools">
|
||||
<label for="ezdataflow_history_filter">{{ 'coderhapsodie.ezdataflow.history.filter.label'|trans }}</label>
|
||||
<select id="ezdataflow_history_filter" name="filter">
|
||||
<option value="0" {{ filter == 0 ? 'selected="selected"' }}>{{ 'coderhapsodie.ezdataflow.history.filter.none'|trans }}</option>
|
||||
<option value="1" {{ filter == 1 ? 'selected="selected"' }}>{{ 'coderhapsodie.ezdataflow.history.filter.non_empty_only'|trans }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include '@ezdesign/ezdataflow/parts/tab/job_list.html.twig' with {
|
||||
identifier: 'ezdataflow_history_results',
|
||||
paginate_route: 'coderhapsodie.ezdataflow.history',
|
||||
paginate_params: {'filter': filter}
|
||||
} %}
|
||||
|
||||
<script>
|
||||
(function ($) {
|
||||
$(document).ready(function ($) {
|
||||
// Manage ajax pagination
|
||||
$('#ezdataflow_history_filter').change(function (e) {
|
||||
e.preventDefault();
|
||||
$('#loading_ezdataflow_history_results').removeClass('d-none');
|
||||
$('#ezdataflow_history_results')
|
||||
.html('')
|
||||
.load('{{ path('coderhapsodie.ezdataflow.history') }}?filter=' + this.value + ' #ezdataflow_history_results>*', null, function () {
|
||||
$('#loading_ezdataflow_history_results').addClass('d-none');
|
||||
});
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
||||
</script>
|
||||
{% include '@ezdesign/ezdataflow/parts/tab/job_list.html.twig' with {identifier: 'ezdataflow_history_results', paginate_route: 'coderhapsodie.ezdataflow.history'} %}
|
||||
@@ -1,23 +1,21 @@
|
||||
{% extends ["@ezdesign/layout.html.twig", "@ezdesign/ui/layout.html.twig"] %}
|
||||
|
||||
{% block body_class %}ez-has-full-width-footer{% endblock %}
|
||||
{% extends "@ezdesign/layout.html.twig" %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{% include ['@ezdesign/parts/breadcrumbs.html.twig', '@ezdesign/ui/breadcrumbs.html.twig'] with { items: [
|
||||
{% include '@ezdesign/parts/breadcrumbs.html.twig' with { items: [
|
||||
{ value: 'breadcrumb.admin'|trans(domain='messages')|desc('Admin') },
|
||||
{ value: 'coderhapsodie.ezdataflow'|trans|desc('EzDataflow') }
|
||||
]} %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_title %}
|
||||
{% include ['@ezdesign/parts/page_title.html.twig', '@ezdesign/ui/page_title.html.twig'] with {
|
||||
{% include '@ezdesign/parts/page_title.html.twig' with {
|
||||
title: 'coderhapsodie.ezdataflow'|trans|desc('EzDataflow'),
|
||||
iconName: 'workflow'
|
||||
} %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ ez_render_component_group('coderhapsodie-ezdataflow', {'filter': app.request.query.get('filter', 0)}, '@ezdesign/ezdataflow/parts/tab/ezdataflow.html.twig') }}
|
||||
{{ ez_platform_tabs('coderhapsodie-ezdataflow', {}, '@ezdesign/ezdataflow/parts/tab/ezdataflow.html.twig') }}
|
||||
|
||||
<div class="modal fade ez-modal show" id="ez-modal--history-details" tabindex="-1" role="dialog" aria-modal="true">
|
||||
<div class="modal-dialog" role="document" style="max-width: 90%">
|
||||
@@ -44,10 +42,6 @@
|
||||
$('.history-details-aware').delegate('.modal-history-details', 'click', function (e) {
|
||||
e.preventDefault();
|
||||
$('#modal_content-details').html('');
|
||||
$('#ez-modal--history-details h3').html("{{ 'coderhapsodie.ezdataflow.workflow.history.title'|trans }}");
|
||||
if ($(this).hasClass('modal-history-log')) {
|
||||
$('#ez-modal--history-details h3').html("{{ 'coderhapsodie.ezdataflow.workflow.log.title'|trans }}");
|
||||
}
|
||||
$('#ez-modal--history-details').modal('show');
|
||||
$.ajax(this.href, {
|
||||
success: function (result) {
|
||||
|
||||
@@ -40,10 +40,9 @@
|
||||
success: function (result) {
|
||||
if (result.redirect) {
|
||||
if (window.location.href === result.redirect) {
|
||||
window.location.reload();
|
||||
document.location.reload();
|
||||
}
|
||||
window.location = result.redirect;
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,10 +125,9 @@
|
||||
success: function (result) {
|
||||
if (result.redirect) {
|
||||
if (window.location.href === result.redirect) {
|
||||
window.location.reload();
|
||||
document.location.reload();
|
||||
}
|
||||
window.location = result.redirect;
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{% import '@ezdesign/ezdataflow/macros.twig' as macros %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container ez-main-container history-details-aware">
|
||||
|
||||
<div class="container ez-main-container">
|
||||
{% if item is not null %}
|
||||
<h2>{{ 'coderhapsodie.ezdataflow.history.job.title'|trans }} n°{{ item.id }}</h2>
|
||||
|
||||
@@ -20,7 +21,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'coderhapsodie.ezdataflow.history.details.request'|trans }}</td>
|
||||
<td>{{ date(item.requestedDate)|ez_short_datetime }}</td>
|
||||
<td>{{ item.requestedDate|date('d/m/Y H:i:s') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'coderhapsodie.ezdataflow.history.details.status'|trans }}</td>
|
||||
@@ -28,11 +29,11 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'coderhapsodie.ezdataflow.history.details.start'|trans }}</td>
|
||||
<td>{{ item.startTime ? date(item.startTime)|ez_short_datetime : '—' }}</td>
|
||||
<td>{{ item.startTime|date('d/m/Y H:i:s') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'coderhapsodie.ezdataflow.history.details.end'|trans }}</td>
|
||||
<td>{{ item.endTime ? date(item.endTime)|ez_short_datetime : '—' }}</td>
|
||||
<td>{{ item.endTime|date('d/m/Y H:i:s') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'coderhapsodie.ezdataflow.history.details.count'|trans }}</td>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{% for line in log %}
|
||||
<p>{{ line|nl2br }}</p>
|
||||
{% endfor %}
|
||||
@@ -27,10 +27,10 @@
|
||||
{% for job in pager.currentPageResults %}
|
||||
<tr>
|
||||
<td>{{ job.label }}</td>
|
||||
<td>{{ date(job.requested_date)|ez_short_datetime }}</td>
|
||||
<td>{{ job.count|default('—') }}</td>
|
||||
<td>{{ job.start_time ? date(job.start_time)|ez_short_datetime : '—' }}</td>
|
||||
<td>{{ job.end_time ? date(job.end_time)|ez_short_datetime : '—' }}</td>
|
||||
<td>{{ job.requested_date|date('d/m/Y H:i:s') }}</td>
|
||||
<td>{{ job.count|default('-') }}</td>
|
||||
<td>{{ job.start_time ? job.start_time|date('d/m/Y H:i:s') : '-' }}</td>
|
||||
<td>{{ job.end_time ? job.end_time|date('d/m/Y H:i:s') : '-' }}</td>
|
||||
<td>{{ macros.translateStatus(job.status) }}</td>
|
||||
<td class="ez-table__cell ez-table__cell--has-action-btns text-right">
|
||||
<a href="{{ path('coderhapsodie.ezdataflow.job.details', {id: job.id}) }}"
|
||||
@@ -41,14 +41,6 @@
|
||||
xlink:href="/bundles/ezplatformadminui/img/ez-icons.svg#about-info"></use>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="{{ path('coderhapsodie.ezdataflow.job.log', {id: job.id}) }}"
|
||||
class="btn btn-icon mx-2 modal-history-details modal-history-log"
|
||||
title="{{ 'coderhapsodie.ezdataflow.history.details.log'|trans }}">
|
||||
<svg class="ez-icon ez-icon--small-medium">
|
||||
<use xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xlink:href="/bundles/ezplatformadminui/img/ez-icons.svg#article"></use>
|
||||
</svg>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -66,6 +58,7 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
(function ($) {
|
||||
$(document).ready(function ($) {
|
||||
// Manage ajax pagination
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<tr>
|
||||
<td>{{ item.label }}</td>
|
||||
<td>{{ item.frequency }}</td>
|
||||
<td>{{ date(item.next)|ez_short_datetime }}</td>
|
||||
<td>{{ item.next|date('d/m/Y H:i:s') }}</td>
|
||||
<td>{{ ('coderhapsodie.ezdataflow.' ~ (item.enabled ? 'yes' : 'no'))|trans }}</td>
|
||||
<td class="ez-table__cell ez-table__cell--has-action-btns text-right">
|
||||
<a href="{{ path('coderhapsodie.ezdataflow.history.workflow', {id: item.id}) }}"
|
||||
|
||||
@@ -16,7 +16,7 @@ class HistoryTab extends AbstractControllerBasedTab implements OrderedTabInterfa
|
||||
*/
|
||||
public function getControllerReference(array $parameters): ControllerReference
|
||||
{
|
||||
return new ControllerReference(DashboardController::class.'::history', [], $parameters);
|
||||
return new ControllerReference(DashboardController::class.'::history');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,9 @@ trait UserSwitcherAwareTrait
|
||||
/** @var UserSwitcherInterface */
|
||||
protected $userSwitcher;
|
||||
|
||||
/**
|
||||
* @param UserSwitcherInterface $userSwitcher
|
||||
*/
|
||||
public function setUserSwitcher(UserSwitcherInterface $userSwitcher): void
|
||||
{
|
||||
$this->userSwitcher = $userSwitcher;
|
||||
|
||||
@@ -4,18 +4,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Writer;
|
||||
|
||||
use CodeRhapsodie\DataflowBundle\DataflowType\Writer\DelegateWriterInterface;
|
||||
use CodeRhapsodie\EzDataflowBundle\Core\Content\ContentCreatorInterface;
|
||||
use CodeRhapsodie\EzDataflowBundle\Core\Content\ContentUpdaterInterface;
|
||||
use CodeRhapsodie\EzDataflowBundle\Model\ContentCreateStructure;
|
||||
use CodeRhapsodie\EzDataflowBundle\Model\ContentStructure;
|
||||
use CodeRhapsodie\EzDataflowBundle\Model\ContentUpdateStructure;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use CodeRhapsodie\DataflowBundle\DataflowType\Writer\WriterInterface;
|
||||
|
||||
class ContentWriter extends RepositoryWriter implements DelegateWriterInterface
|
||||
class ContentWriter extends RepositoryWriter implements WriterInterface
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/** @var ContentCreatorInterface */
|
||||
private $creator;
|
||||
|
||||
@@ -34,40 +31,15 @@ class ContentWriter extends RepositoryWriter implements DelegateWriterInterface
|
||||
public function write($item)
|
||||
{
|
||||
if (!$item instanceof ContentStructure) {
|
||||
$this->log('warning', 'Data is not a ContentStucture');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($item instanceof ContentCreateStructure) {
|
||||
$this->log('info', 'Save content', [
|
||||
'content_type' => $item->getContentTypeIdentifier(),
|
||||
'content_location' => $item->getLocations(),
|
||||
]);
|
||||
|
||||
return $this->creator->createFromStructure($item);
|
||||
$this->creator->createFromStructure($item);
|
||||
}
|
||||
|
||||
if ($item instanceof ContentUpdateStructure) {
|
||||
$this->log('info', 'Update content', ['id' => $item->getId(), 'remote_id' => $item->getRemoteId()]);
|
||||
|
||||
return $this->updater->updateFromStructure($item);
|
||||
$this->updater->updateFromStructure($item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports($item): bool
|
||||
{
|
||||
return $item instanceof ContentStructure;
|
||||
}
|
||||
|
||||
private function log(string $level, string $message, array $context = [])
|
||||
{
|
||||
if (null === $this->logger) {
|
||||
return;
|
||||
}
|
||||
$this->logger->log($level, $message, $context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Writer;
|
||||
|
||||
use CodeRhapsodie\DataflowBundle\DataflowType\Writer\WriterInterface;
|
||||
use CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcherAwareInterface;
|
||||
use CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcherAwareTrait;
|
||||
use CodeRhapsodie\DataflowBundle\DataflowType\Writer\WriterInterface;
|
||||
|
||||
abstract class RepositoryWriter implements WriterInterface, UserSwitcherAwareInterface
|
||||
{
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Tests\Core\FieldComparator;
|
||||
|
||||
use CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\DelegatorFieldComparator;
|
||||
use CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface;
|
||||
use eZ\Publish\API\Repository\Values\Content\Field;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DelegatorFieldComparatorTest extends TestCase
|
||||
{
|
||||
/** @var DelegatorFieldComparator */
|
||||
private $delegatorFieldComparator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$type1FieldComparatorMock = $this->createMock(FieldComparatorInterface::class);
|
||||
$type1FieldComparatorMock->method('compare')->willReturnCallback(function (Field $field, $hash) {
|
||||
return $hash === 'rightValue1';
|
||||
});
|
||||
$type2FieldComparatorMock = $this->createMock(FieldComparatorInterface::class);
|
||||
$type2FieldComparatorMock->method('compare')->willReturnCallback(function (Field $field, $hash) {
|
||||
return $hash === 'rightValue2';
|
||||
});
|
||||
$this->delegatorFieldComparator = new DelegatorFieldComparator();
|
||||
$this->delegatorFieldComparator->registerDelegateFieldComparator($type1FieldComparatorMock, 'type1');
|
||||
$this->delegatorFieldComparator->registerDelegateFieldComparator($type2FieldComparatorMock, 'type2');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider fieldProvider
|
||||
*/
|
||||
public function testField(string $type, bool $expected, $hash)
|
||||
{
|
||||
$field = new Field(['fieldTypeIdentifier' => $type]);
|
||||
$return = $this->delegatorFieldComparator->compare($field, $hash);
|
||||
|
||||
$this->assertSame($expected, $return);
|
||||
}
|
||||
|
||||
public function fieldProvider(): iterable
|
||||
{
|
||||
yield ['type1', true, 'rightValue1'];
|
||||
yield ['type1', false, 'wrongValue'];
|
||||
yield ['type2', true, 'rightValue2'];
|
||||
yield ['type2', false, 'wrongValue'];
|
||||
yield ['otherType', false, 'rightValue1'];
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Tests\Filter;
|
||||
|
||||
use CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface;
|
||||
use CodeRhapsodie\EzDataflowBundle\Filter\NotModifiedContentFilter;
|
||||
use CodeRhapsodie\EzDataflowBundle\Model\ContentUpdateStructure;
|
||||
use eZ\Publish\API\Repository\ContentService;
|
||||
use eZ\Publish\API\Repository\Values\Content\Field;
|
||||
use eZ\Publish\Core\Repository\Values\Content\Content;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class NotModifiedContentFilterTest extends TestCase
|
||||
{
|
||||
/** @var ContentService|MockObject */
|
||||
private $contentServiceMock;
|
||||
|
||||
/** @var FieldComparatorInterface|MockObject */
|
||||
private $comparatorMock;
|
||||
|
||||
/** @var NotModifiedContentFilter */
|
||||
private $notModifiedContentFilter;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->contentServiceMock = $this->createMock(ContentService::class);
|
||||
$this->comparatorMock = $this->createMock(FieldComparatorInterface::class);
|
||||
$this->notModifiedContentFilter = new NotModifiedContentFilter($this->contentServiceMock, $this->comparatorMock);
|
||||
}
|
||||
|
||||
public function testNotContentUpdateStructure()
|
||||
{
|
||||
$data = 'notAStruct';
|
||||
$returnValue = ($this->notModifiedContentFilter)($data);
|
||||
|
||||
$this->assertSame($data, $returnValue);
|
||||
}
|
||||
|
||||
public function testIdenticalContent()
|
||||
{
|
||||
$id = 10;
|
||||
$field1 = 'field1';
|
||||
$value1 = 'value1';
|
||||
$field2 = 'field2';
|
||||
$value2 = 'value2';
|
||||
$contentField1 = new Field();
|
||||
$contentField2 = new Field();
|
||||
$data = ContentUpdateStructure::createForContentId($id, 'lang', [
|
||||
$field1 => $value1,
|
||||
$field2 => $value2,
|
||||
]);
|
||||
$content = $this->createMock(Content::class);
|
||||
|
||||
$content
|
||||
->expects($this->exactly(2))
|
||||
->method('getField')
|
||||
->withConsecutive([$field1], [$field2])
|
||||
->willReturnOnConsecutiveCalls($contentField1, $contentField2)
|
||||
;
|
||||
$this->contentServiceMock
|
||||
->expects($this->once())
|
||||
->method('loadContent')
|
||||
->with($id)
|
||||
->willReturn($content)
|
||||
;
|
||||
$this->comparatorMock
|
||||
->expects($this->exactly(2))
|
||||
->method('compare')
|
||||
->withConsecutive([$contentField1, $value1], [$contentField2, $value2])
|
||||
->willReturn(true)
|
||||
;
|
||||
|
||||
$return = ($this->notModifiedContentFilter)($data);
|
||||
|
||||
$this->assertFalse($return);
|
||||
}
|
||||
|
||||
public function testDifferentContent()
|
||||
{
|
||||
$id = 10;
|
||||
$field1 = 'field1';
|
||||
$value1 = 'value1';
|
||||
$field2 = 'field2';
|
||||
$value2 = 'value2';
|
||||
$field3 = 'field3';
|
||||
$value3 = 'value3';
|
||||
$contentField1 = new Field();
|
||||
$contentField2 = new Field();
|
||||
$data = ContentUpdateStructure::createForContentId($id, 'lang', [
|
||||
$field1 => $value1,
|
||||
$field2 => $value2,
|
||||
$field3 => $value3,
|
||||
]);
|
||||
$content = $this->createMock(Content::class);
|
||||
|
||||
$content
|
||||
->expects($this->exactly(2))
|
||||
->method('getField')
|
||||
->withConsecutive([$field1], [$field2])
|
||||
->willReturnOnConsecutiveCalls($contentField1, $contentField2)
|
||||
;
|
||||
$this->contentServiceMock
|
||||
->expects($this->once())
|
||||
->method('loadContent')
|
||||
->with($id)
|
||||
->willReturn($content)
|
||||
;
|
||||
$this->comparatorMock
|
||||
->expects($this->exactly(2))
|
||||
->method('compare')
|
||||
->withConsecutive([$contentField1, $value1], [$contentField2, $value2])
|
||||
->willReturnOnConsecutiveCalls(true, false)
|
||||
;
|
||||
|
||||
$return = ($this->notModifiedContentFilter)($data);
|
||||
|
||||
$this->assertSame($data, $return);
|
||||
}
|
||||
|
||||
public function testLoadEmptyByRemoteId()
|
||||
{
|
||||
$remoteId = 'abc';
|
||||
$data = ContentUpdateStructure::createForContentRemoteId($remoteId, 'lang', []);
|
||||
|
||||
$this->contentServiceMock
|
||||
->expects($this->once())
|
||||
->method('loadContentByRemoteId')
|
||||
->with($remoteId)
|
||||
->willReturn(new Content())
|
||||
;
|
||||
$return = ($this->notModifiedContentFilter)($data);
|
||||
|
||||
$this->assertFalse($return);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
// Skip autoloading if already done by phpunit alias (including from meta repo if this is vendor)
|
||||
if (defined('PHPUNIT_COMPOSER_INSTALL')) {
|
||||
return;
|
||||
}
|
||||
$autoloadFile = __DIR__ . '/../vendor/autoload.php';
|
||||
if (!file_exists($autoloadFile)) {
|
||||
throw new RuntimeException('Install dependencies to run test suite.');
|
||||
}
|
||||
require_once $autoloadFile;
|
||||
Reference in New Issue
Block a user