mirror of
https://github.com/code-rhapsodie/ibexa-dataflow-bundle.git
synced 2026-03-24 06:32:07 +01:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cca5bc57b4 | ||
|
|
137d5cbbb8 | ||
|
|
08302a3fd7 | ||
|
|
1dfcd5ef5d | ||
|
|
b3eddc2116 | ||
|
|
f204672681 | ||
|
|
a030a65214 | ||
|
|
b6a1526f56 | ||
|
|
2d3f3df9e8 | ||
|
|
158956117c | ||
|
|
31e9cde92e | ||
|
|
9ed9e84298 | ||
|
|
efe50b7613 | ||
|
|
cae5c3d152 | ||
|
|
a0596374d4 | ||
|
|
3160d0e58e | ||
|
|
bbd1b9f795 | ||
|
|
a968a6c8e3 | ||
|
|
99f1770842 | ||
|
|
ac23baf91f | ||
|
|
a0cb937af6 | ||
|
|
04633d2fd3 | ||
|
|
ffdf24fe0c | ||
|
|
2618ba9463 | ||
|
|
c0c571b058 | ||
|
|
278f2fd114 | ||
|
|
6ece645267 | ||
|
|
5180108598 | ||
|
|
08cd3eccd6 | ||
|
|
9dc90bb001 |
@@ -1,3 +1,12 @@
|
||||
# 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
|
||||
|
||||
|
||||
44
README.md
44
README.md
@@ -13,7 +13,7 @@ Ibexa Dataflow bundle is intended to manage content imports from external data s
|
||||
|
||||
| Ibexa Dataflow Version | Ibexa Content Version | Status |
|
||||
|------------------------|-----------------------|-------------------------------|
|
||||
| 5.x | 4.x | :white_check_mark: Maintained |
|
||||
| 6.x | 5.x | :white_check_mark: Maintained |
|
||||
|
||||
## User Interface (UI)
|
||||
|
||||
@@ -232,27 +232,31 @@ 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
|
||||
|
||||
### Add custom field comparator
|
||||
|
||||
|
||||
@@ -44,16 +44,17 @@
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"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.6",
|
||||
"ibexa/core": "^4.6"
|
||||
"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",
|
||||
@@ -68,7 +69,8 @@
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-v4.x": "4.x-dev",
|
||||
"dev-v5.x": "5.x-dev"
|
||||
"dev-v5.x": "5.x-dev",
|
||||
"dev-v6.x": "6.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ return RectorConfig::configure()
|
||||
__DIR__ . '/src',
|
||||
__DIR__ . '/tests',
|
||||
])
|
||||
->withPhpVersion(PhpVersion::PHP_81)
|
||||
->withPhpVersion(PhpVersion::PHP_83)
|
||||
// uncomment to reach your current PHP version
|
||||
->withPhpSets(php81: true)
|
||||
->withPhpSets(php83: true)
|
||||
->withTypeCoverageLevel(0)
|
||||
->withDeadCodeLevel(0)
|
||||
->withCodeQualityLevel(0)
|
||||
|
||||
@@ -9,18 +9,23 @@ use CodeRhapsodie\IbexaDataflowBundle\DependencyInjection\Compiler\FieldComparat
|
||||
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
|
||||
{
|
||||
protected $name = 'CodeRhapsodieIbexaDataflowBundle';
|
||||
public const string VERSION = '6.0.0';
|
||||
public const string PRODUCT_NAME = 'ibexadataflow';
|
||||
|
||||
public function getContainerExtension()
|
||||
protected string $name = 'CodeRhapsodieIbexaDataflowBundle';
|
||||
|
||||
#[\Override]
|
||||
public function getContainerExtension(): ?ExtensionInterface
|
||||
{
|
||||
return new CodeRhapsodieIbexaDataflowExtension();
|
||||
}
|
||||
|
||||
public function build(ContainerBuilder $container)
|
||||
public function build(ContainerBuilder $container): void
|
||||
{
|
||||
parent::build($container);
|
||||
|
||||
@@ -31,4 +36,3 @@ class CodeRhapsodieIbexaDataflowBundle extends Bundle
|
||||
$ibexaExtension->addPolicyProvider(new PolicyProvider());
|
||||
}
|
||||
}
|
||||
class_alias(CodeRhapsodieIbexaDataflowBundle::class, 'CodeRhapsodie\EzDataflowBundle\CodeRhapsodieIbexaDataflowBundle');
|
||||
|
||||
@@ -6,25 +6,34 @@ namespace CodeRhapsodie\IbexaDataflowBundle\Controller;
|
||||
|
||||
use CodeRhapsodie\DataflowBundle\Entity\Job;
|
||||
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
|
||||
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(path: '/ibexa_dataflow')]
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public function __construct(private readonly JobGateway $jobGateway, private readonly ScheduledDataflowGateway $scheduledDataflowGateway)
|
||||
public function __construct(
|
||||
private readonly JobGateway $jobGateway,
|
||||
private readonly ScheduledDataflowGateway $scheduledDataflowGateway,
|
||||
private readonly ExceptionHandlerInterface $exceptionHandler
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -33,7 +42,18 @@ class DashboardController extends Controller
|
||||
{
|
||||
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
|
||||
|
||||
return $this->render('@ibexadesign/ibexa_dataflow/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
|
||||
@@ -75,7 +95,7 @@ class DashboardController extends Controller
|
||||
]);
|
||||
|
||||
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/oneshot.html.twig', [
|
||||
'pager' => $this->getPager($this->jobGateway->getOneshotListQueryForAdmin(), $request),
|
||||
'pager' => $this->getPager($this->jobGateway->getOneshotListQueryForAdmin(), $request, Job::class),
|
||||
'form' => $form->createView(),
|
||||
]);
|
||||
}
|
||||
@@ -86,7 +106,7 @@ class DashboardController extends Controller
|
||||
$this->denyAccessUnlessGranted(new Attribute('ibexa_dataflow', 'view'));
|
||||
|
||||
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/oneshot.html.twig', [
|
||||
'pager' => $this->getPager($this->jobGateway->getOneshotListQueryForAdmin(), $request),
|
||||
'pager' => $this->getPager($this->jobGateway->getOneshotListQueryForAdmin(), $request, Job::class),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -97,7 +117,7 @@ class DashboardController extends Controller
|
||||
$filter = (int) $request->query->get('filter', JobGateway::FILTER_NONE);
|
||||
|
||||
return $this->render('@ibexadesign/ibexa_dataflow/Dashboard/history.html.twig', [
|
||||
'pager' => $this->getPager($this->jobGateway->getListQueryForAdmin($filter), $request),
|
||||
'pager' => $this->getPager($this->jobGateway->getListQueryForAdmin($filter), $request, Job::class),
|
||||
'filter' => $filter,
|
||||
]);
|
||||
}
|
||||
@@ -109,22 +129,41 @@ class DashboardController extends Controller
|
||||
|
||||
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, fn($queryBuilder) => $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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ 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(path: '/ibexa_dataflow/scheduled_workflow')]
|
||||
@@ -44,7 +44,7 @@ class ScheduledDataflowController extends Controller
|
||||
['message' => $e->getMessage()]));
|
||||
}
|
||||
|
||||
return new JsonResponse(['redirect' => $this->generateUrl('coderhapsodie.ibexa_dataflow.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([
|
||||
@@ -68,7 +68,7 @@ class ScheduledDataflowController extends Controller
|
||||
['message' => $e->getMessage()]));
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('coderhapsodie.ibexa_dataflow.main');
|
||||
return $this->redirectToRoute('coderhapsodie.ibexa_dataflow.main', ['_fragment' => 'ibexa-tab-coderhapsodie-ibexa_dataflow-code-rhapsodie-ibexa_dataflow-repeating']);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit', name: 'coderhapsodie.ibexa_dataflow.workflow.edit')]
|
||||
@@ -91,7 +91,7 @@ class ScheduledDataflowController extends Controller
|
||||
['message' => $e->getMessage()]));
|
||||
}
|
||||
|
||||
return new JsonResponse(['redirect' => $this->generateUrl('coderhapsodie.ibexa_dataflow.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([
|
||||
@@ -109,7 +109,7 @@ class ScheduledDataflowController extends Controller
|
||||
|
||||
$this->changeDataflowStatus($id, true);
|
||||
|
||||
return $this->redirectToRoute('coderhapsodie.ibexa_dataflow.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)
|
||||
@@ -133,6 +133,6 @@ class ScheduledDataflowController extends Controller
|
||||
|
||||
$this->changeDataflowStatus($id, false);
|
||||
|
||||
return $this->redirectToRoute('coderhapsodie.ibexa_dataflow.main');
|
||||
return $this->redirectToRoute('coderhapsodie.ibexa_dataflow.main', ['_fragment' => 'ibexa-tab-coderhapsodie-ibexa_dataflow-code-rhapsodie-ibexa_dataflow-repeating']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,13 @@ 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
|
||||
{
|
||||
public function __construct(private readonly ContentService $contentService, private readonly ContentTypeService $contentTypeService, private readonly ContentStructFieldFillerInterface $filler, private readonly LocationMatcherInterface $matcher)
|
||||
public function __construct(private ContentService $contentService, private ContentTypeService $contentTypeService, private ContentStructFieldFillerInterface $filler, private LocationMatcherInterface $matcher, private Repository $repository)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -32,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,4 +71,3 @@ class ContentCreator implements ContentCreatorInterface
|
||||
return $locationCreateStructs;
|
||||
}
|
||||
}
|
||||
class_alias(ContentCreator::class, 'CodeRhapsodie\EzDataflowBundle\Core\Content\ContentCreator');
|
||||
|
||||
@@ -11,4 +11,3 @@ interface ContentCreatorInterface
|
||||
{
|
||||
public function createFromStructure(ContentCreateStructure $structure): Content;
|
||||
}
|
||||
class_alias(ContentCreatorInterface::class, 'CodeRhapsodie\EzDataflowBundle\Core\Content\ContentCreatorInterface');
|
||||
|
||||
@@ -9,11 +9,12 @@ 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
|
||||
{
|
||||
public function __construct(private readonly ContentService $contentService, private readonly ContentTypeService $contentTypeService, private readonly ContentStructFieldFillerInterface $filler)
|
||||
public function __construct(private ContentService $contentService, private ContentTypeService $contentTypeService, private ContentStructFieldFillerInterface $filler, private Repository $repository)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -44,10 +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;
|
||||
}
|
||||
}
|
||||
}
|
||||
class_alias(ContentUpdater::class, 'CodeRhapsodie\EzDataflowBundle\Core\Content\ContentUpdater');
|
||||
|
||||
@@ -11,4 +11,3 @@ interface ContentUpdaterInterface
|
||||
{
|
||||
public function updateFromStructure(ContentUpdateStructure $structure): Content;
|
||||
}
|
||||
class_alias(ContentUpdaterInterface::class, 'CodeRhapsodie\EzDataflowBundle\Core\Content\ContentUpdaterInterface');
|
||||
|
||||
@@ -59,4 +59,3 @@ class ContentStructFieldFiller implements ContentStructFieldFillerInterface
|
||||
throw UnsupportedFieldTypeException::create($fieldTypeIdentifier);
|
||||
}
|
||||
}
|
||||
class_alias(ContentStructFieldFiller::class, 'CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFiller');
|
||||
|
||||
@@ -11,4 +11,3 @@ interface ContentStructFieldFillerInterface
|
||||
{
|
||||
public function fillFields(ContentType $contentType, ContentStruct $contentStruct, array $fieldHashes): void;
|
||||
}
|
||||
class_alias(ContentStructFieldFillerInterface::class, 'CodeRhapsodie\EzDataflowBundle\Core\Field\ContentStructFieldFillerInterface');
|
||||
|
||||
@@ -23,4 +23,3 @@ class DefaultFieldValueCreator implements FieldValueCreatorInterface
|
||||
return $this->fieldTypeService->getFieldType($fieldTypeIdentifier)->fromHash($hash);
|
||||
}
|
||||
}
|
||||
class_alias(DefaultFieldValueCreator::class, 'CodeRhapsodie\EzDataflowBundle\Core\Field\DefaultFieldValueCreator');
|
||||
|
||||
@@ -15,4 +15,3 @@ interface FieldValueCreatorInterface
|
||||
*/
|
||||
public function createValue(string $fieldTypeIdentifier, $hash): Value;
|
||||
}
|
||||
class_alias(FieldValueCreatorInterface::class, 'CodeRhapsodie\EzDataflowBundle\Core\Field\FieldValueCreatorInterface');
|
||||
|
||||
@@ -26,4 +26,3 @@ abstract class AbstractFieldComparator implements FieldComparatorInterface
|
||||
*/
|
||||
abstract protected function compareValues(Value $currentValue, Value $newValue): bool;
|
||||
}
|
||||
class_alias(AbstractFieldComparator::class, 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator');
|
||||
|
||||
18
src/Core/FieldComparator/BillingAddressComparator.php
Normal file
18
src/Core/FieldComparator/BillingAddressComparator.php
Normal 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;
|
||||
}
|
||||
}
|
||||
18
src/Core/FieldComparator/CustomerGroupComparator.php
Normal file
18
src/Core/FieldComparator/CustomerGroupComparator.php
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -34,4 +34,3 @@ class DelegatorFieldComparator implements FieldComparatorInterface
|
||||
$this->delegates[$fieldTypeIdentifier] = $typedFieldComparator;
|
||||
}
|
||||
}
|
||||
class_alias(DelegatorFieldComparator::class, 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\DelegatorFieldComparator');
|
||||
|
||||
@@ -13,4 +13,3 @@ interface FieldComparatorInterface
|
||||
*/
|
||||
public function compare(Field $field, $hash): bool;
|
||||
}
|
||||
class_alias(FieldComparatorInterface::class, 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\FieldComparatorInterface');
|
||||
|
||||
@@ -16,4 +16,3 @@ class MapLocationFieldComparator extends AbstractFieldComparator
|
||||
;
|
||||
}
|
||||
}
|
||||
class_alias(MapLocationFieldComparator::class, 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\MapLocationFieldComparator');
|
||||
|
||||
@@ -27,4 +27,3 @@ class MatrixFieldComparator extends AbstractFieldComparator
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class_alias(MatrixFieldComparator::class, 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\MatrixFieldComparator');
|
||||
|
||||
@@ -24,4 +24,3 @@ class NovaSEOMetasFieldComparator extends AbstractFieldComparator
|
||||
return count($currentValue->metas) === count($newValue->metas);
|
||||
}
|
||||
}
|
||||
class_alias(NovaSEOMetasFieldComparator::class, 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\NovaSEOMetasFieldComparator');
|
||||
|
||||
@@ -13,4 +13,3 @@ class SimpleFieldComparator extends AbstractFieldComparator
|
||||
return (string) $currentValue === (string) $newValue;
|
||||
}
|
||||
}
|
||||
class_alias(SimpleFieldComparator::class, 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\SimpleFieldComparator');
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?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);
|
||||
|
||||
return empty(array_diff($currentEntriesId, $newEntriesId));
|
||||
}
|
||||
}
|
||||
@@ -13,4 +13,3 @@ class UrlFieldComparator extends AbstractFieldComparator
|
||||
return $currentValue->link === $newValue->link && $currentValue->text === $newValue->text;
|
||||
}
|
||||
}
|
||||
class_alias(UrlFieldComparator::class, 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\UrlFieldComparator');
|
||||
|
||||
@@ -12,7 +12,7 @@ use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||
|
||||
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);
|
||||
|
||||
@@ -11,7 +11,7 @@ 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;
|
||||
|
||||
@@ -12,7 +12,7 @@ class Configuration implements ConfigurationInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfigTreeBuilder()
|
||||
public function getConfigTreeBuilder(): TreeBuilder
|
||||
{
|
||||
$treeBuilder = new TreeBuilder('code_rhapsodie_ibexa_dataflow');
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -30,4 +30,3 @@ class InvalidArgumentTypeException extends \Exception
|
||||
));
|
||||
}
|
||||
}
|
||||
class_alias(InvalidArgumentTypeException::class, 'CodeRhapsodie\EzDataflowBundle\Exception\InvalidArgumentTypeException');
|
||||
|
||||
@@ -7,4 +7,3 @@ namespace CodeRhapsodie\IbexaDataflowBundle\Exception;
|
||||
class NoMatchFoundException extends \Exception
|
||||
{
|
||||
}
|
||||
class_alias(NoMatchFoundException::class, 'CodeRhapsodie\EzDataflowBundle\Exception\NoMatchFoundException');
|
||||
|
||||
@@ -15,4 +15,3 @@ class UnknownFieldException extends \Exception
|
||||
));
|
||||
}
|
||||
}
|
||||
class_alias(UnknownFieldException::class, 'CodeRhapsodie\EzDataflowBundle\Exception\UnknownFieldException');
|
||||
|
||||
@@ -14,4 +14,3 @@ class UnsupportedFieldTypeException extends \Exception
|
||||
));
|
||||
}
|
||||
}
|
||||
class_alias(UnsupportedFieldTypeException::class, 'CodeRhapsodie\EzDataflowBundle\Exception\UnsupportedFieldTypeException');
|
||||
|
||||
@@ -9,12 +9,9 @@ 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
|
||||
{
|
||||
/**
|
||||
* ContentStructureFactory constructor.
|
||||
*/
|
||||
public function __construct(private readonly ContentService $contentService)
|
||||
public function __construct(private ContentService $contentService)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -53,4 +50,3 @@ final class ContentStructureFactory implements ContentStructureFactoryInterface
|
||||
);
|
||||
}
|
||||
}
|
||||
class_alias(ContentStructureFactory::class, 'CodeRhapsodie\EzDataflowBundle\Factory\ContentStructureFactory');
|
||||
|
||||
@@ -18,4 +18,3 @@ interface ContentStructureFactoryInterface
|
||||
*/
|
||||
public function transform(array $data, string $remoteId, string $language, string $contentType, $parentLocations, int $mode = ContentStructureFactoryInterface::MODE_INSERT_OR_UPDATE);
|
||||
}
|
||||
class_alias(ContentStructureFactoryInterface::class, 'CodeRhapsodie\EzDataflowBundle\Factory\ContentStructureFactoryInterface');
|
||||
|
||||
@@ -52,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;
|
||||
@@ -60,4 +60,3 @@ class NotModifiedContentFilter
|
||||
$this->logger->log($level, $message, $context);
|
||||
}
|
||||
}
|
||||
class_alias(NotModifiedContentFilter::class, 'CodeRhapsodie\EzDataflowBundle\Filter\NotModifiedContentFilter');
|
||||
|
||||
46
src/Filter/NotModifiedProductFilter.php
Normal file
46
src/Filter/NotModifiedProductFilter.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,11 +35,10 @@ class CreateOneshotType extends AbstractType
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Job::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
class_alias(CreateOneshotType::class, 'CodeRhapsodie\EzDataflowBundle\Form\CreateOneshotType');
|
||||
|
||||
@@ -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,11 +47,10 @@ class CreateScheduledType extends AbstractType
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => ScheduledDataflow::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
class_alias(CreateScheduledType::class, 'CodeRhapsodie\EzDataflowBundle\Form\CreateScheduledType');
|
||||
|
||||
@@ -15,12 +15,13 @@ class DataflowTypeChoiceType extends AbstractType
|
||||
{
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -32,4 +33,3 @@ class DataflowTypeChoiceType extends AbstractType
|
||||
]);
|
||||
}
|
||||
}
|
||||
class_alias(DataflowTypeChoiceType::class, 'CodeRhapsodie\EzDataflowBundle\Form\DataflowTypeChoiceType');
|
||||
|
||||
@@ -12,14 +12,15 @@ 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';
|
||||
}
|
||||
}
|
||||
class_alias(FrequencyType::class, 'CodeRhapsodie\EzDataflowBundle\Form\FrequencyType');
|
||||
|
||||
@@ -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,11 +37,10 @@ class UpdateScheduledType extends AbstractType
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => ScheduledDataflow::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
class_alias(UpdateScheduledType::class, 'CodeRhapsodie\EzDataflowBundle\Form\UpdateScheduledType');
|
||||
|
||||
@@ -14,7 +14,7 @@ class UserTimezoneAwareDateTimeTransformer implements DataTransformerInterface
|
||||
{
|
||||
}
|
||||
|
||||
public function transform($value)
|
||||
public function transform($value): mixed
|
||||
{
|
||||
if (!$value instanceof \DateTimeInterface) {
|
||||
return $value;
|
||||
@@ -23,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;
|
||||
@@ -45,4 +45,3 @@ class UserTimezoneAwareDateTimeTransformer implements DataTransformerInterface
|
||||
return new \DateTimeZone($tz);
|
||||
}
|
||||
}
|
||||
class_alias(UserTimezoneAwareDateTimeTransformer::class, 'CodeRhapsodie\EzDataflowBundle\Form\UserTimezoneAwareDateTimeTransformer');
|
||||
|
||||
@@ -15,14 +15,14 @@ class UserTimezoneAwareDateTimeType extends AbstractType
|
||||
{
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
class_alias(UserTimezoneAwareDateTimeType::class, 'CodeRhapsodie\EzDataflowBundle\Form\UserTimezoneAwareDateTimeType');
|
||||
|
||||
@@ -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,9 +52,9 @@ class YamlType extends AbstractType
|
||||
));
|
||||
}
|
||||
|
||||
public function getBlockPrefix()
|
||||
#[\Override]
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'coderhapsodie_port_yaml';
|
||||
}
|
||||
}
|
||||
class_alias(YamlType::class, 'CodeRhapsodie\EzDataflowBundle\Form\YamlType');
|
||||
|
||||
@@ -12,12 +12,12 @@ class ExceptionJSONDecoderAdapter implements AdapterInterface
|
||||
{
|
||||
}
|
||||
|
||||
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): void {
|
||||
|
||||
@@ -5,21 +5,22 @@ declare(strict_types=1);
|
||||
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;
|
||||
|
||||
public function __construct(private readonly JobRepository $jobRepository)
|
||||
public function __construct(private JobRepository $jobRepository, private JobGatewayDataflow $jobGateway)
|
||||
{
|
||||
}
|
||||
|
||||
public function find(int $id): ?Job
|
||||
{
|
||||
return $this->jobRepository->find($id);
|
||||
return $this->jobGateway->find($id);
|
||||
}
|
||||
|
||||
public function getOneshotListQueryForAdmin(): QueryBuilder
|
||||
@@ -52,7 +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();
|
||||
}
|
||||
}
|
||||
class_alias(JobGateway::class, 'CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway');
|
||||
|
||||
@@ -8,9 +8,9 @@ use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
|
||||
use CodeRhapsodie\DataflowBundle\Repository\ScheduledDataflowRepository;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
|
||||
final class ScheduledDataflowGateway
|
||||
final readonly class ScheduledDataflowGateway
|
||||
{
|
||||
public function __construct(private readonly ScheduledDataflowRepository $scheduledDataflowRepository)
|
||||
public function __construct(private ScheduledDataflowRepository $scheduledDataflowRepository)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -38,4 +38,3 @@ final class ScheduledDataflowGateway
|
||||
$this->scheduledDataflowRepository->delete($id);
|
||||
}
|
||||
}
|
||||
class_alias(ScheduledDataflowGateway::class, 'CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway');
|
||||
|
||||
65
src/Gateway/TransformingAdapter.php
Normal file
65
src/Gateway/TransformingAdapter.php
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -42,4 +42,3 @@ class LocationMatcher implements LocationMatcherInterface
|
||||
throw new NoMatchFoundException('No location matched provided value');
|
||||
}
|
||||
}
|
||||
class_alias(LocationMatcher::class, 'CodeRhapsodie\EzDataflowBundle\Matcher\LocationMatcher');
|
||||
|
||||
@@ -13,4 +13,3 @@ interface LocationMatcherInterface
|
||||
*/
|
||||
public function matchLocation($valueToMatch): Location;
|
||||
}
|
||||
class_alias(LocationMatcherInterface::class, 'CodeRhapsodie\EzDataflowBundle\Matcher\LocationMatcherInterface');
|
||||
|
||||
@@ -10,11 +10,7 @@ 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.
|
||||
@@ -30,9 +26,8 @@ class ContentCreateStructure extends ContentStructure
|
||||
*
|
||||
* @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;
|
||||
@@ -52,7 +47,7 @@ class ContentCreateStructure extends ContentStructure
|
||||
/**
|
||||
* @throws \CodeRhapsodie\IbexaDataflowBundle\Exception\InvalidArgumentTypeException
|
||||
*/
|
||||
private function setLocations(array $locations)
|
||||
private function setLocations(array $locations): void
|
||||
{
|
||||
foreach ($locations as $locationOrIdOrRemoteIdOrStruct) {
|
||||
if (!is_int($locationOrIdOrRemoteIdOrStruct)
|
||||
@@ -67,4 +62,3 @@ class ContentCreateStructure extends ContentStructure
|
||||
$this->locations = $locations;
|
||||
}
|
||||
}
|
||||
class_alias(ContentCreateStructure::class, 'CodeRhapsodie\EzDataflowBundle\Model\ContentCreateStructure');
|
||||
|
||||
@@ -6,14 +6,11 @@ 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
|
||||
{
|
||||
@@ -30,4 +27,3 @@ abstract class ContentStructure
|
||||
return $this->fields;
|
||||
}
|
||||
}
|
||||
class_alias(ContentStructure::class, 'CodeRhapsodie\EzDataflowBundle\Model\ContentStructure');
|
||||
|
||||
@@ -6,8 +6,7 @@ namespace CodeRhapsodie\IbexaDataflowBundle\Model;
|
||||
|
||||
class ContentUpdateStructure extends ContentStructure
|
||||
{
|
||||
/** @var int|null */
|
||||
protected $id;
|
||||
protected ?int $id = null;
|
||||
|
||||
private function __construct(string $languageCode, array $fields)
|
||||
{
|
||||
@@ -36,4 +35,3 @@ class ContentUpdateStructure extends ContentStructure
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
class_alias(ContentUpdateStructure::class, 'CodeRhapsodie\EzDataflowBundle\Model\ContentUpdateStructure');
|
||||
|
||||
15
src/Model/ProductCreateStructure.php
Normal file
15
src/Model/ProductCreateStructure.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\IbexaDataflowBundle\Model;
|
||||
|
||||
class ProductCreateStructure extends ProductStructure
|
||||
{
|
||||
public function __construct(string $code, array $fields, string $languageCode)
|
||||
{
|
||||
$this->code = $code;
|
||||
$this->fields = $fields;
|
||||
$this->languageCode = $languageCode;
|
||||
}
|
||||
}
|
||||
35
src/Model/ProductStructure.php
Normal file
35
src/Model/ProductStructure.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace CodeRhapsodie\IbexaDataflowBundle\Model;
|
||||
|
||||
abstract class ProductStructure
|
||||
{
|
||||
protected string $code;
|
||||
|
||||
protected array $fields;
|
||||
|
||||
protected string $languageCode;
|
||||
|
||||
protected int $stock;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
40
src/Model/ProductUpdateStructure.php
Normal file
40
src/Model/ProductUpdateStructure.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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)
|
||||
{
|
||||
$this->code = $code;
|
||||
$this->fields = $fields;
|
||||
$this->languageCode = $languageCode;
|
||||
$this->stock = $stock;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
coderhapsodie.ibexa_dataflow.controllers:
|
||||
resource: '../../Controller/'
|
||||
type: annotation
|
||||
type: attribute
|
||||
|
||||
|
||||
@@ -4,44 +4,32 @@ imports:
|
||||
services:
|
||||
_defaults:
|
||||
public: false
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
coderhapsodie.dataflow.connection: "@ibexa.persistence.connection"
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Controller\DashboardController:
|
||||
public: true
|
||||
tags:
|
||||
- { name: controller.service_arguments }
|
||||
arguments:
|
||||
$jobGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\JobGateway'
|
||||
$scheduledDataflowGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway'
|
||||
calls:
|
||||
- ['setContainer', ['@service_container']]
|
||||
- ['performAccessCheck', []]
|
||||
$exceptionHandler: '@CodeRhapsodie\DataflowBundle\ExceptionsHandler\ExceptionHandlerInterface'
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Controller\ScheduledDataflowController:
|
||||
public: true
|
||||
tags:
|
||||
- { name: controller.service_arguments }
|
||||
arguments:
|
||||
$notificationHandler: '@Ibexa\Contracts\AdminUi\Notification\NotificationHandlerInterface'
|
||||
$scheduledDataflowGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway'
|
||||
$translator: '@translator'
|
||||
calls:
|
||||
- [ 'setContainer', [ '@service_container' ] ]
|
||||
- [ 'performAccessCheck', [ ] ]
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Controller\JobController:
|
||||
public: true
|
||||
tags:
|
||||
- { name: controller.service_arguments }
|
||||
arguments:
|
||||
$jobGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\JobGateway'
|
||||
$notificationHandler: '@Ibexa\Contracts\AdminUi\Notification\NotificationHandlerInterface'
|
||||
$translator: '@translator'
|
||||
$scheduledDataflowGateway: '@CodeRhapsodie\IbexaDataflowBundle\Gateway\ScheduledDataflowGateway'
|
||||
calls:
|
||||
- [ 'setContainer', [ '@service_container' ] ]
|
||||
- [ 'performAccessCheck', [ ] ]
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Writer\RepositoryWriter:
|
||||
abstract: true
|
||||
@@ -76,11 +64,12 @@ services:
|
||||
$contentService: '@Ibexa\Contracts\Core\Repository\ContentService'
|
||||
$contentTypeService: '@Ibexa\Contracts\Core\Repository\ContentTypeService'
|
||||
$filler: '@CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFillerInterface'
|
||||
$repository: '@Ibexa\Core\Event\Repository'
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFillerInterface: '@CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFiller'
|
||||
CodeRhapsodie\IbexaDataflowBundle\Core\Field\ContentStructFieldFiller:
|
||||
arguments:
|
||||
$fieldValueCreators: !tagged 'coderhapsodie.ibexa_dataflow.field_value_creator'
|
||||
$fieldValueCreators: !tagged_iterator 'coderhapsodie.ibexa_dataflow.field_value_creator'
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Matcher\LocationMatcherInterface: '@CodeRhapsodie\IbexaDataflowBundle\Matcher\LocationMatcher'
|
||||
CodeRhapsodie\IbexaDataflowBundle\Matcher\LocationMatcher:
|
||||
@@ -128,6 +117,15 @@ services:
|
||||
CodeRhapsodie\IbexaDataflowBundle\Gateway\JobGateway:
|
||||
arguments:
|
||||
$jobRepository: '@CodeRhapsodie\DataflowBundle\Repository\JobRepository'
|
||||
$jobGateway: '@CodeRhapsodie\DataflowBundle\Gateway\JobGateway'
|
||||
|
||||
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-ibexa_dataflow }
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Tab\RepeatingTab:
|
||||
parent: Ibexa\Contracts\AdminUi\Tab\AbstractTab
|
||||
@@ -159,6 +157,11 @@ services:
|
||||
$contentService: '@Ibexa\Contracts\Core\Repository\ContentService'
|
||||
$comparator: '@CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\FieldComparatorInterface'
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Filter\NotModifiedProductFilter:
|
||||
arguments:
|
||||
$notModifiedContentFilter: '@CodeRhapsodie\IbexaDataflowBundle\Filter\NotModifiedContentFilter'
|
||||
$connection: '@ibexa.persistence.connection'
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\FieldComparatorInterface: '@CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\DelegatorFieldComparator'
|
||||
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\DelegatorFieldComparator:
|
||||
|
||||
|
||||
@@ -2,29 +2,29 @@ services:
|
||||
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\SimpleFieldComparator:
|
||||
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
tags:
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezauthor' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezboolean' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezcountry' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezdate' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezdatetime' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezemail' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezfloat' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezinteger' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezisbn' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezkeyword' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezobjectrelation' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezobjectrelationlist' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezrichtext' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezselection' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'eztext' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezstring' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'eztime' }
|
||||
- { 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\IbexaDataflowBundle\Core\FieldComparator\UrlFieldComparator:
|
||||
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
tags:
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezurl' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_url' }
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\NovaSEOMetasFieldComparator:
|
||||
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
@@ -34,9 +34,25 @@ services:
|
||||
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\MatrixFieldComparator:
|
||||
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
tags:
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ezmatrix' }
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.field_comparator', fieldType: 'ibexa_matrix' }
|
||||
|
||||
CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\MapLocationFieldComparator:
|
||||
parent: 'CodeRhapsodie\IbexaDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
|
||||
tags:
|
||||
- { name: 'coderhapsodie.ibexa_dataflow.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' }
|
||||
|
||||
|
||||
@@ -83,3 +83,7 @@ coderhapsodie.dataflow.update.next: 'Next execution'
|
||||
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
|
||||
@@ -81,3 +81,7 @@ coderhapsodie.dataflow.update.next: 'Prochaine exécution'
|
||||
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
|
||||
@@ -0,0 +1,5 @@
|
||||
{%- block content -%}
|
||||
{% include '@ibexadesign/ibexa_dataflow/parts/tab/dashboard_list.html.twig' with {
|
||||
identifier: 'ibexa_dataflow_schedule_dashboard_results',
|
||||
} %}
|
||||
{%- endblock -%}
|
||||
File diff suppressed because one or more lines are too long
@@ -61,7 +61,7 @@
|
||||
const oneShotModal = document.getElementById('modal-new-oneshot');
|
||||
oneShotModal.querySelector('#create_oneshot_label').value = '';
|
||||
oneShotModal.querySelector('#create_oneshot_options').value = '';
|
||||
oneShotModal.querySelector('.flatpickr.flatpickr-input').parentNode.parentNode.ibexaInstance.flatpickrInstance.setDate(new Date(), true);
|
||||
oneShotModal.querySelector('#create_oneshot_requestedDate').closest('.ibexa-picker').querySelector('.ibexa-date-time-picker').ibexaInstance.flatpickrInstance.setDate(new Date(), true);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
} %}
|
||||
{% block body_content %}
|
||||
{{ form_start(update_form) }}
|
||||
<div class="form-fields">
|
||||
{{ form_widget(update_form) }}
|
||||
</div>
|
||||
<button id="modal-edit-submit" type="submit" hidden />
|
||||
<div class="form-fields">
|
||||
{{ form_widget(update_form) }}
|
||||
</div>
|
||||
<button id="modal-edit-submit" type="submit" hidden />
|
||||
{{ form_end(update_form) }}
|
||||
{% endblock %}
|
||||
{% block footer_content %}
|
||||
@@ -66,6 +66,10 @@
|
||||
})
|
||||
.then((r) => r.json())
|
||||
.then((result) => {
|
||||
if (result.redirect && window.location.pathname+window.location.hash === result.redirect) {
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
if (result.redirect) {
|
||||
window.location = result.redirect;
|
||||
return;
|
||||
@@ -96,7 +100,7 @@
|
||||
editModal.querySelector('#update_scheduled_label').value = node.querySelector('#update_scheduled_label').value;
|
||||
editModal.querySelector('#update_scheduled_options').value = node.querySelector('#update_scheduled_options').value;
|
||||
editModal.querySelector('#update_scheduled_frequency').value = node.querySelector('#update_scheduled_frequency').value;
|
||||
editModal.querySelector('#update_scheduled_next').parentNode.parentNode.ibexaInstance.flatpickrInstance.setDate(
|
||||
editModal.querySelector('#update_scheduled_next').closest('.ibexa-picker').querySelector('.ibexa-date-time-picker').ibexaInstance.flatpickrInstance.setDate(
|
||||
new Date(node.querySelector('#update_scheduled_next').value * 1000),
|
||||
true
|
||||
);
|
||||
|
||||
@@ -36,11 +36,11 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'coderhapsodie.ibexa_dataflow.history.details.count'|trans }}</td>
|
||||
<td>{{ item.count }}</td>
|
||||
<td>{{ item.count ? item.count|format_number(locale: app.request.locale) : '—' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'coderhapsodie.ibexa_dataflow.history.details.errors'|trans }}</td>
|
||||
<td>{{ item.exceptions|length }}</td>
|
||||
<td>{{ item.exceptions|length|format_number(locale: app.request.locale) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'coderhapsodie.ibexa_dataflow.history.details.type'|trans }}</td>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{% extends '@ibexadesign/ui/form_fields.html.twig' %}
|
||||
|
||||
{%- block checkbox_widget -%}
|
||||
{{ block('form_label') }}
|
||||
{{ block('toggle_widget') }}
|
||||
{%- endblock -%}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
{% set id = identifier|default('ibexa_dataflow_history_results') %}
|
||||
|
||||
{% import '@ibexadesign/ibexa_dataflow/macros.twig' as macros %}
|
||||
|
||||
<div id="loading_{{ id }}" class="text-center" hidden>
|
||||
<svg class="ez-icon ez-icon--extra-large">
|
||||
<use xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xlink:href="{{ ibexa_icon_path('spinner') }}"></use>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div id="{{ id }}" data-loader="loading_{{ id }}" class="history-details-aware">
|
||||
|
||||
{% set body_rows = [] %}
|
||||
|
||||
{% for job in jobs %}
|
||||
{% set body_row_cols = [] %}
|
||||
{% set body_row_cols = body_row_cols|merge([
|
||||
{content: job.label},
|
||||
{content: date(job.requested_date)|ibexa_short_datetime},
|
||||
{content: job.start_time ? date(job.start_time)|ibexa_short_datetime : '—'},
|
||||
{content: macros.translateStatus(job.status)},
|
||||
]) %}
|
||||
|
||||
|
||||
{% set body_rows = body_rows|merge([{ cols: body_row_cols }]) %}
|
||||
{% endfor %}
|
||||
|
||||
{% embed '@ibexadesign/ui/component/table/table.html.twig' with {
|
||||
headline: 'coderhapsodie.ibexa_dataflow.dashboard.title'|trans,
|
||||
head_cols: [
|
||||
{ content: 'coderhapsodie.ibexa_dataflow.history.list.name'|trans },
|
||||
{ content: 'coderhapsodie.ibexa_dataflow.history.list.request'|trans },
|
||||
{ content: 'coderhapsodie.ibexa_dataflow.history.list.start'|trans },
|
||||
{ content: 'coderhapsodie.ibexa_dataflow.history.list.status'|trans },
|
||||
{ },
|
||||
],
|
||||
body_rows,
|
||||
empty_table_info_text: 'coderhapsodie.ibexa_dataflow.history.list.empty'|trans,
|
||||
} %}
|
||||
{% endembed %}
|
||||
</div>
|
||||
@@ -18,8 +18,8 @@
|
||||
{% set body_row_cols = body_row_cols|merge([
|
||||
{content: job.label},
|
||||
{content: date(job.requested_date)|ibexa_short_datetime},
|
||||
{content: job.count|default('—')},
|
||||
{content: job.exceptions|length},
|
||||
{content: job.count is not null ? job.count|format_number(locale: app.request.locale) : '—'},
|
||||
{content: job.exceptions|length|format_number(locale: app.request.locale)},
|
||||
{content: job.start_time ? date(job.start_time)|ibexa_short_datetime : '—'},
|
||||
{content: job.end_time ? date(job.end_time)|ibexa_short_datetime : '—'},
|
||||
{content: macros.translateStatus(job.status)},
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
oneShotModal.querySelector('#create_oneshot_label').value = node.querySelector('#create_oneshot_label').value;
|
||||
oneShotModal.querySelector('#create_oneshot_options').value = node.querySelector('#create_oneshot_options').value;
|
||||
oneShotModal.querySelector('.ibexa-dropdown').ibexaInstance.selectOption(node.querySelector('#create_oneshot_dataflowType').value)
|
||||
oneShotModal.querySelector('.flatpickr.flatpickr-input').parentNode.parentNode.ibexaInstance.flatpickrInstance.setDate(new Date(), true);
|
||||
oneShotModal.querySelector('#create_oneshot_requestedDate').closest('.ibexa-picker').querySelector('.ibexa-date-time-picker').ibexaInstance.flatpickrInstance.setDate(new Date(), true);
|
||||
})
|
||||
.then(() => {
|
||||
bootstrap.Tab.getOrCreateInstance(document.querySelector('#ibexa-tab-label-coderhapsodie-ibexa_dataflow-code-rhapsodie-ibexa_dataflow-oneshot')).show()
|
||||
|
||||
@@ -12,7 +12,7 @@ class PolicyProvider extends YamlPolicyProvider implements PolicyProviderInterfa
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getFiles()
|
||||
protected function getFiles(): array
|
||||
{
|
||||
return [__DIR__.'/../Resources/config/policies.yaml'];
|
||||
}
|
||||
|
||||
45
src/Tab/DashboardTab.php
Normal file
45
src/Tab/DashboardTab.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\IbexaDataflowBundle\Tab;
|
||||
|
||||
use CodeRhapsodie\IbexaDataflowBundle\Controller\DashboardController;
|
||||
use Ibexa\Contracts\AdminUi\Tab\AbstractControllerBasedTab;
|
||||
use Ibexa\Contracts\AdminUi\Tab\OrderedTabInterface;
|
||||
use Symfony\Component\HttpKernel\Controller\ControllerReference;
|
||||
|
||||
class DashboardTab extends AbstractControllerBasedTab implements OrderedTabInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getControllerReference(array $parameters): ControllerReference
|
||||
{
|
||||
return new ControllerReference(DashboardController::class.'::dashboard');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOrder(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIdentifier(): string
|
||||
{
|
||||
return 'code-rhapsodie-ibexa_dataflow-dashboard';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->translator->trans('coderhapsodie.ibexa_dataflow.dashboard');
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ use Ibexa\Contracts\Core\Repository\UserService;
|
||||
class UserSwitcher implements UserSwitcherInterface
|
||||
{
|
||||
/** @var \Ibexa\Contracts\Core\Repository\Values\User\UserReference[] */
|
||||
private $userStack;
|
||||
private array $userStack;
|
||||
|
||||
/**
|
||||
* @param string|int $adminLoginOrId
|
||||
@@ -46,4 +46,3 @@ class UserSwitcher implements UserSwitcherInterface
|
||||
$this->permissionResolver->setCurrentUserReference(array_pop($this->userStack));
|
||||
}
|
||||
}
|
||||
class_alias(UserSwitcher::class, 'CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcher');
|
||||
|
||||
@@ -8,4 +8,3 @@ interface UserSwitcherAwareInterface
|
||||
{
|
||||
public function setUserSwitcher(UserSwitcherInterface $userSwitcher): void;
|
||||
}
|
||||
class_alias(UserSwitcherAwareInterface::class, 'CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcherAwareInterface');
|
||||
|
||||
@@ -6,13 +6,10 @@ namespace CodeRhapsodie\IbexaDataflowBundle\UserSwitcher;
|
||||
|
||||
trait UserSwitcherAwareTrait
|
||||
{
|
||||
/** @var UserSwitcherInterface */
|
||||
protected $userSwitcher;
|
||||
protected UserSwitcherInterface $userSwitcher;
|
||||
|
||||
public function setUserSwitcher(UserSwitcherInterface $userSwitcher): void
|
||||
{
|
||||
$this->userSwitcher = $userSwitcher;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias(UserSwitcherAwareTrait::class, 'CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcherAwareTrait');
|
||||
|
||||
@@ -12,4 +12,3 @@ interface UserSwitcherInterface
|
||||
|
||||
public function switchBack(): void;
|
||||
}
|
||||
class_alias(UserSwitcherInterface::class, 'CodeRhapsodie\EzDataflowBundle\UserSwitcher\UserSwitcherInterface');
|
||||
|
||||
@@ -55,7 +55,7 @@ class ContentWriter extends RepositoryWriter implements DelegateWriterInterface
|
||||
return $item instanceof ContentStructure;
|
||||
}
|
||||
|
||||
private function log(string $level, string $message, array $context = [])
|
||||
private function log(string $level, string $message, array $context = []): void
|
||||
{
|
||||
if (null === $this->logger) {
|
||||
return;
|
||||
@@ -63,4 +63,3 @@ class ContentWriter extends RepositoryWriter implements DelegateWriterInterface
|
||||
$this->logger->log($level, $message, $context);
|
||||
}
|
||||
}
|
||||
class_alias(ContentWriter::class, 'CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter');
|
||||
|
||||
@@ -12,14 +12,13 @@ abstract class RepositoryWriter implements WriterInterface, UserSwitcherAwareInt
|
||||
{
|
||||
use UserSwitcherAwareTrait;
|
||||
|
||||
public function prepare()
|
||||
public function prepare(): void
|
||||
{
|
||||
$this->userSwitcher->switchToAdmin();
|
||||
}
|
||||
|
||||
public function finish()
|
||||
public function finish(): void
|
||||
{
|
||||
$this->userSwitcher->switchBack();
|
||||
}
|
||||
}
|
||||
class_alias(RepositoryWriter::class, 'CodeRhapsodie\EzDataflowBundle\Writer\RepositoryWriter');
|
||||
|
||||
Reference in New Issue
Block a user