Skip to content

Commit fd709ed

Browse files
authored
Merge pull request #1 from teamneusta/feature/export-controller
[Feature] Add `PageExportController` to bundle
2 parents 7eb9595 + af8d5db commit fd709ed

File tree

13 files changed

+430
-17
lines changed

13 files changed

+430
-17
lines changed

config/pimcore/config.yaml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
###########################################################
2+
# Neusta Converter Bundle
3+
###########################################################
4+
neusta_converter:
5+
converter:
6+
###########################################################
7+
# Import Converter (YamlExportPage -> Page)
8+
###########################################################
9+
neusta_pimcore_import_export.import_page:
10+
target: Pimcore\Model\Document\Page
11+
populators:
12+
- Neusta\Pimcore\ImportExportBundle\Documents\Import\PageImportPopulator
13+
properties:
14+
id:
15+
source: id
16+
default: 0
17+
key: ~
18+
title:
19+
source: title
20+
default: 'no title'
21+
controller:
22+
source: controller
23+
default: 'no controller'
24+
type:
25+
source: type
26+
default: 'page'
27+
published:
28+
source: published
29+
default: false
30+
path:
31+
source: path
32+
default: '/'
33+
parentId:
34+
source: parentId
35+
default: 0
36+
37+
###########################################################
38+
# Export Converter (Page -> YamlExportPage)
39+
###########################################################
40+
neusta_pimcore_import_export.export_page:
41+
target: Neusta\Pimcore\ImportExportBundle\Documents\Export\YamlExportPage
42+
populators:
43+
- neusta_pimcore_import_export.page.property.language.populator
44+
- neusta_pimcore_import_export.page.property.navigation_title.populator
45+
- neusta_pimcore_import_export.page.property.navigation_name.populator
46+
- neusta_pimcore_import_export.page.editables.populator
47+
properties:
48+
id: ~
49+
key: ~
50+
title: ~
51+
controller: ~
52+
type: ~
53+
published: ~
54+
path: ~
55+
parentId: ~
56+
57+
neusta_pimcore_import_export.editable_converter:
58+
target: Neusta\Pimcore\ImportExportBundle\Documents\Export\YamlExportEditable
59+
properties:
60+
type: ~
61+
name: ~
62+
data: ~

config/pimcore/routing.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
neusta_pimcore_import_export_page_export:
2+
resource: '../../src/Controller/Admin/PageExportController.php'
3+
type: attribute
4+
options:
5+
expose: true

config/services.yaml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,58 @@ services:
22
_defaults:
33
autowire: true
44
autoconfigure: true
5+
6+
Neusta\Pimcore\ImportExportBundle\Toolbox\:
7+
resource: '../src/Toolbox'
8+
9+
###########################################################
10+
# Controller
11+
###########################################################
12+
Neusta\Pimcore\ImportExportBundle\Controller\Admin\PageExportController:
13+
public: true
14+
tags: [ 'controller.service_arguments' ]
15+
16+
###########################################################
17+
# Import Populator (YamlExportPage -> Page)
18+
###########################################################
19+
Neusta\Pimcore\ImportExportBundle\Documents\Import\PageImportPopulator: ~
20+
21+
Neusta\Pimcore\ImportExportBundle\Documents\Import\PageImporter:
22+
arguments:
23+
$yamlToPageConverter: '@neusta_pimcore_import_export.import_page'
24+
25+
###########################################################
26+
# Export Populator (Page -> YamlExportPage)
27+
###########################################################
28+
neusta_pimcore_import_export.page.editables.populator:
29+
class: Neusta\ConverterBundle\Populator\ArrayConvertingPopulator
30+
arguments:
31+
$converter: '@neusta_pimcore_import_export.editable_converter'
32+
$sourceArrayPropertyName: 'editables'
33+
$targetPropertyName: 'editables'
34+
35+
neusta_pimcore_import_export.page.property.language.populator:
36+
class: Neusta\Pimcore\ImportExportBundle\PimcoreConverter\Populator\PropertyBasedMappingPopulator
37+
arguments:
38+
$propertyKey: 'language'
39+
$targetProperty: 'language'
40+
41+
neusta_pimcore_import_export.page.property.navigation_title.populator:
42+
class: Neusta\Pimcore\ImportExportBundle\PimcoreConverter\Populator\PropertyBasedMappingPopulator
43+
arguments:
44+
$propertyKey: 'navigation_title'
45+
$targetProperty: 'navigation_title'
46+
47+
neusta_pimcore_import_export.page.property.navigation_name.populator:
48+
class: Neusta\Pimcore\ImportExportBundle\PimcoreConverter\Populator\PropertyBasedMappingPopulator
49+
arguments:
50+
$propertyKey: 'navigation_name'
51+
$targetProperty: 'navigation_name'
52+
53+
Neusta\Pimcore\ImportExportBundle\Documents\Export\PageExporter:
54+
arguments:
55+
$pageToYamlConverter: '@neusta_pimcore_import_export.export_page'
56+
57+
Neusta\Pimcore\ImportExportBundle\EventListener\PimcoreAdminListener:
58+
tags:
59+
- { name: kernel.event_listener, event: pimcore.bundle_manager.paths.js, method: addJSFiles }

public/js/exportPage.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
pimcore.registerNS("neusta_pimcore_import_export.plugin.page.export");
2+
3+
neusta_pimcore_import_export.plugin.page.export = Class.create({
4+
initialize: function () {
5+
document.addEventListener(pimcore.events.prepareDocumentTreeContextMenu, this.onPrepareDocumentTreeContextMenu.bind(this));
6+
},
7+
8+
onPrepareDocumentTreeContextMenu: function (e) {
9+
let menu = e.detail.menu;
10+
let document = e.detail.document;
11+
// Export page into yaml file
12+
menu.add("-");
13+
menu.add(new Ext.menu.Item({
14+
text: 'Export to YAML',
15+
iconCls: "pimcore_icon_export",
16+
handler: function () {
17+
pimcore.helpers.download(Routing.generate('neusta_pimcore_import_export_page_export', {page_id: document.data.id}));
18+
}
19+
}));
20+
},
21+
22+
});
23+
24+
var pimcorePluginPageExport = new neusta_pimcore_import_export.plugin.page.export();
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Neusta\Pimcore\ImportExportBundle\Controller\Admin;
4+
5+
use Neusta\Pimcore\ImportExportBundle\Documents\Export\PageExporter;
6+
use Neusta\Pimcore\ImportExportBundle\Toolbox\Repository\PageRepository;
7+
use Pimcore\Model\Document\Page;
8+
use Symfony\Component\HttpFoundation\HeaderUtils;
9+
use Symfony\Component\HttpFoundation\JsonResponse;
10+
use Symfony\Component\HttpFoundation\Request;
11+
use Symfony\Component\HttpFoundation\Response;
12+
use Symfony\Component\Routing\Annotation\Route;
13+
14+
final class PageExportController
15+
{
16+
public function __construct(
17+
private PageExporter $pageExporter,
18+
private PageRepository $pageRepository,
19+
) {
20+
}
21+
22+
#[Route(
23+
'/admin/neusta/import-export/page/export',
24+
name: 'neusta_pimcore_import_export_page_export',
25+
methods: ['GET']
26+
)]
27+
public function exportPage(Request $request): Response
28+
{
29+
$pageId = $request->query->getInt('page_id');
30+
$page = $this->pageRepository->getById($pageId);
31+
32+
if (!$page instanceof Page) {
33+
return new JsonResponse(
34+
\sprintf('Page with id "%s" was not found', $pageId),
35+
Response::HTTP_NOT_FOUND,
36+
);
37+
}
38+
39+
try {
40+
$yaml = $this->pageExporter->toYaml($page);
41+
} catch (\Exception $e) {
42+
return new JsonResponse($e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
43+
}
44+
45+
$response = new Response($yaml);
46+
$response->headers->set('Content-type', 'application/yaml');
47+
$response->headers->set(
48+
'Content-Disposition',
49+
HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, $this->createFilename($page)),
50+
);
51+
52+
return $response;
53+
}
54+
55+
private function createFilename(Page $page): string
56+
{
57+
return \sprintf('%s.yaml', str_replace(' ', '_', (string) $page->getKey()));
58+
}
59+
}

src/DependencyInjection/NeustaPimcoreImportExportExtension.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php declare(strict_types=1);
22

3+
namespace Neusta\Pimcore\ImportExportBundle\DependencyInjection;
4+
35
use Symfony\Component\Config\FileLocator;
46
use Symfony\Component\DependencyInjection\ContainerBuilder;
57
use Symfony\Component\DependencyInjection\Loader;
@@ -9,7 +11,7 @@ final class NeustaPimcoreImportExportExtension extends Extension
911
{
1012
public function load(array $configs, ContainerBuilder $container): void
1113
{
12-
$loader = new Loader\YamlFileLoader($container, new FileLocator(dirname(__DIR__, 2) . '/config'));
14+
$loader = new Loader\YamlFileLoader($container, new FileLocator(\dirname(__DIR__, 2) . '/config'));
1315
$loader->load('services.yaml');
1416
}
1517
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Neusta\Pimcore\ImportExportBundle\EventListener;
4+
5+
use Pimcore\Event\BundleManager\PathsEvent;
6+
7+
final class PimcoreAdminListener
8+
{
9+
public function addJSFiles(PathsEvent $event): void
10+
{
11+
$event->addPaths([
12+
'/bundles/neustapimcoreimportexport/js/exportPage.js',
13+
]);
14+
}
15+
}

src/NeustaPimcoreImportExportBundle.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,23 @@
22

33
namespace Neusta\Pimcore\ImportExportBundle;
44

5+
use Neusta\ConverterBundle\NeustaConverterBundle;
56
use Pimcore\Extension\Bundle\AbstractPimcoreBundle;
67
use Pimcore\Extension\Bundle\Traits\PackageVersionTrait;
8+
use Pimcore\HttpKernel\Bundle\DependentBundleInterface;
9+
use Pimcore\HttpKernel\BundleCollection\BundleCollection;
710

8-
final class NeustaPimcoreImportExportBundle extends AbstractPimcoreBundle
11+
final class NeustaPimcoreImportExportBundle extends AbstractPimcoreBundle implements DependentBundleInterface
912
{
1013
use PackageVersionTrait;
1114

1215
public function getPath(): string
1316
{
1417
return \dirname(__DIR__);
1518
}
19+
20+
public static function registerDependentBundles(BundleCollection $collection): void
21+
{
22+
$collection->addBundle(NeustaConverterBundle::class);
23+
}
1624
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Neusta\Pimcore\ImportExportBundle\PimcoreConverter\Populator;
4+
5+
use Neusta\ConverterBundle\Exception\PopulationException;
6+
use Neusta\ConverterBundle\Populator;
7+
use Symfony\Component\PropertyAccess\PropertyAccess;
8+
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
9+
10+
/**
11+
* @template TSource of object
12+
* @template TTarget of object
13+
* @template TContext of object|null
14+
*
15+
* @implements Populator<TSource, TTarget, TContext>
16+
*/
17+
final class PropertyBasedMappingPopulator implements Populator
18+
{
19+
/** @var \Closure(mixed, TContext=):mixed */
20+
private \Closure $mapper;
21+
private PropertyAccessorInterface $accessor;
22+
23+
/**
24+
* @param \Closure(mixed, TContext=):mixed|null $mapper
25+
*/
26+
public function __construct(
27+
private string $targetProperty,
28+
private string $propertyKey,
29+
private mixed $defaultValue = null,
30+
?\Closure $mapper = null,
31+
?PropertyAccessorInterface $accessor = null,
32+
private bool $skipNull = false,
33+
) {
34+
$this->mapper = $mapper ?? static fn ($v) => $v;
35+
$this->accessor = $accessor ?? PropertyAccess::createPropertyAccessor();
36+
}
37+
38+
/**
39+
* @throws PopulationException
40+
*/
41+
public function populate(object $target, object $source, ?object $ctx = null): void
42+
{
43+
try {
44+
$value = $this->defaultValue;
45+
46+
if (method_exists($source, 'getProperty') && $source->getProperty($this->propertyKey)) {
47+
$value = $source->getProperty($this->propertyKey);
48+
}
49+
50+
if (!$this->skipNull || (null !== $value)) {
51+
$this->accessor->setValue($target, $this->targetProperty, ($this->mapper)($value, $ctx));
52+
}
53+
} catch (\Throwable $exception) {
54+
throw new PopulationException('property["' . $this->propertyKey . '"]', $this->targetProperty, $exception);
55+
}
56+
}
57+
}

tests/DummyUnitTest.php

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)