diff --git a/.php_cs b/.php_cs
new file mode 100644
index 0000000..4cd3303
--- /dev/null
+++ b/.php_cs
@@ -0,0 +1,14 @@
+setFinder(
+ PhpCsFixer\Finder::create()
+ ->in(__DIR__)
+ ->exclude([
+ '.cs',
+ '.platform',
+ 'vendor',
+ ])
+ ->files()->name('*.php')
+ )
+;
diff --git a/.travis.yml b/.travis.yml
index f5c6310..25163c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,6 @@ cache:
- vendor
php:
- - 7.1
- 7.2
before_install:
@@ -19,7 +18,6 @@ install:
- composer info -i
script:
- - php vendor/bin/phpcs --standard=.cs/cs_ruleset.xml --extensions=php bundle/
- - php vendor/bin/phpcs --standard=.cs/cs_ruleset.xml --extensions=php lib/
- - php vendor/bin/phpcs --standard=.cs/cs_ruleset.xml --extensions=php tests/
+ - php vendor/bin/php-cs-fixer fix -v --dry-run --show-progress=estimating
- php vendor/bin/phpunit
+
diff --git a/bundle/Command/TranslateContentCommand.php b/bundle/Command/TranslateContentCommand.php
index 2a76521..700dce5 100644
--- a/bundle/Command/TranslateContentCommand.php
+++ b/bundle/Command/TranslateContentCommand.php
@@ -1,19 +1,17 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\EzPlatformAutomatedTranslationBundle\Command;
+use eZ\Publish\API\Repository\ContentService;
+use eZ\Publish\API\Repository\PermissionResolver;
+use eZ\Publish\API\Repository\UserService;
use EzSystems\EzPlatformAutomatedTranslation\ClientProvider;
-use EzSystems\EzPlatformAutomatedTranslation\RepositoryAware;
use EzSystems\EzPlatformAutomatedTranslation\Translator;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
@@ -21,37 +19,41 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
-/**
- * Class TranslateContentCommand.
- */
-class TranslateContentCommand extends Command
+final class TranslateContentCommand extends Command
{
- use RepositoryAware;
- /**
- * @var Translator
- */
+ private const ADMINISTRATOR_USER_ID = 14;
+
+ /** @var Translator */
private $translator;
- /**
- * @var ClientProvider
- */
+ /** @var ClientProvider */
private $clientProvider;
- /**
- * TranslateContentCommand constructor.
- *
- * @param Translator $translator
- */
- public function __construct(Translator $translator, ClientProvider $clientProvider)
- {
+ /** @var \eZ\Publish\API\Repository\ContentService */
+ private $contentService;
+
+ /** @var \eZ\Publish\API\Repository\PermissionResolver */
+ private $permissionResolver;
+
+ /** @var \eZ\Publish\API\Repository\UserService */
+ private $userService;
+
+ public function __construct(
+ Translator $translator,
+ ClientProvider $clientProvider,
+ ContentService $contentService,
+ PermissionResolver $permissionResolver,
+ UserService $userService
+ ) {
$this->clientProvider = $clientProvider;
- parent::__construct();
$this->translator = $translator;
+ $this->contentService = $contentService;
+ $this->permissionResolver = $permissionResolver;
+ $this->userService = $userService;
+
+ parent::__construct();
}
- /**
- * {@inheritdoc}
- */
protected function configure(): void
{
$this
@@ -69,31 +71,27 @@ protected function configure(): void
->addOption('to', '--to', InputOption::VALUE_REQUIRED, 'Target Language');
}
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output): void
+ protected function execute(InputInterface $input, OutputInterface $output): int
{
$contentId = (int) $input->getArgument('contentId');
- $content = $this->repository->getContentService()->loadContent($contentId);
- $draft = $this->translator->getTranslatedContent(
+ $content = $this->contentService->loadContent($contentId);
+ $draft = $this->translator->getTranslatedContent(
$input->getOption('from'),
$input->getOption('to'),
$input->getArgument('service'),
$content
);
- $this->repository->getContentService()->publishVersion($draft->versionInfo);
+ $this->contentService->publishVersion($draft->versionInfo);
$output->writeln("Translation to {$contentId} Done.");
+
+ return Command::SUCCESS;
}
- /**
- * {@inheritdoc}
- */
protected function initialize(InputInterface $input, OutputInterface $output): void
{
parent::initialize($input, $output);
- $this->repository->getPermissionResolver()->setCurrentUserReference(
- $this->repository->getUserService()->loadUser(14)
+ $this->permissionResolver->setCurrentUserReference(
+ $this->userService->loadUser(self::ADMINISTRATOR_USER_ID)
);
}
}
diff --git a/bundle/Controller/TranslationController.php b/bundle/Controller/TranslationController.php
index 934b336..738e139 100644
--- a/bundle/Controller/TranslationController.php
+++ b/bundle/Controller/TranslationController.php
@@ -1,58 +1,133 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\EzPlatformAutomatedTranslationBundle\Controller;
use EzSystems\EzPlatformAdminUiBundle\Controller\TranslationController as BaseTranslationController;
+use EzSystems\EzPlatformAdminUiBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Exception\RouteNotFoundException;
+use Symfony\Component\Routing\RouterInterface;
-/**
- * Class TranslationController.
- */
class TranslationController extends BaseTranslationController
{
- /**
- * {@inheritdoc}
- */
+// /** @var \EzSystems\EzPlatformAdminUiBundle\Controller\TranslationController */
+// private $translationController;
+//
+// public function __construct(BaseTranslationController $translationController)
+// {
+// $this->translationController = $translationController;
+// }
+
public function addAction(Request $request): Response
{
$response = parent::addAction($request);
+
if (!$response instanceof RedirectResponse) {
return $response;
}
- $targetUrl = $response->getTargetUrl();
- $pattern = str_replace(
+ $targetUrl = $response->getTargetUrl();
+ $contentTranslatePattern = str_replace(
'/',
'\/?',
urldecode(
$this->generateUrl(
'ezplatform.content.translate',
[
- 'contentId' => '([0-9]*)',
+ 'contentId' => '([0-9]*)',
'fromLanguageCode' => '([a-zA-Z-]*)',
- 'toLanguageCode' => '([a-zA-Z-]*)',
+ 'toLanguageCode' => '([a-zA-Z-]*)',
]
)
)
);
+
+
+ try {
+ // admin-ui v3.3.6 introduces different route `ibexa.content.translate_with_location.proxy`
+ // when translated content is created.
+ $contentTranslateWithLocationPattern = str_replace(
+ '/',
+ '\/?',
+ urldecode(
+ $this->generateUrl(
+ 'ibexa.content.translate_with_location.proxy',
+ [
+ 'contentId' => '([0-9]*)',
+ 'fromLanguageCode' => '([a-zA-Z-]*)',
+ 'toLanguageCode' => '([a-zA-Z-]*)',
+ 'locationId' => '([0-9]*)',
+ ]
+ )
+ )
+ );
+ } catch (\Symfony\Component\Routing\Exception\RouteNotFoundException $exception) {
+ $contentTranslateWithLocationPattern = 'NOP';
+ }
+
+ try {
+ $contentTranslateWithLocationPatternWithOutProxy = str_replace(
+ '/',
+ '\/?',
+ urldecode(
+ $this->generateUrl(
+ // path: /content/{contentId}/location/{locationId}/translate/{toLanguageCode}/{fromLanguageCode}
+ 'ibexa.content.translate_with_location',
+ [
+ 'contentId' => '([0-9]*)',
+ 'locationId' => '([0-9]*)',
+ 'fromLanguageCode' => '([a-zA-Z-]*)',
+ 'toLanguageCode' => '([a-zA-Z-]*)',
+ ]
+ )
+ )
+ );
+ } catch (\Symfony\Component\Routing\Exception\RouteNotFoundException $exception) {
+ $contentTranslateWithLocationPatternWithOutProxy = 'NOP';
+ }
+
$serviceAlias = $request->request->get('add-translation')['translatorAlias'] ?? '';
- if (1 !== preg_match("#{$pattern}#", $targetUrl) || '' === $serviceAlias) {
+
+// dump([
+// '$targetUrl' => $targetUrl,
+// '$serviceAlias' => $serviceAlias,
+// '$contentTranslatePattern' => $contentTranslatePattern,
+// '$contentTranslateWithLocationPattern' => $contentTranslateWithLocationPattern,
+// '$contentTranslateWithLocationPatternWithOutProxy' => $contentTranslateWithLocationPatternWithOutProxy,
+// ]);
+
+ if ('' === $serviceAlias || (
+ !$this->targetUrlContainsPattern($targetUrl, $contentTranslatePattern) &&
+ !$this->targetUrlContainsPattern($targetUrl, $contentTranslateWithLocationPattern) &&
+ !$this->targetUrlContainsPattern($targetUrl, $contentTranslateWithLocationPatternWithOutProxy)
+ )) {
+// dump(__LINE__);
+// die(__METHOD__);
return $response;
}
+
$response->setTargetUrl(sprintf('%s?translatorAlias=%s', $targetUrl, $serviceAlias));
+// dump(__LINE__);
+// die(__METHOD__);
return $response;
}
+
+ public function removeAction(Request $request): Response
+ {
+ return parent::removeAction($request);
+ }
+
+ private function targetUrlContainsPattern(string $targetUrl, string $pattern): bool
+ {
+ return 1 === preg_match("#{$pattern}#", $targetUrl);
+ }
}
diff --git a/bundle/DependencyInjection/Configuration.php b/bundle/DependencyInjection/Configuration.php
index 7bea9bc..89f872c 100644
--- a/bundle/DependencyInjection/Configuration.php
+++ b/bundle/DependencyInjection/Configuration.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -15,23 +11,18 @@
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\SiteAccessAware;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-/**
- * Class Configuration.
- */
class Configuration extends SiteAccessAware\Configuration
{
- /**
- * {@inheritdoc}
- */
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('ez_platform_automated_translation');
- $systemNode = $this->generateScopeBaseNode($rootNode);
+ $systemNode = $this->generateScopeBaseNode($rootNode);
$systemNode
->variableNode('configurations')->end()
- ->arrayNode('nontranslatablecharacters')->end()
- ->arrayNode('nontranslatabletags')->end();
+ ->arrayNode('non_translatable_characters')->end()
+ ->arrayNode('non_translatable_tags')->end()
+ ->arrayNode('non_translatable_self_closed_tags')->end();
return $treeBuilder;
}
diff --git a/bundle/DependencyInjection/EzPlatformAutomatedTranslationExtension.php b/bundle/DependencyInjection/EzPlatformAutomatedTranslationExtension.php
index d592c8a..5b3a7af 100644
--- a/bundle/DependencyInjection/EzPlatformAutomatedTranslationExtension.php
+++ b/bundle/DependencyInjection/EzPlatformAutomatedTranslationExtension.php
@@ -1,26 +1,21 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\EzPlatformAutomatedTranslationBundle\DependencyInjection;
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\SiteAccessAware\ConfigurationProcessor;
+use EzSystems\EzPlatformAutomatedTranslation\Encoder\BlockAttribute\BlockAttributeEncoderInterface;
+use EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\FieldEncoderInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
-/**
- * Class EzPlatformAutomatedTranslationExtension.
- */
class EzPlatformAutomatedTranslationExtension extends Extension
{
/**
@@ -29,39 +24,41 @@ class EzPlatformAutomatedTranslationExtension extends Extension
public function load(array $configs, ContainerBuilder $container): void
{
$configuration = new Configuration();
- $config = $this->processConfiguration($configuration, $configs);
+ $config = $this->processConfiguration($configuration, $configs);
+ if (empty($config['system'])) {
+ return;
+ }
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
// always needed because of Bundle extension.
$loader->load('services_override.yml');
- if (empty($config['system'])) {
- return;
- }
+ $container->registerForAutoconfiguration(FieldEncoderInterface::class)
+ ->addTag('ezplatform.automated_translation.field_encoder');
+
+ $container->registerForAutoconfiguration(BlockAttributeEncoderInterface::class)
+ ->addTag('ezplatform.automated_translation.block_attribute_encoder');
if (!$this->hasConfiguredClients($config, $container)) {
return;
}
- $asseticBundles = $container->getParameter('assetic.bundles');
- $asseticBundles[] = 'EzPlatformAutomatedTranslationBundle';
- $container->setParameter('assetic.bundles', $asseticBundles);
-
$loader->load('ezadminui.yml');
$loader->load('default_settings.yml');
$loader->load('services.yml');
$processor = new ConfigurationProcessor($container, $this->getAlias());
$processor->mapSetting('configurations', $config);
- $processor->mapSetting('nontranslatablecharacters', $config);
- $processor->mapSetting('nontranslatabletags', $config);
- $processor->mapSetting('nonnalidattributetags', $config);
+ $processor->mapSetting('non_translatable_characters', $config);
+ $processor->mapSetting('non_translatable_tags', $config);
+ $processor->mapSetting('non_translatable_self_closed_tags', $config);
+ $processor->mapSetting('non_valid_attribute_tags', $config);
}
private function hasConfiguredClients(array $config, ContainerBuilder $container): bool
{
- return 0 !== count(array_filter($config['system'], function ($value) use ($container) {
- return array_filter($value['configurations'], function ($value) use ($container) {
+ return 0 !== count(array_filter($config['system'], static function ($value) use ($container) {
+ return array_filter($value['configurations'], static function ($value) use ($container) {
$value = is_array($value) ? reset($value) : $value;
return !empty($container->resolveEnvPlaceholders($value, true));
diff --git a/bundle/Event/FieldDecodeEvent.php b/bundle/Event/FieldDecodeEvent.php
new file mode 100644
index 0000000..3c3e667
--- /dev/null
+++ b/bundle/Event/FieldDecodeEvent.php
@@ -0,0 +1,63 @@
+type = $type;
+ $this->value = $value;
+ $this->previousValue = $previousValue;
+ }
+
+ public function getType(): string
+ {
+ return $this->type;
+ }
+
+ public function setType(string $type): void
+ {
+ $this->type = $type;
+ }
+
+ public function getValue(): Value
+ {
+ return $this->value;
+ }
+
+ public function setValue(Value $value): void
+ {
+ $this->value = $value;
+ }
+
+ public function getPreviousValue()
+ {
+ return $this->previousValue;
+ }
+
+ public function setPreviousValue($previousValue): void
+ {
+ $this->previousValue = $previousValue;
+ }
+}
diff --git a/bundle/Event/FieldEncodeEvent.php b/bundle/Event/FieldEncodeEvent.php
new file mode 100644
index 0000000..f42d218
--- /dev/null
+++ b/bundle/Event/FieldEncodeEvent.php
@@ -0,0 +1,48 @@
+field = $field;
+ $this->value = $value;
+ }
+
+ public function getField(): Field
+ {
+ return $this->field;
+ }
+
+ public function setField(Field $field): void
+ {
+ $this->field = $field;
+ }
+
+ public function getValue(): string
+ {
+ return $this->value;
+ }
+
+ public function setValue(string $value): void
+ {
+ $this->value = $value;
+ }
+}
diff --git a/bundle/EventListener/ContentProxyTranslateListener.php b/bundle/EventListener/ContentProxyTranslateListener.php
new file mode 100644
index 0000000..1746aae
--- /dev/null
+++ b/bundle/EventListener/ContentProxyTranslateListener.php
@@ -0,0 +1,91 @@
+requestStack = $requestStack;
+ $this->translator = $translator;
+ $this->contentService = $contentService;
+ $this->router = $router;
+ }
+
+ public static function getSubscribedEvents(): array
+ {
+ return [
+ ContentProxyTranslateEvent::class => ['translate', 100],
+ ];
+ }
+
+ public function translate(ContentProxyTranslateEvent $event): void
+ {
+ $request = $this->requestStack->getMainRequest();
+
+ if (null === $request) {
+ return;
+ }
+
+ if (!$request->query->has('translatorAlias')) {
+ return;
+ }
+
+ $content = $this->contentService->loadContent(
+ $event->getContentId(),
+ $event->getFromLanguageCode() !== null
+ ? [$event->getFromLanguageCode()]
+ : null
+ );
+
+ $fromLanguageCode = $event->getFromLanguageCode();
+ $toLanguageCode = $event->getToLanguageCode();
+
+ $contentDraft = $this->translator->getTranslatedContent(
+ $fromLanguageCode,
+ $toLanguageCode,
+ $request->query->get('translatorAlias'),
+ $content
+ );
+
+ $response = new RedirectResponse(
+ $this->router->generate('ezplatform.content.draft.edit', [
+ 'contentId' => $contentDraft->id,
+ 'versionNo' => $contentDraft->getVersionInfo()->versionNo,
+ 'language' => $toLanguageCode,
+ ])
+ );
+
+ $event->stopPropagation();
+ $event->setResponse($response);
+ }
+}
diff --git a/bundle/Events.php b/bundle/Events.php
new file mode 100644
index 0000000..1628efc
--- /dev/null
+++ b/bundle/Events.php
@@ -0,0 +1,22 @@
+
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -15,22 +11,13 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
-/**
- * Class EzPlatformAutomatedTranslationBundle.
- */
class EzPlatformAutomatedTranslationBundle extends Bundle
{
- /**
- * {@inheritdoc}
- */
public function getParent(): ?string
{
return 'EzPlatformAdminUiBundle';
}
- /**
- * {@inheritdoc}
- */
public function build(ContainerBuilder $container): void
{
parent::build($container);
diff --git a/bundle/Form/Data/TranslationAddData.php b/bundle/Form/Data/TranslationAddData.php
index 409a287..c3cf16a 100644
--- a/bundle/Form/Data/TranslationAddData.php
+++ b/bundle/Form/Data/TranslationAddData.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -14,27 +10,18 @@
use EzSystems\EzPlatformAdminUi\Form\Data\Content\Translation\TranslationAddData as BaseTranslationAddData;
-/**
- * Class TranslationAddData.
- */
class TranslationAddData extends BaseTranslationAddData
{
- /**
- * @var string
- */
+ /** @var string */
protected $translatorAlias;
- /**
- * @return mixed
- */
+ /** @return mixed */
public function getTranslatorAlias()
{
return $this->translatorAlias;
}
- /**
- * @param mixed $translatorAlias
- */
+ /** @param mixed $translatorAlias */
public function setTranslatorAlias($translatorAlias): void
{
$this->translatorAlias = $translatorAlias;
diff --git a/bundle/Form/Extension/ContentEditType.php b/bundle/Form/Extension/ContentEditType.php
index 5a95a12..7f1dbe5 100644
--- a/bundle/Form/Extension/ContentEditType.php
+++ b/bundle/Form/Extension/ContentEditType.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -14,8 +10,12 @@
use eZ\Publish\API\Repository\ContentTypeService;
use EzSystems\EzPlatformAdminUi\RepositoryForms\Data\ContentTranslationData;
+// use EzSystems\EzPlatformAdminUi\Form\Data\ContentTranslationData;
+use EzSystems\EzPlatformAdminUi\Form\Type\Content\Translation\TranslationAddType as BaseTranslationAddType;
use EzSystems\EzPlatformAutomatedTranslation\Translator;
use EzSystems\RepositoryForms\Data\Content\FieldData;
+// use EzSystems\EzPlatformContentForms\Data\Content\FieldData;
+// use EzSystems\EzPlatformContentForms\Form\Type\Content\ContentEditType as BaseContentEditType;
use EzSystems\RepositoryForms\Form\Type\Content\ContentEditType as BaseContentEditType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
@@ -23,54 +23,37 @@
use Symfony\Component\Form\FormEvents;
use Symfony\Component\HttpFoundation\RequestStack;
-/**
- * Class ContentEditType.
- */
class ContentEditType extends AbstractTypeExtension
{
- /**
- * @var Translator
- */
+ /** @var Translator */
private $translator;
- /**
- * @var RequestStack
- */
+ /** @var RequestStack */
private $requestStack;
- /**
- * @var ContentTypeService
- */
+ /** @var ContentTypeService */
private $contentTypeService;
- /**
- * ContentEditType constructor.
- *
- * @param Translator $translator
- * @param RequestStack $requestStack
- * @param ContentTypeService $contentTypeService
- */
public function __construct(
Translator $translator,
RequestStack $requestStack,
ContentTypeService $contentTypeService
) {
- $this->translator = $translator;
- $this->requestStack = $requestStack;
+ $this->translator = $translator;
+ $this->requestStack = $requestStack;
$this->contentTypeService = $contentTypeService;
}
- /**
- * {@inheritdoc}
- */
public function getExtendedType(): string
{
return BaseContentEditType::class;
}
- /**
- * {@inheritdoc}
- */
+ public static function getExtendedTypes(): iterable
+ {
+ return [BaseContentEditType::class];
+ }
+
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addEventListener(
@@ -87,27 +70,27 @@ function (FormEvent $event) {
if (!$request->query->has('translatorAlias')) {
return;
}
- $fromLanguageCode = $request->attributes->get('fromLanguageCode') ?? null;
- $toLanguageCode = $request->attributes->get('toLanguageCode') ?? null;
+ $fromLanguageCode = $request->attributes->get('fromLanguageCode', null);
+ $toLanguageCode = $request->attributes->get('toLanguageCode', null);
$translatedFields = $this->translator->getTranslatedFields(
$fromLanguageCode,
$toLanguageCode,
$request->query->get('translatorAlias'),
$data->content
);
- $contentType = $this->contentTypeService->loadContentType(
+ $contentType = $this->contentTypeService->loadContentType(
$data->content->contentInfo->contentTypeId
);
foreach ($data->content->getFieldsByLanguage() as $field) {
- $fieldDef = $contentType->getFieldDefinition($field->fieldDefIdentifier);
+ $fieldDef = $contentType->getFieldDefinition($field->fieldDefIdentifier);
$fieldValue = $translatedFields[$fieldDef->identifier] ??
$data->content->getFieldValue($fieldDef->identifier, $fromLanguageCode);
$data->addFieldData(
new FieldData(
[
'fieldDefinition' => $fieldDef,
- 'field' => $field,
- 'value' => $fieldValue,
+ 'field' => $field,
+ 'value' => $fieldValue,
]
)
);
diff --git a/bundle/Form/Extension/ContentEditType.php.txt b/bundle/Form/Extension/ContentEditType.php.txt
new file mode 100644
index 0000000..5a95a12
--- /dev/null
+++ b/bundle/Form/Extension/ContentEditType.php.txt
@@ -0,0 +1,119 @@
+
+ * @copyright Copyright (C) eZ Systems AS. All rights reserved.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
+ */
+declare(strict_types=1);
+
+namespace EzSystems\EzPlatformAutomatedTranslationBundle\Form\Extension;
+
+use eZ\Publish\API\Repository\ContentTypeService;
+use EzSystems\EzPlatformAdminUi\RepositoryForms\Data\ContentTranslationData;
+use EzSystems\EzPlatformAutomatedTranslation\Translator;
+use EzSystems\RepositoryForms\Data\Content\FieldData;
+use EzSystems\RepositoryForms\Form\Type\Content\ContentEditType as BaseContentEditType;
+use Symfony\Component\Form\AbstractTypeExtension;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Form\FormEvent;
+use Symfony\Component\Form\FormEvents;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * Class ContentEditType.
+ */
+class ContentEditType extends AbstractTypeExtension
+{
+ /**
+ * @var Translator
+ */
+ private $translator;
+
+ /**
+ * @var RequestStack
+ */
+ private $requestStack;
+
+ /**
+ * @var ContentTypeService
+ */
+ private $contentTypeService;
+
+ /**
+ * ContentEditType constructor.
+ *
+ * @param Translator $translator
+ * @param RequestStack $requestStack
+ * @param ContentTypeService $contentTypeService
+ */
+ public function __construct(
+ Translator $translator,
+ RequestStack $requestStack,
+ ContentTypeService $contentTypeService
+ ) {
+ $this->translator = $translator;
+ $this->requestStack = $requestStack;
+ $this->contentTypeService = $contentTypeService;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getExtendedType(): string
+ {
+ return BaseContentEditType::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(FormBuilderInterface $builder, array $options): void
+ {
+ $builder->addEventListener(
+ FormEvents::PRE_SET_DATA,
+ function (FormEvent $event) {
+ $data = $event->getData();
+ if (!$data instanceof ContentTranslationData) {
+ return;
+ }
+ $request = $this->requestStack->getMasterRequest();
+ if (null === $request) {
+ return;
+ }
+ if (!$request->query->has('translatorAlias')) {
+ return;
+ }
+ $fromLanguageCode = $request->attributes->get('fromLanguageCode') ?? null;
+ $toLanguageCode = $request->attributes->get('toLanguageCode') ?? null;
+ $translatedFields = $this->translator->getTranslatedFields(
+ $fromLanguageCode,
+ $toLanguageCode,
+ $request->query->get('translatorAlias'),
+ $data->content
+ );
+ $contentType = $this->contentTypeService->loadContentType(
+ $data->content->contentInfo->contentTypeId
+ );
+ foreach ($data->content->getFieldsByLanguage() as $field) {
+ $fieldDef = $contentType->getFieldDefinition($field->fieldDefIdentifier);
+ $fieldValue = $translatedFields[$fieldDef->identifier] ??
+ $data->content->getFieldValue($fieldDef->identifier, $fromLanguageCode);
+ $data->addFieldData(
+ new FieldData(
+ [
+ 'fieldDefinition' => $fieldDef,
+ 'field' => $field,
+ 'value' => $fieldValue,
+ ]
+ )
+ );
+ }
+ $event->setData($data);
+ }
+ );
+ }
+}
diff --git a/bundle/Form/Extension/LanguageCreateType.php b/bundle/Form/Extension/LanguageCreateType.php
index 6fbacee..79b88b5 100644
--- a/bundle/Form/Extension/LanguageCreateType.php
+++ b/bundle/Form/Extension/LanguageCreateType.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -17,39 +13,26 @@
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
-/**
- * Class LanguageCreateType.
- */
class LanguageCreateType extends AbstractTypeExtension
{
- /**
- * @var array
- */
+ /** @var array */
private $localeList;
- /**
- * LanguageCreateType constructor.
- *
- * @param array $localeList
- */
public function __construct(array $localeList)
{
$this->localeList = array_keys($localeList);
- // To Be Remove for PROD ready plugin
- $this->localeList['klingon'] = 'klingon';
}
- /**
- * {@inheritdoc}
- */
public function getExtendedType(): string
{
return BaseLanguageCreateType::class;
}
- /**
- * {@inheritdoc}
- */
+ public static function getExtendedTypes(): iterable
+ {
+ return [BaseLanguageCreateType::class];
+ }
+
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->remove('languageCode');
@@ -57,10 +40,10 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'languageCode',
ChoiceType::class,
[
- 'label' => /* @Desc("Language code") */
+ 'label' => /* @Desc("Language code") */
'ezplatform.language.create.language_code',
'required' => false,
- 'choices' => array_combine($this->localeList, $this->localeList),
+ 'choices' => array_combine($this->localeList, $this->localeList),
]
);
}
diff --git a/bundle/Form/Extension/TranslationAddType.php b/bundle/Form/Extension/TranslationAddType.php
index 9c43d41..5e8880f 100644
--- a/bundle/Form/Extension/TranslationAddType.php
+++ b/bundle/Form/Extension/TranslationAddType.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -20,53 +16,40 @@
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
-use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
-/**
- * Class TranslationAddType.
- */
class TranslationAddType extends AbstractTypeExtension
{
- /**
- * @var ClientProvider
- */
+ /** @var ClientProvider */
private $clientProvider;
- /**
- * @var LocaleConverterInterface
- */
+ /** @var LocaleConverterInterface */
private $localeConverter;
- /**
- * TranslationAddType constructor.
- *
- * @param ClientProvider $clientProvider
- * @param LocaleConverterInterface $localeConverter
- */
- public function __construct(ClientProvider $clientProvider, LocaleConverterInterface $localeConverter)
- {
- $this->clientProvider = $clientProvider;
+ public function __construct(
+ ClientProvider $clientProvider,
+ LocaleConverterInterface $localeConverter
+ ) {
+ $this->clientProvider = $clientProvider;
$this->localeConverter = $localeConverter;
}
- /**
- * {@inheritdoc}
- */
public function getExtendedType(): string
{
return BaseTranslationAddType::class;
}
- /**
- * {@inheritdoc}
- */
+ public static function getExtendedTypes(): iterable
+ {
+ return [BaseTranslationAddType::class];
+ }
+
public function buildForm(FormBuilderInterface $builder, array $options): void
{
- $clients = $this->clientProvider->getClients();
+ $clients = $this->clientProvider->getClients();
$clientsCount = count($clients);
if ($clientsCount <= 0) {
@@ -79,9 +62,9 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'translatorAlias',
CheckboxType::class,
[
- 'label' => $client->getServiceFullName(),
- 'value' => $client->getServiceAlias(),
- 'data' => true,
+ 'label' => $client->getServiceFullName(),
+ 'value' => $client->getServiceAlias(),
+ 'data' => true,
'required' => false,
]
);
@@ -95,11 +78,11 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'translatorAlias',
ChoiceType::class,
[
- 'label' => false,
- 'expanded' => false,
- 'multiple' => false,
- 'required' => false,
- 'choices' => ['' => 'no-service'] + $this->clientProvider->getClients(),
+ 'label' => false,
+ 'expanded' => false,
+ 'multiple' => false,
+ 'required' => false,
+ 'choices' => ['' => 'no-service'] + $this->clientProvider->getClients(),
'choice_label' => function ($client) {
if ($client instanceof ClientInterface) {
return ucfirst($client->getServiceFullName());
@@ -119,28 +102,23 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
$builder->addModelTransformer(new TranslationAddDataTransformer());
}
- /**
- * {@inheritdoc}
- */
- public function buildView(FormView $view, FormInterface $form, array $options): void
+ public function buildView(FormView $view, FormInterface $form, array $options)
{
// let's pass to the template/form the possible language
$map = [];
$fillMap = function ($key, &$map) use ($form) {
$languages = $form->get($key);
- foreach ($languages as $language) {
- /** @var Form $language */
- /** @var FormBuilderInterface $config */
- $config = $language->getConfig();
- $lang = $config->getOption('value');
+ $choices = $languages->getConfig()->getAttribute('choice_list')->getChoices();
+ /** @var \eZ\Publish\API\Repository\Values\Content\Language $language */
+ foreach ($choices as $language) {
foreach ($this->clientProvider->getClients() as $client) {
- $posix = $this->localeConverter->convertToPOSIX($lang);
+ $posix = $this->localeConverter->convertToPOSIX($language->languageCode);
if (null === $posix) {
continue;
}
if ($client->supportsLanguage($posix)) {
- $map[$client->getServiceAlias()][] = $lang;
+ $map[$client->getServiceAlias()][] = $language->languageCode;
}
}
}
@@ -153,14 +131,8 @@ public function buildView(FormView $view, FormInterface $form, array $options):
parent::buildView($view, $form, $options);
}
- /**
- * {@inheritdoc}
- */
public function configureOptions(OptionsResolver $resolver): void
{
- $resolver->setDefaults(
- [
- ]
- );
+ $resolver->setDefaults([]);
}
}
diff --git a/bundle/Form/TranslationAddDataTransformer.php b/bundle/Form/TranslationAddDataTransformer.php
index 5cfb0f7..9ecb9ce 100644
--- a/bundle/Form/TranslationAddDataTransformer.php
+++ b/bundle/Form/TranslationAddDataTransformer.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -16,23 +12,14 @@
use EzSystems\EzPlatformAutomatedTranslationBundle\Form\Data\TranslationAddData;
use Symfony\Component\Form\DataTransformerInterface;
-/**
- * Class TranslationAddDataTransformer.
- */
class TranslationAddDataTransformer implements DataTransformerInterface
{
- /**
- * {@inheritdoc}
- */
public function transform($value)
{
/* @var BaseTranslationAddData $value */
return new TranslationAddData($value->getLocation(), $value->getLanguage(), $value->getBaseLanguage());
}
- /**
- * {@inheritdoc}
- */
public function reverseTransform($value)
{
return $value;
diff --git a/bundle/Resources/config/default_settings.yml b/bundle/Resources/config/default_settings.yml
index 9d64eb8..db5ca3b 100644
--- a/bundle/Resources/config/default_settings.yml
+++ b/bundle/Resources/config/default_settings.yml
@@ -1,6 +1,7 @@
parameters:
ez_platform_automated_translation.default.configurations: ~
- ez_platform_automated_translation.default.nontranslatablecharacters: []
- ez_platform_automated_translation.default.nontranslatabletags: []
- ez_platform_automated_translation.default.nonnalidattributetags: []
+ ez_platform_automated_translation.default.non_translatable_characters: []
+ ez_platform_automated_translation.default.non_translatable_tags: []
+ ez_platform_automated_translation.default.non_translatable_self_closed_tags: []
+ ez_platform_automated_translation.default.non_valid_attribute_tags: []
diff --git a/bundle/Resources/config/services.yml b/bundle/Resources/config/services.yml
index d687368..fc57816 100644
--- a/bundle/Resources/config/services.yml
+++ b/bundle/Resources/config/services.yml
@@ -1,12 +1,62 @@
-parameters:
-
services:
_defaults:
autowire: true
+ autoconfigure: true
public: false
- EzSystems\EzPlatformAutomatedTranslation\:
- resource: '../../../lib'
+ _instanceof:
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\FieldEncoderInterface:
+ tags: [ 'ezplatform.automated_translation.field_encoder' ]
+
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\BlockAttribute\BlockAttributeEncoderInterface:
+ tags: [ 'ezplatform.automated_translation.block_attribute_encoder' ]
+
+ # field encoder
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\TextLineFieldEncoder: ~
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\TextBlockFieldEncoder: ~
+
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\PageBuilderFieldEncoder:
+ arguments:
+ $blockAttributeEncoderManager: '@EzSystems\EzPlatformAutomatedTranslation\Encoder\BlockAttribute\BlockAttributeEncoderManager'
+ $blockDefinitionFactory: '@EzSystems\EzPlatformPageFieldType\FieldType\Page\Block\Definition\BlockDefinitionFactory'
+
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\RichTextFieldEncoder:
+ arguments:
+ $richTextEncoder: '@EzSystems\EzPlatformAutomatedTranslation\Encoder\RichText\RichTextEncoder'
+
+ # field encoder manager
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\FieldEncoderManager:
+ arguments:
+ $fieldEncoders: #!tagged_iterator 'ezplatform.automated_translation.field_encoder'
+ - '@EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\TextLineFieldEncoder'
+ - '@EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\TextBlockFieldEncoder'
+ - '@EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\PageBuilderFieldEncoder'
+ - '@EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\RichTextFieldEncoder'
+
+ # block attribute
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\BlockAttribute\TextBlockAttributeEncoder: ~
+
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\BlockAttribute\RichTextBlockAttributeEncoder:
+ arguments:
+ $richTextEncoder: '@EzSystems\EzPlatformAutomatedTranslation\Encoder\RichText\RichTextEncoder'
+
+ # block attribute encoder manager
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\BlockAttribute\BlockAttributeEncoderManager:
+ arguments:
+ $blockAttributeEncoders: #!tagged_iterator 'ezplatform.automated_translation.block_attribute_encoder'
+ - '@EzSystems\EzPlatformAutomatedTranslation\Encoder\BlockAttribute\TextBlockAttributeEncoder'
+ - '@EzSystems\EzPlatformAutomatedTranslation\Encoder\BlockAttribute\RichTextBlockAttributeEncoder'
+
+ # RichText encoder
+ EzSystems\EzPlatformAutomatedTranslation\Encoder\RichText\RichTextEncoder:
+ arguments:
+ $configResolver: '@ezpublish.config.resolver'
+
+ EzSystems\EzPlatformAutomatedTranslation\Encoder: ~
+
+ EzSystems\EzPlatformAutomatedTranslation\Translator: ~
+
+ EzSystems\EzPlatformAutomatedTranslation\TranslatorGuard: ~
EzSystems\EzPlatformAutomatedTranslation\Client\:
resource: '../../../lib/Client'
@@ -17,7 +67,7 @@ services:
EzSystems\EzPlatformAutomatedTranslationBundle\Command\:
resource: '../../Command/*'
- tags: ["console.command"]
+ tags: ['console.command']
EzSystems\EzPlatformAutomatedTranslationBundle\Form\Extension\TranslationAddType:
tags:
@@ -25,11 +75,14 @@ services:
EzSystems\EzPlatformAutomatedTranslationBundle\Form\Extension\ContentEditType:
tags:
+# - { name: form.type_extension, extended_type: EzSystems\EzPlatformContentForms\Form\Type\Content\ContentEditType }
- { name: form.type_extension, extended_type: EzSystems\RepositoryForms\Form\Type\Content\ContentEditType }
-
EzSystems\EzPlatformAutomatedTranslationBundle\Form\Extension\LanguageCreateType:
bind:
- $localeList: %ezpublish.locale.conversion_map%
+ $localeList: '%ezpublish.locale.conversion_map%'
tags:
- { name: form.type_extension, extended_type: EzSystems\EzPlatformAdminUi\Form\Type\Language\LanguageCreateType }
+
+ EzSystems\EzPlatformAutomatedTranslationBundle\EventListener\ContentProxyTranslateListener: ~
+
diff --git a/bundle/Resources/config/services_override.yml b/bundle/Resources/config/services_override.yml
index bdac470..8d3c1a2 100644
--- a/bundle/Resources/config/services_override.yml
+++ b/bundle/Resources/config/services_override.yml
@@ -1,4 +1,12 @@
services:
- EzSystems\EzPlatformAutomatedTranslationBundle\Controller\:
- resource: "../../Controller/*"
- parent: EzSystems\EzPlatformAdminUiBundle\Controller\Controller
+# EzSystems\EzPlatformAutomatedTranslationBundle\Controller\TranslationController:
+# decorates: EzSystems\EzPlatformAdminUiBundle\Controller\TranslationController
+# autoconfigure: true
+# autowire: true
+# tags: ['controller.service_arguments']
+## lazy : true # Segmentation fault (core dumped)
+
+ EzSystems\EzPlatformAutomatedTranslationBundle\Controller\TranslationController:
+ parent: EzSystems\EzPlatformAdminUiBundle\Controller\TranslationController
+ arguments:
+ $translationHelper: '@ezpublish.translation_helper'
diff --git a/bundle/Resources/doc/INSTALL.md b/bundle/Resources/doc/INSTALL.md
index 4b0f315..29b0e0f 100644
--- a/bundle/Resources/doc/INSTALL.md
+++ b/bundle/Resources/doc/INSTALL.md
@@ -9,23 +9,19 @@
Run `composer require ezsystems/ezplatform-automated-translation` to install the bundle and its dependencies:
-### Register the bundle
+### Change bundle's position in the configuration
-Activate the bundle in `app\AppKernel.php` file.
+The new bundle is automatically enabled in the configuration thanks to Flex. Even though, it's important and required to move `EzSystems\EzPlatformAutomatedTranslationBundle\EzPlatformAutomatedTranslationBundle::class => ['all' => true]` before `EzSystems\EzPlatformAdminUiBundle\EzPlatformAdminUiBundle::class => ['all' => true],` due to the templates loading order.
```php
-// app\AppKernel.php
-
-public function registerBundles()
-{
- ...
- $bundles = array(
- new FrameworkBundle(),
- ...
- // eZ Platform Automated Translation Bundle
- new EzSystems\EzPlatformAutomatedTranslationBundle\EzPlatformAutomatedTranslationBundle()
- );
- ...
-}
+ ['all' => true],
+ EzSystems\EzPlatformAdminUiBundle\EzPlatformAdminUiBundle::class => ['all' => true],
+ ...
+];
```
+
diff --git a/bundle/Resources/encore/ez.config.js b/bundle/Resources/encore/ez.config.js
new file mode 100644
index 0000000..d139d39
--- /dev/null
+++ b/bundle/Resources/encore/ez.config.js
@@ -0,0 +1,5 @@
+const path = require('path');
+
+module.exports = (Encore) => {
+ Encore.addEntry('ezplatform-automated-translation-js', [path.resolve(__dirname, '../public/admin/js/ezplatformautomatedtranslation.js')]);
+};
diff --git a/bundle/Resources/public/admin/js/ezplatformautomatedtranslation.js b/bundle/Resources/public/admin/js/ezplatformautomatedtranslation.js
index 45a42f7..f139154 100644
--- a/bundle/Resources/public/admin/js/ezplatformautomatedtranslation.js
+++ b/bundle/Resources/public/admin/js/ezplatformautomatedtranslation.js
@@ -1,4 +1,5 @@
-$(function () {
+jQuery(function () {
+ let $ = jQuery;
let $form = $("form[name=add-translation]", "#add-translation-modal");
let $container = $(".ezautomatedtranslation-services-container:first", $form);
let $error = $(".ezautomatedtranslation-error", $container);
@@ -21,14 +22,19 @@ $(function () {
});
$("form[name=add-translation]").submit(function () {
- let targetLang = $(".ez-translation__label--selected input[id^=add-translation_language]:checked").val();
- let sourceLang = $(".ez-translation__label--selected input[id^=add-translation_base_language]:checked").val();
+ let targetLang = $("select[name=add-translation\\[language\\]]").val();
+ let sourceLang = $("select[name=add-translation\\[base_language\\]]").val();
let mapping = $container.data('languages-mapping');
let $serviceSelector = $("#add-translation_translatorAlias");
let serviceAlias = $serviceSelector.val();
if ($serviceSelector.is("[type=checkbox]") && !$serviceSelector.is(":checked")) {
serviceAlias = '';
}
+
+ if (!serviceAlias.length) {
+ return true;
+ }
+
let translationAvailable = (typeof sourceLang === 'undefined' || -1 !== $.inArray(sourceLang, mapping[serviceAlias])) && (-1 !== $.inArray(targetLang, mapping[serviceAlias]));
if (false === translationAvailable) {
$error.removeClass("invisible");
diff --git a/bundle/Resources/views/ezadminui/javascripts.html.twig b/bundle/Resources/views/ezadminui/javascripts.html.twig
index 1adad6f..757d82c 100644
--- a/bundle/Resources/views/ezadminui/javascripts.html.twig
+++ b/bundle/Resources/views/ezadminui/javascripts.html.twig
@@ -1,3 +1 @@
-{% javascripts 'bundles/ezplatformautomatedtranslation/admin/js/ezplatformautomatedtranslation.js' %}
-
-{% endjavascripts %}
+{{ encore_entry_script_tags('ezplatform-automated-translation-js', null, 'ezplatform') }}
diff --git a/bundle/Resources/views/themes/admin/content/modal/add_translation.html.twig b/bundle/Resources/views/themes/admin/content/modal/add_translation.html.twig
new file mode 100644
index 0000000..cf8d886
--- /dev/null
+++ b/bundle/Resources/views/themes/admin/content/modal/add_translation.html.twig
@@ -0,0 +1,48 @@
+{% trans_default_domain 'locationview' %}
+
+{% form_theme form '@ezdesign/ui/form_fields.html.twig' '@ezdesign/content/translation_add_form_fields.html.twig' %}
+
+
+
+ {% set action = action is defined ? action : path('ezplatform.translation.add') %}
+ {{ form_start(form, {'action': action}) }}
+
+
+
+
{{ 'tab.translations.add.language'|trans|desc('Select a language for the new translation') }}
+ {{ form_widget(form.language, {'attr': {'hidden': 'hidden', 'class': 'ez-translation__language-wrapper ez-translation__language-wrapper--language'}}) }}
+ {% include '@ezdesign/ui/component/custom_dropdown.html.twig' with {
+ choices: form.language.vars.choices,
+ value: form.language.vars.value,
+ source_selector: '.ez-translation__language-wrapper--language',
+ choice_translation_domain: false
+ } %}
+
+
{{ 'tab.translations.add.base_language'|trans|desc('Base this translation on an existing translation') }}
+ {{ form_widget(form.base_language, {'attr': {'hidden': 'hidden', 'class': 'ez-translation__language-wrapper ez-translation__language-wrapper--base-language'}}) }}
+ {% include '@ezdesign/ui/component/custom_dropdown.html.twig' with {
+ choices: form.base_language.vars.choices,
+ value: form.base_language.vars.value,
+ source_selector: '.ez-translation__language-wrapper--base-language',
+ choice_translation_domain: false
+ } %}
+
+ {% include '@ezdesign/content/remote_translate_form_fields.html.twig' %}
+
+
+
+ {{ form_end(form) }}
+
+
diff --git a/bundle/Resources/views/themes/admin/content/remote_translate_form_fields.html.twig b/bundle/Resources/views/themes/admin/content/remote_translate_form_fields.html.twig
new file mode 100644
index 0000000..6faf70a
--- /dev/null
+++ b/bundle/Resources/views/themes/admin/content/remote_translate_form_fields.html.twig
@@ -0,0 +1,35 @@
+{% if form.vars.autotranslated_data is defined %}
+
+ {% if form.translatorAlias.vars.choices is defined %}
+ {# that is a select - then multiple providers #}
+
{{ 'tab.translations.remote.translation.service'|trans()|desc('Use automatic translation') }}
+
+ {{ form_widget(form.translatorAlias) }}
+ {% else %}
+ {# that is a checkbox - then one provider #}
+
{{ 'tab.translations.remote.translation.service.with'|trans({"%alias%":form.translatorAlias.vars.label})|desc('Use automatic translation with %s') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ "Automatic translation is not setup for this language. Please contact the website administrator"|trans()|desc("Automatic translation is not setup for this language") }}
+
+
+
+
+
+ {% do form.translatorAlias.setRendered %}
+ {% endif %}
+
+{% endif %}
diff --git a/composer.json b/composer.json
index 1d5562d..8683a40 100644
--- a/composer.json
+++ b/composer.json
@@ -21,16 +21,18 @@
"GPL-2.0"
],
"require": {
- "php": "^7.1",
- "roave/security-advisories": "dev-master",
+ "php": "^7.2",
"guzzlehttp/guzzle": "^6.3.0",
- "ezsystems/ezpublish-kernel": "^6.0.0|^7.0"
+ "ezsystems/ezpublish-kernel": "^6.0.0|^7.0",
+ "ezsystems/ezplatform-admin-ui": "^1.5.0"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.2",
"phpmd/phpmd": "^2.6",
"friendsofphp/php-cs-fixer": "^2.10",
- "phpunit/phpunit": "^6.4"
+ "phpunit/phpunit": "^8.5",
+ "ezsystems/ezplatform-code-style": "^0.1.0",
+ "dg/bypass-finals": "^1.3"
},
"autoload": {
"psr-4": {
@@ -39,9 +41,15 @@
"EzSystems\\EzPlatformAutomatedTranslationBundle\\Tests\\": "tests"
}
},
+ "autoload-dev": {
+ "psr-4": {
+ "EzSystems\\EzPlatformAutomatedTranslation\\Tests\\": "tests/lib/",
+ "EzSystems\\EzPlatformAutomatedTranslationBundle\\Tests\\": "tests/bundle/"
+ }
+ },
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "2.2.x-dev"
}
}
}
diff --git a/lib/Client/ClientInterface.php b/lib/Client/ClientInterface.php
index d4fde10..9131596 100644
--- a/lib/Client/ClientInterface.php
+++ b/lib/Client/ClientInterface.php
@@ -1,56 +1,31 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\EzPlatformAutomatedTranslation\Client;
-/**
- * Interface ClientInterface.
- */
interface ClientInterface
{
/**
* @param array $configuration
- *
- * @return mixed
*/
public function setConfiguration(array $configuration): void;
- /**
- * @param string $payload
- * @param string $from
- * @param string $to
- *
- * @return string
- */
public function translate(string $payload, ?string $from, string $to): string;
- /**
- * @param string $languageCode
- *
- * @return mixed
- */
- public function supportsLanguage(string $languageCode);
+ public function supportsLanguage(string $languageCode): bool;
/**
* Use as key.
- *
- * @return string
*/
public function getServiceAlias(): string;
/**
* Use for Human.
- *
- * @return string
*/
public function getServiceFullName(): string;
}
diff --git a/lib/Client/Deepl.php b/lib/Client/Deepl.php
index 3acdde3..2a3b155 100644
--- a/lib/Client/Deepl.php
+++ b/lib/Client/Deepl.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -16,35 +12,21 @@
use EzSystems\EzPlatformAutomatedTranslation\Exception\InvalidLanguageCodeException;
use GuzzleHttp\Client;
-/**
- * Class Deepl.
- */
class Deepl implements ClientInterface
{
- /**
- * @var string
- */
+ /** @var string */
private $authKey;
- /**
- * {@inheritdoc}
- */
public function getServiceAlias(): string
{
return 'deepl';
}
- /**
- * {@inheritdoc}
- */
public function getServiceFullName(): string
{
return 'Deepl';
}
- /**
- * {@inheritdoc}
- */
public function setConfiguration(array $configuration): void
{
if (!isset($configuration['authKey'])) {
@@ -53,16 +35,13 @@ public function setConfiguration(array $configuration): void
$this->authKey = $configuration['authKey'];
}
- /**
- * {@inheritdoc}
- */
public function translate(string $payload, ?string $from, string $to): string
{
$parameters = [
- 'auth_key' => $this->authKey,
- 'target_lang' => $this->normalized($to),
+ 'auth_key' => $this->authKey,
+ 'target_lang' => $this->normalized($to),
'tag_handling' => 'xml',
- 'text' => $payload,
+ 'text' => $payload,
];
if (null !== $from) {
@@ -71,10 +50,10 @@ public function translate(string $payload, ?string $from, string $to): string
];
}
- $http = new Client(
+ $http = new Client(
[
'base_uri' => 'https://api.deepl.com',
- 'timeout' => 5.0,
+ 'timeout' => 5.0,
]
);
$response = $http->post('/v1/translate', ['form_params' => $parameters]);
@@ -84,17 +63,11 @@ public function translate(string $payload, ?string $from, string $to): string
return $json->translations[0]->text;
}
- /**
- * {@inheritdoc}
- */
- public function supportsLanguage(string $languageCode)
+ public function supportsLanguage(string $languageCode): bool
{
return \in_array($this->normalized($languageCode), self::LANGUAGE_CODES);
}
- /**
- * {@inheritdoc}
- */
private function normalized(string $languageCode): string
{
if (\in_array($languageCode, self::LANGUAGE_CODES)) {
diff --git a/lib/Client/Google.php b/lib/Client/Google.php
index 8835d68..16c24f5 100644
--- a/lib/Client/Google.php
+++ b/lib/Client/Google.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -15,36 +11,41 @@
use EzSystems\EzPlatformAutomatedTranslation\Exception\ClientNotConfiguredException;
use EzSystems\EzPlatformAutomatedTranslation\Exception\InvalidLanguageCodeException;
use GuzzleHttp\Client;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
/**
* Class GoogleTranslate:.
*/
-class Google implements ClientInterface
+class Google implements ClientInterface, LoggerAwareInterface
{
+ use LoggerAwareTrait;
+
/**
- * @var string
+ * Google List of available code https://cloud.google.com/translate/docs/languages.
*/
+ private const LANGUAGE_CODES = [
+ 'af', 'sq', 'am', 'ar', 'hy', 'az', 'eu', 'be', 'bn', 'bs', 'bg', 'ca', 'co', 'hr', 'ur', 'uz', 'ta', 'tg',
+ 'cs', 'da', 'nl', 'en', 'eo', 'et', 'fi', 'fr', 'fy', 'gl', 'ka', 'de', 'el', 'gu', 'ht', 'ha', 'iw', 'sv',
+ 'hi', 'hu', 'gd', 'sr', 'st', 'ro', 'ru', 'sm', 'pa', 'te', 'th', 'tr', 'uk', 'yi', 'yo', 'zu', 'xh', 'sw',
+ 'is', 'ig', 'id', 'ga', 'it', 'ja', 'jw', 'kn', 'kk', 'km', 'ko', 'ku', 'ky', 'lo', 'la', 'lv', 'lt', 'lb',
+ 'cy', 'mk', 'mg', 'ms', 'ml', 'mt', 'mi', 'mr', 'mn', 'my', 'ne', 'vi', 'sn', 'sd', 'si', 'sk', 'pl', 'pt',
+ 'fa', 'no', 'ny', 'ps', 'sl', 'so', 'es', 'su', 'tl', 'ceb', 'zh-CN', 'zh-TW', 'hmn', 'haw', 'he',
+ ];
+
+ /** @var string */
private $apiKey;
- /**
- * {@inheritdoc}
- */
public function getServiceAlias(): string
{
return 'google';
}
- /**
- * {@inheritdoc}
- */
public function getServiceFullName(): string
{
return 'Google Translate';
}
- /**
- * {@inheritdoc}
- */
public function setConfiguration(array $configuration): void
{
if (!isset($configuration['apiKey'])) {
@@ -53,16 +54,19 @@ public function setConfiguration(array $configuration): void
$this->apiKey = $configuration['apiKey'];
}
- /**
- * {@inheritdoc}
- */
public function translate(string $payload, ?string $from, string $to): string
{
+ $this->logger->info(sprintf(
+ 'Calling %s for translated content (length %s)',
+ $this->getServiceFullName(),
+ strlen($payload)
+ ));
+
$parameters = [
- 'key' => $this->apiKey,
+ 'key' => $this->apiKey,
'target' => $this->normalized($to),
'format' => 'html',
- 'q' => $payload,
+ 'q' => $payload,
];
if (null !== $from) {
@@ -71,31 +75,30 @@ public function translate(string $payload, ?string $from, string $to): string
];
}
- $http = new Client(
+ $http = new Client(
[
'base_uri' => 'https://translation.googleapis.com/',
- 'timeout' => 2.0,
+ 'timeout' => 10.0,
]
);
$response = $http->post('/language/translate/v2', ['form_params' => $parameters]);
- $json = json_decode($response->getBody()->getContents());
+ $json = json_decode($response->getBody()->getContents());
+ $translatedText = $json->data->translations[0]->translatedText;
+
+ $this->logger->info(sprintf(
+ '%s has returned translated content (length %s)',
+ $this->getServiceFullName(),
+ strlen($translatedText)
+ ));
- return $json->data->translations[0]->translatedText;
+ return $translatedText;
}
- /**
- * {@inheritdoc}
- */
- public function supportsLanguage(string $languageCode)
+ public function supportsLanguage(string $languageCode): bool
{
return \in_array($this->normalized($languageCode), self::LANGUAGE_CODES);
}
- /**
- * @param string $languageCode
- *
- * @return string
- */
private function normalized(string $languageCode): string
{
if (\in_array($languageCode, self::LANGUAGE_CODES)) {
@@ -113,16 +116,4 @@ private function normalized(string $languageCode): string
}
throw new InvalidLanguageCodeException($languageCode, $this->getServiceAlias());
}
-
- /**
- * Google List of available code https://cloud.google.com/translate/docs/languages.
- */
- private const LANGUAGE_CODES = [
- 'af', 'sq', 'am', 'ar', 'hy', 'az', 'eu', 'be', 'bn', 'bs', 'bg', 'ca', 'co', 'hr', 'ur', 'uz', 'ta', 'tg',
- 'cs', 'da', 'nl', 'en', 'eo', 'et', 'fi', 'fr', 'fy', 'gl', 'ka', 'de', 'el', 'gu', 'ht', 'ha', 'iw', 'sv',
- 'hi', 'hu', 'gd', 'sr', 'st', 'ro', 'ru', 'sm', 'pa', 'te', 'th', 'tr', 'uk', 'yi', 'yo', 'zu', 'xh', 'sw',
- 'is', 'ig', 'id', 'ga', 'it', 'ja', 'jw', 'kn', 'kk', 'km', 'ko', 'ku', 'ky', 'lo', 'la', 'lv', 'lt', 'lb',
- 'cy', 'mk', 'mg', 'ms', 'ml', 'mt', 'mi', 'mr', 'mn', 'my', 'ne', 'vi', 'sn', 'sd', 'si', 'sk', 'pl', 'pt',
- 'fa', 'no', 'ny', 'ps', 'sl', 'so', 'es', 'su', 'tl', 'ceb', 'zh-CN', 'zh-TW', 'hmn', 'haw',
- ];
}
diff --git a/lib/ClientProvider.php b/lib/ClientProvider.php
index 8aa4497..82a0afe 100644
--- a/lib/ClientProvider.php
+++ b/lib/ClientProvider.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -15,27 +11,14 @@
use eZ\Publish\Core\MVC\ConfigResolverInterface;
use EzSystems\EzPlatformAutomatedTranslation\Client\ClientInterface;
-/**
- * Class ClientProvider.
- */
class ClientProvider
{
- /**
- * @var ClientInterface[]
- */
+ /** @var ClientInterface[] */
private $clients;
- /**
- * @var ConfigResolverInterface
- */
+ /** @var ConfigResolverInterface */
private $configResolver;
- /**
- * ClientProvider constructor.
- *
- * @param ConfigResolverInterface $configResolver
- * @param iterable $clients
- */
public function __construct(iterable $clients, ConfigResolverInterface $configResolver)
{
$this->configResolver = $configResolver;
@@ -54,8 +37,8 @@ public function __construct(iterable $clients, ConfigResolverInterface $configRe
private function addClient(ClientInterface $client): self
{
$configurations = $this->configResolver->getParameter('configurations', 'ez_platform_automated_translation');
- $reflection = new \ReflectionClass($client);
- $key = strtolower($reflection->getShortName());
+ $reflection = new \ReflectionClass($client);
+ $key = strtolower($reflection->getShortName());
if (isset($configurations[$key])) {
$client->setConfiguration($configurations[$key]);
$this->clients[$key] = $client;
diff --git a/lib/Encoder.php b/lib/Encoder.php
index 6c43d38..b9c6de2 100644
--- a/lib/Encoder.php
+++ b/lib/Encoder.php
@@ -1,22 +1,24 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\EzPlatformAutomatedTranslation;
-use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ConfigResolver;
use eZ\Publish\API\Repository\ContentTypeService;
use eZ\Publish\API\Repository\Values\Content\Content;
-use eZ\Publish\Core\FieldType\RichText\Value as RichTextValue;
-use eZ\Publish\Core\FieldType\TextLine\Value as TextLineValue;
+use eZ\Publish\API\Repository\Values\Content\Field;
+use eZ\Publish\Core\FieldType\Value;
+use eZ\Publish\SPI\FieldType\Value as SPIValue;
+use EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\FieldEncoderManager;
+use EzSystems\EzPlatformAutomatedTranslation\Exception\EmptyTranslatedFieldException;
+use EzSystems\EzPlatformAutomatedTranslationBundle\Event\FieldDecodeEvent;
+use EzSystems\EzPlatformAutomatedTranslationBundle\Event\FieldEncodeEvent;
+use EzSystems\EzPlatformAutomatedTranslationBundle\Events;
+use InvalidArgumentException;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
/**
@@ -70,214 +72,114 @@ class Encoder
private const XML_MARKUP = '';
- /**
- * Allow to replace characters preserve eZ RichText Content.
- *
- * @var array
- */
- private $nonTranslatableCharactersHashMap;
-
- /**
- * Everything inside these tags must be preserve from translation.
- *
- * @var array
- */
- private $nonTranslatableTags;
-
- /**
- * Every attributes inside these tags must be preserve from translation.
- *
- * @var array
- */
- private $nonValidAttributeTags;
-
- /**
- * @var ContentTypeService
- */
+ /** @var ContentTypeService */
private $contentTypeService;
- /**
- * @var array
- */
- private $placeHolderMap;
+ /** @var \EzSystems\EzPlatformAutomatedTranslation\Encoder\Field\FieldEncoderManager */
+ private $fieldEncoderManager;
- /**
- * Encoder constructor.
- *
- * @param ContentTypeService $contentTypeService
- * @param ConfigResolver $configResolver
- */
- public function __construct(ContentTypeService $contentTypeService, ConfigResolver $configResolver)
- {
+ public function __construct(
+ ContentTypeService $contentTypeService,
+ FieldEncoderManager $fieldEncoderManager
+ ) {
$this->contentTypeService = $contentTypeService;
- $this->placeHolderMap = [];
- $tags = $configResolver->getParameter(
- 'nontranslatabletags',
- 'ez_platform_automated_translation'
- );
- $chars = $configResolver->getParameter(
- 'nontranslatablecharacters',
- 'ez_platform_automated_translation'
- );
-
- $attributes = $configResolver->getParameter(
- 'nonnalidattributetags',
- 'ez_platform_automated_translation'
- );
-
- $this->nonTranslatableTags = ['ezembed'] + $tags;
- $this->nonTranslatableCharactersHashMap = ["\n" => 'XXXEOLXXX'] + $chars;
- $this->nonValidAttributeTags = ['title'] + $attributes;
+ $this->fieldEncoderManager = $fieldEncoderManager;
}
- /**
- * @param Content $content
- *
- * @return string
- */
public function encode(Content $content): string
{
- $results = [];
+ $results = [];
$contentType = $this->contentTypeService->loadContentType($content->contentInfo->contentTypeId);
foreach ($content->getFields() as $field) {
- $identifier = $field->fieldDefIdentifier;
+ $identifier = $field->fieldDefIdentifier;
$fieldDefinition = $contentType->getFieldDefinition($identifier);
if (!$fieldDefinition->isTranslatable) {
continue;
}
$type = \get_class($field->value);
- // Note that TextBlock is a TextLine
- if ($field->value instanceof TextLineValue) {
- $value = (string) $field->value;
- $results[$identifier] = ['#' => $value, '@type' => $type];
+
+ if (null === ($value = $this->encodeField($field))) {
continue;
}
- if ($field->value instanceof RichTextValue) {
- // we need to remove that to make it a good XML
- $value = $this->richTextEncode($field->value);
- $results[$identifier] = ['#' => $value, '@type' => $type];
- }
+
+ $results[$identifier] = [
+ '#' => $value,
+ '@type' => $type,
+ ];
}
$encoder = new XmlEncoder();
$payload = $encoder->encode($results, XmlEncoder::FORMAT);
+
+// dump($payload);
+
// here Encoder has decorated with CDATA, we don't want the CDATA
- $payload = str_replace(
+ return str_replace(
[''],
['<' . self::CDATA_FAKER_TAG . '>', '' . self::CDATA_FAKER_TAG . '>'],
$payload
);
-
- return $payload;
}
- /**
- * @param string $xml
- *
- * @return array
- */
- public function decode(string $xml): array
+ public function decode(string $xml, Content $sourceContent): array
{
- $encoder = new XmlEncoder();
- $data = str_replace(
+ $encoder = new XmlEncoder();
+ $data = str_replace(
['<' . self::CDATA_FAKER_TAG . '>', '' . self::CDATA_FAKER_TAG . '>'],
[''],
$xml
);
+
$decodeArray = $encoder->decode($data, XmlEncoder::FORMAT);
- $results = [];
+ $results = [];
foreach ($decodeArray as $fieldIdentifier => $xmlValue) {
- $type = $xmlValue['@type'];
- $value = $xmlValue['#'];
- if (RichTextValue::class === $type) {
- $value = $this->richTextDecode($value);
- }
- $trimmedValue = trim($value);
- if ('' === $trimmedValue) {
+ $previousFieldValue = $sourceContent->getField($fieldIdentifier)->value;
+ $type = $xmlValue['@type'];
+ $stringValue = $xmlValue['#'];
+ $fieldValue = $this->decodeField($type, $stringValue, $previousFieldValue);
+
+ if (null === $fieldValue) {
+ // TODO $this->logger
continue;
}
- $results[$fieldIdentifier] = new $type($trimmedValue);
+
+ if (!in_array(SPIValue::class, class_implements($type))) {
+ throw new InvalidArgumentException(sprintf(
+ 'Unable to instantiate class %s, it should implement %s', $type, SPIValue::class
+ ));
+ }
+
+ if (get_class($fieldValue) !== $type) {
+ throw new InvalidArgumentException(sprintf(
+ 'Decoded field class mismatch: expected %s, actual: %s', $type, get_class($fieldValue)
+ ));
+ }
+
+ $results[$fieldIdentifier] = $fieldValue;
}
return $results;
}
- /**
- * @param RichTextValue $value
- *
- * @return string
- */
- public function richTextEncode(RichTextValue $value): string
+ private function encodeField(Field $field): ?string
{
- $xmlString = (string) $value;
- $xmlString = substr($xmlString, strpos($xmlString, '>') + 1);
- $xmlString = str_replace(
- array_keys($this->nonTranslatableCharactersHashMap),
- array_values($this->nonTranslatableCharactersHashMap),
- $xmlString
- );
-
- foreach ($this->nonTranslatableTags as $tag) {
- $xmlString = preg_replace_callback(
- '#<' . $tag . '(.[^>]*)>(.*)' . $tag . '>#uim',
- function ($matches) use ($tag) {
- $hash = sha1($matches[0]);
- $this->placeHolderMap[$hash] = $matches[0];
-
- return "<{$tag}>{$hash}{$tag}>";
- },
- $xmlString
- );
+ try {
+ return $this->fieldEncoderManager->encode($field);
+ } catch (InvalidArgumentException $e) {
+ return null;
}
- foreach ($this->nonValidAttributeTags as $tag) {
- $xmlString = preg_replace_callback(
- '#<' . $tag . '(.[^>]*)>#uim',
- function ($matches) use ($tag) {
- $hash = sha1($matches[0]);
- $this->placeHolderMap[$hash] = $matches[0];
-
- return "";
- },
- $xmlString
- );
- $xmlString = str_replace("{$tag}>", " ", $xmlString);
- }
-
- return $xmlString;
}
/**
- * @param string $value
- *
- * @return string
+ * @param mixed $previousFieldValue
*/
- public function richTextDecode(string $value): string
+ private function decodeField(string $type, string $value, $previousFieldValue): ?Value
{
- $value = str_replace(
- array_values($this->nonTranslatableCharactersHashMap),
- array_keys($this->nonTranslatableCharactersHashMap),
- $value
- );
- foreach ($this->nonTranslatableTags as $tag) {
- $value = preg_replace_callback(
- '#<' . $tag . '>(.*)' . $tag . '>#uim',
- function ($matches) {
- return $this->placeHolderMap[trim($matches[1])];
- },
- $value
- );
- }
- foreach ($this->nonValidAttributeTags as $tag) {
- $value = preg_replace_callback(
- '#]*)>#uim',
- function ($matches) {
- return $this->placeHolderMap[trim($matches[1])];
- },
- $value
- );
- $value = str_replace(" ", "{$tag}>", $value);
+ try {
+ return $this->fieldEncoderManager->decode($type, $value, $previousFieldValue);
+ } catch (InvalidArgumentException | EmptyTranslatedFieldException $e) {
+ // TODO dump($e->getMessage());
+ return null;
}
-
- return $value;
}
}
diff --git a/lib/Encoder/BlockAttribute/BlockAttributeEncoderInterface.php b/lib/Encoder/BlockAttribute/BlockAttributeEncoderInterface.php
new file mode 100644
index 0000000..1bb67e2
--- /dev/null
+++ b/lib/Encoder/BlockAttribute/BlockAttributeEncoderInterface.php
@@ -0,0 +1,23 @@
+blockAttributeEncoders = $blockAttributeEncoders;
+ }
+
+ /**
+ * @param mixed $value
+ */
+ public function encode(string $type, $value): string
+ {
+ foreach ($this->blockAttributeEncoders as $blockAttributeEncoder) {
+ if ($blockAttributeEncoder->canEncode($type)) {
+ return $blockAttributeEncoder->encode($value);
+ }
+ }
+
+ throw new InvalidArgumentException(
+ sprintf(
+ 'Unable to encode block attribute %s. Make sure block attribute encoder service for it is properly registered.',
+ $type
+ )
+ );
+ }
+
+ /**
+ * @throws \EzSystems\EzPlatformAutomatedTranslation\Exception\EmptyTranslatedAttributeException
+ */
+ public function decode(string $type, string $value): string
+ {
+ foreach ($this->blockAttributeEncoders as $blockAttributeEncoder) {
+ if ($blockAttributeEncoder->canDecode($type)) {
+ return $blockAttributeEncoder->decode($value);
+ }
+ }
+
+ throw new InvalidArgumentException(
+ sprintf(
+ 'Unable to decode block attribute %s. Make sure block attribute encoder service for it is properly registered.',
+ $type
+ )
+ );
+ }
+}
diff --git a/lib/Encoder/BlockAttribute/RichTextBlockAttributeEncoder.php b/lib/Encoder/BlockAttribute/RichTextBlockAttributeEncoder.php
new file mode 100644
index 0000000..42e220b
--- /dev/null
+++ b/lib/Encoder/BlockAttribute/RichTextBlockAttributeEncoder.php
@@ -0,0 +1,52 @@
+richTextEncoder = $richTextEncoder;
+ }
+
+ public function canEncode(string $type): bool
+ {
+ return $type === self::TYPE;
+ }
+
+ public function canDecode(string $type): bool
+ {
+ return $type === self::TYPE;
+ }
+
+ public function encode($value): string
+ {
+ return $this->richTextEncoder->encode((string) $value);
+ }
+
+ public function decode(string $value): string
+ {
+ $decodedValue = $this->richTextEncoder->decode($value);
+
+ if (strlen($decodedValue) === 0) {
+ throw new EmptyTranslatedAttributeException();
+ }
+
+ return $decodedValue;
+ }
+}
diff --git a/lib/Encoder/BlockAttribute/TextBlockAttributeEncoder.php b/lib/Encoder/BlockAttribute/TextBlockAttributeEncoder.php
new file mode 100644
index 0000000..2f30d39
--- /dev/null
+++ b/lib/Encoder/BlockAttribute/TextBlockAttributeEncoder.php
@@ -0,0 +1,34 @@
+fieldEncoders = $fieldEncoders;
+ }
+
+ public function encode(Field $field): string
+ {
+ foreach ($this->fieldEncoders as $fieldEncoder) {
+ if ($fieldEncoder->canEncode($field)) {
+ return $fieldEncoder->encode($field);
+ }
+ }
+
+ throw new InvalidArgumentException(
+ sprintf(
+ 'Unable to encode field %s. Make sure field encoder service for it is properly registered.',
+ get_class($field)
+ )
+ );
+ }
+
+ /**
+ * @param mixed $previousFieldValue
+ *
+ * @throws \InvalidArgumentException
+ * @throws \EzSystems\EzPlatformAutomatedTranslation\Exception\EmptyTranslatedFieldException
+ */
+ public function decode(string $type, string $value, $previousFieldValue): Value
+ {
+ foreach ($this->fieldEncoders as $fieldEncoder) {
+ if ($fieldEncoder->canDecode($type)) {
+ return $fieldEncoder->decode($value, $previousFieldValue);
+ }
+ }
+
+ throw new InvalidArgumentException(
+ sprintf(
+ 'Unable to decode field %s. Make sure field encoder service for it is properly registered.',
+ $type
+ )
+ );
+ }
+}
diff --git a/lib/Encoder/Field/PageBuilderFieldEncoder.php b/lib/Encoder/Field/PageBuilderFieldEncoder.php
new file mode 100644
index 0000000..4ebecad
--- /dev/null
+++ b/lib/Encoder/Field/PageBuilderFieldEncoder.php
@@ -0,0 +1,173 @@
+';
+
+ /** @var \EzSystems\EzPlatformAutomatedTranslation\Encoder\BlockAttribute\BlockAttributeEncoderManager */
+ private $blockAttributeEncoderManager;
+
+ /** @var \EzSystems\EzPlatformPageFieldType\FieldType\Page\Block\Definition\BlockDefinitionFactory */
+ private $blockDefinitionFactory;
+
+ public function __construct(
+ BlockAttributeEncoderManager $blockAttributeEncoderManager,
+ BlockDefinitionFactory $blockDefinitionFactory
+ ) {
+ $this->blockAttributeEncoderManager = $blockAttributeEncoderManager;
+ $this->blockDefinitionFactory = $blockDefinitionFactory;
+ }
+
+ public function canEncode(Field $field): bool
+ {
+ return class_exists(Value::class) && $field->value instanceof Value;
+ }
+
+ public function canDecode(string $type): bool
+ {
+ return class_exists(Value::class) && Value::class === $type;
+ }
+
+ public function encode(Field $field): string
+ {
+ /** @var Value $value */
+ $value = $field->value;
+ $page = $value->getPage();
+ $blocks = [];
+
+ foreach ($this->getBlockIterator($page) as $block) {
+ $blockDefinition = $this->blockDefinitionFactory->getBlockDefinition($block->getType());
+ $attrs = [];
+
+ foreach ($block->getAttributes() as $attribute) {
+ $attributeType = $blockDefinition->getAttributes()[$attribute->getName()]->getType();
+
+ if (null === ($attributeValue = $this->encodeBlockAttribute($attributeType, $attribute->getValue()))) {
+ continue;
+ }
+
+ $attrs[$attribute->getName()] = [
+ '@type' => $attributeType,
+ '#' => $attributeValue,
+ ];
+ }
+
+ $blocks[$block->getId()] = [
+ 'name' => $block->getName(),
+ 'attributes' => $attrs,
+ ];
+ }
+
+ $encoder = new XmlEncoder();
+ $payload = $encoder->encode($blocks, XmlEncoder::FORMAT, [
+ /*XmlEncoder::ROOT_NODE_NAME*/ 'xml_root_node_name' => 'blocks',
+ ]);
+
+// dump($payload);
+// die(__METHOD__);
+
+ $payload = str_replace('' . "\n", '', $payload);
+
+ $payload = str_replace(
+ [''],
+ ['<' . self::CDATA_FAKER_TAG . '>', '' . self::CDATA_FAKER_TAG . '>'],
+ $payload
+ );
+
+// dump($payload);
+// die(__METHOD__);
+ return (string) $payload;
+ }
+
+ public function decode(string $value, $previousFieldValue): APIValue
+ {
+ $encoder = new XmlEncoder();
+ $data = str_replace(
+ ['<' . self::CDATA_FAKER_TAG . '>', '' . self::CDATA_FAKER_TAG . '>'],
+ [''],
+ $value
+ );
+
+ /** @var Value $previousFieldValue */
+ $page = clone $previousFieldValue->getPage();
+ $decodeArray = $encoder->decode($data, XmlEncoder::FORMAT);
+
+// dump($decodeArray);
+
+ foreach ($decodeArray as $blockId => $xmlValue) {
+ $block = $page->getBlockById((string) $blockId);
+ $block->setName($xmlValue['name']);
+
+ if (is_array($xmlValue['attributes'])) {
+ foreach ($xmlValue['attributes'] as $attributeName => $attribute) {
+ if (null === ($attributeValue = $this->decodeBlockAttribute($attribute['@type'], $attribute['#']))) {
+ continue;
+ }
+
+ $block->getAttribute($attributeName)->setValue($attributeValue);
+ }
+ }
+ }
+
+// dump($page);
+// die(__METHOD__);
+ return new Value($page);
+ }
+
+ /**
+ * @param mixed $value
+ */
+ private function encodeBlockAttribute(string $type, $value): ?string
+ {
+ try {
+ $value = $this->blockAttributeEncoderManager->encode($type, $value);
+ } catch (InvalidArgumentException $e) {
+ return null;
+ }
+
+ return $value;
+ }
+
+ private function decodeBlockAttribute(string $type, string $value): ?string
+ {
+ try {
+ $value = $this->blockAttributeEncoderManager->decode($type, $value);
+ } catch (InvalidArgumentException | EmptyTranslatedAttributeException $e) {
+ return null;
+ }
+
+ return $value;
+ }
+
+ public function getBlockIterator(?Page $page) {
+ $blocks = [];
+ if ($page) {
+ foreach ($page->getZones() as $zone) {
+ foreach ($zone->getBlocks() as $block) {
+ $blocks[] = $block;
+ }
+ }
+ }
+ return $blocks;
+ }
+}
diff --git a/lib/Encoder/Field/RichTextFieldEncoder.php b/lib/Encoder/Field/RichTextFieldEncoder.php
new file mode 100644
index 0000000..8be2da3
--- /dev/null
+++ b/lib/Encoder/Field/RichTextFieldEncoder.php
@@ -0,0 +1,52 @@
+richTextEncoder = $richTextEncoder;
+ }
+
+ public function canEncode($field): bool
+ {
+ return $field->value instanceof RichTextValue;
+ }
+
+ public function canDecode(string $type): bool
+ {
+ return RichTextValue::class === $type;
+ }
+
+ public function encode($field): string
+ {
+ return $this->richTextEncoder->encode((string) $field->value);
+ }
+
+ public function decode(string $value, $previousFieldValue): Value
+ {
+ $decodedValue = $this->richTextEncoder->decode($value);
+
+ if (strlen($decodedValue) === 0) {
+ throw new EmptyTranslatedFieldException();
+ }
+
+ return new RichTextValue($decodedValue);
+ }
+}
diff --git a/lib/Encoder/Field/TextBlockFieldEncoder.php b/lib/Encoder/Field/TextBlockFieldEncoder.php
new file mode 100644
index 0000000..385a0b5
--- /dev/null
+++ b/lib/Encoder/Field/TextBlockFieldEncoder.php
@@ -0,0 +1,62 @@
+value instanceof TextBlockValue;
+ }
+
+ public function canDecode(string $type): bool
+ {
+ return TextBlockValue::class === $type;
+ }
+
+ public function encode(Field $field): string
+ {
+ return (string) $field->value;
+ }
+
+ public function decode(string $value, $previousFieldValue): Value
+ {
+ $value = trim($value);
+
+ if (strlen($value) === 0) {
+ throw new EmptyTranslatedFieldException();
+ }
+
+ // If string contains '&'
+ // "Aide & procédures"
+ // it will be warp with CDATA
+ // ''
+ // CDATA will be transform to
+ // Aides & démarches
+ // After translation
+ // Aids & Procedures
+ // Then will be replace by 'Aids & Procedures]]>
+ // So we need to remove XML_MARKUP and replace '&' by '&'
+ // TODO This is not the good solution...
+ $value = str_replace([
+ '',
+ '&',
+ ], [
+ '', '&'
+ ], $value);
+
+ return new TextBlockValue($value);
+ }
+}
diff --git a/lib/Encoder/Field/TextLineFieldEncoder.php b/lib/Encoder/Field/TextLineFieldEncoder.php
new file mode 100644
index 0000000..68f6dc2
--- /dev/null
+++ b/lib/Encoder/Field/TextLineFieldEncoder.php
@@ -0,0 +1,62 @@
+value instanceof TextLineValue;
+ }
+
+ public function canDecode(string $type): bool
+ {
+ return TextLineValue::class === $type;
+ }
+
+ public function encode(Field $field): string
+ {
+ return (string) $field->value;
+ }
+
+ public function decode(string $value, $previousFieldValue): Value
+ {
+ $value = trim($value);
+
+ if (strlen($value) === 0) {
+ throw new EmptyTranslatedFieldException();
+ }
+
+ // If string contains '&'
+ // "Aide & procédures"
+ // it will be warp with CDATA
+ // ''
+ // CDATA will be transform to
+ // Aides & démarches
+ // After translation
+ // Aids & Procedures
+ // Then will be replace by 'Aids & Procedures]]>
+ // So we need to remove XML_MARKUP and replace '&' by '&'
+ // TODO This is not the good solution...
+ $value = str_replace([
+ '',
+ '&',
+ ], [
+ '', '&'
+ ], $value);
+
+ return new TextLineValue($value);
+ }
+}
diff --git a/lib/Encoder/RichText/RichTextEncoder.php b/lib/Encoder/RichText/RichTextEncoder.php
new file mode 100644
index 0000000..a2d9ae8
--- /dev/null
+++ b/lib/Encoder/RichText/RichTextEncoder.php
@@ -0,0 +1,210 @@
+';
+
+ /**
+ * Allow to replace characters preserve eZ RichText Content.
+ *
+ * @var array
+ */
+ private $nonTranslatableCharactersHashMap;
+
+ /**
+ * Everything inside these tags must be preserve from translation.
+ *
+ * @var array
+ */
+ private $nonTranslatableTags;
+
+ /**
+ * Everything inside these self-closing tags must be preserve from translation.
+ *
+ * @var array
+ */
+ private $nonTranslatableSelfClosingTags;
+
+ /**
+ * Every attributes inside these tags must be preserve from translation.
+ *
+ * @var array
+ */
+ private $nonValidAttributeTags;
+
+ /** @var array */
+ private $placeHolderMap;
+
+ public function __construct(
+ ConfigResolverInterface $configResolver
+ ) {
+ $tags = $configResolver->getParameter(
+ 'non_translatable_tags',
+ 'ez_platform_automated_translation'
+ );
+
+ $selfClosedTags = $configResolver->getParameter(
+ 'non_translatable_self_closed_tags',
+ 'ez_platform_automated_translation'
+ );
+
+ $chars = $configResolver->getParameter(
+ 'non_translatable_characters',
+ 'ez_platform_automated_translation'
+ );
+
+ $attributes = $configResolver->getParameter(
+ 'non_valid_attribute_tags',
+ 'ez_platform_automated_translation'
+ );
+
+ $this->nonTranslatableTags = ['ezvalue', 'ezconfig', 'ezembed'] + $tags;
+ $this->nonTranslatableSelfClosingTags = ['ezembedinline'] + $selfClosedTags;
+ $this->nonTranslatableCharactersHashMap = [
+ "\n" => ' ',
+ '' => '',
+ ] + $chars;
+ $this->nonValidAttributeTags = ['title'] + $attributes;
+ $this->placeHolderMap = [];
+ }
+
+ public function encode(string $xmlString): string
+ {
+ if (strpos($xmlString, self::XML_MARKUP . "\n") !== false) {
+ $xmlString = substr($xmlString, strlen(self::XML_MARKUP . "\n"));
+ }
+
+ $xmlString = $this->encodeNonTranslatableCharacters($xmlString);
+
+ foreach ($this->nonTranslatableSelfClosingTags as $tag) {
+ $xmlString = preg_replace_callback(
+ '#<' . $tag . '(.[^>]*)?/>#Uuim',
+ function ($matches) use ($tag) {
+ $hash = $this->hash($matches[0]);
+ $this->placeHolderMap[$hash] = $matches[0];
+
+ return "<{$tag}>{$hash}{$tag}>";
+ },
+ $xmlString
+ );
+ }
+
+ foreach ($this->nonTranslatableTags as $tag) {
+ $xmlString = preg_replace_callback(
+ '#<' . $tag . '(>| (.[^>]*)?>)((?:.|\n)*)' . $tag . '>#Uuim',
+ function ($matches) use ($tag) {
+ $hash = $this->hash($matches[0]);
+ $this->placeHolderMap[$hash] = $matches[0];
+
+ return "<{$tag}>{$hash}{$tag}>";
+ },
+ $xmlString
+ );
+ }
+
+ foreach ($this->nonValidAttributeTags as $tag) {
+ $xmlString = preg_replace_callback(
+ '#<' . $tag . '(.[^>]*)>#Uuim',
+ function ($matches) use ($tag) {
+ $hash = $this->hash($matches[0]);
+ $this->placeHolderMap[$hash] = $matches[0];
+
+ return "";
+ },
+ $xmlString
+ );
+ $xmlString = str_replace("{$tag}>", " ", $xmlString);
+ }
+
+ $xmlString = str_replace(
+ [''],
+ ['<' . self::CDATA_FAKER_TAG . '>', '' . self::CDATA_FAKER_TAG . '>'],
+ $xmlString
+ );
+
+ return $xmlString;
+ }
+
+ public function decode(string $value): string
+ {
+ $value = str_replace(
+ ['<' . self::CDATA_FAKER_TAG . '>', '' . self::CDATA_FAKER_TAG . '>'],
+ [''],
+ $value
+ );
+
+ $value = $this->decodeNonTranslatableCharacters($value);
+
+ foreach (array_reverse($this->nonTranslatableSelfClosingTags) as $tag) {
+ $value = preg_replace_callback(
+ '#<' . $tag . '>(.*)' . $tag . '>#Uuim',
+ function ($matches) {
+ return $this->placeHolderMap[trim($matches[1])];
+ },
+ $value
+ );
+ }
+
+ foreach (array_reverse($this->nonTranslatableTags) as $tag) {
+ $value = preg_replace_callback(
+ '#<' . $tag . '>(.*)' . $tag . '>#Uuim',
+ function ($matches) {
+ return $this->placeHolderMap[trim($matches[1])];
+ },
+ $value
+ );
+ }
+
+ foreach ($this->nonValidAttributeTags as $tag) {
+ $value = preg_replace_callback(
+ '#]*)>#Uuim',
+ function ($matches) {
+ return $this->placeHolderMap[trim(str_replace('="1"', '', $matches[1]))];
+ },
+ $value
+ );
+ $value = str_replace(" ", "{$tag}>", $value);
+ }
+
+ return $this->decodeNonTranslatableCharacters($value);
+ }
+
+ private function hash(string $data): string
+ {
+ return 'H' . substr(md5($data), 0, 8);
+ }
+
+ private function encodeNonTranslatableCharacters(string $value): string
+ {
+ return str_replace(
+ array_keys($this->nonTranslatableCharactersHashMap),
+ array_values($this->nonTranslatableCharactersHashMap),
+ $value
+ );
+ }
+
+ private function decodeNonTranslatableCharacters(string $value): string
+ {
+ return str_replace(
+ array_values($this->nonTranslatableCharactersHashMap),
+ array_keys($this->nonTranslatableCharactersHashMap),
+ $value
+ );
+ }
+}
diff --git a/lib/Exception/ClientNotConfiguredException.php b/lib/Exception/ClientNotConfiguredException.php
index 5810bc3..3160ed9 100644
--- a/lib/Exception/ClientNotConfiguredException.php
+++ b/lib/Exception/ClientNotConfiguredException.php
@@ -1,12 +1,8 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -14,9 +10,6 @@
use RuntimeException;
-/**
- * Class ClientNotConfiguredException.
- */
class ClientNotConfiguredException extends RuntimeException
{
}
diff --git a/lib/Exception/EmptyTranslatedAttributeException.php b/lib/Exception/EmptyTranslatedAttributeException.php
new file mode 100644
index 0000000..09fbc7a
--- /dev/null
+++ b/lib/Exception/EmptyTranslatedAttributeException.php
@@ -0,0 +1,15 @@
+
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
@@ -14,17 +10,8 @@
use InvalidArgumentException;
-/**
- * Class InvalidLanguageCodeException.
- */
class InvalidLanguageCodeException extends InvalidArgumentException
{
- /**
- * InvalidLanguageCodeException constructor.
- *
- * @param string $languageCode
- * @param string $driver
- */
public function __construct(string $languageCode, string $driver)
{
parent::__construct("$languageCode not recognized by $driver");
diff --git a/lib/Translator.php b/lib/Translator.php
index 5d7e4cb..5e1748e 100644
--- a/lib/Translator.php
+++ b/lib/Translator.php
@@ -1,76 +1,55 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\EzPlatformAutomatedTranslation;
+use eZ\Publish\API\Repository\ContentService;
+use eZ\Publish\API\Repository\ContentTypeService;
use eZ\Publish\API\Repository\Values\Content\Content;
use eZ\Publish\API\Repository\Values\ContentType\FieldDefinition;
use eZ\Publish\Core\MVC\Symfony\Locale\LocaleConverterInterface;
-/**
- * Class Translator.
- */
class Translator
{
- use RepositoryAware;
-
- /**
- * @var TranslatorGuard
- */
+ /** @var TranslatorGuard */
private $guard;
- /**
- * @var LocaleConverterInterface
- */
+ /** @var LocaleConverterInterface */
private $localeConverter;
- /**
- * @var ClientProvider
- */
+ /** @var ClientProvider */
private $clientProvider;
- /**
- * @var Encoder
- */
+ /** @var Encoder */
private $encoder;
- /**
- * Translator constructor.
- *
- * @param TranslatorGuard $guard
- * @param LocaleConverterInterface $localeConverter
- * @param ClientProvider $clientProvider
- * @param Encoder $encoder
- */
+ /** @var \eZ\Publish\API\Repository\ContentService */
+ private $contentService;
+
+ /** @var \eZ\Publish\API\Repository\ContentTypeService */
+ private $contentTypeService;
+
public function __construct(
TranslatorGuard $guard,
LocaleConverterInterface $localeConverter,
ClientProvider $clientProvider,
- Encoder $encoder
+ Encoder $encoder,
+ ContentService $contentService,
+ ContentTypeService $contentTypeService
) {
- $this->guard = $guard;
+ $this->guard = $guard;
$this->localeConverter = $localeConverter;
- $this->clientProvider = $clientProvider;
- $this->encoder = $encoder;
+ $this->clientProvider = $clientProvider;
+ $this->encoder = $encoder;
+ $this->contentService = $contentService;
+ $this->contentTypeService = $contentTypeService;
}
- /**
- * @param string $from
- * @param string $to
- * @param string $remoteServiceKey
- * @param Content $content
- *
- * @return Content
- */
public function getTranslatedFields(?string $from, ?string $to, string $remoteServiceKey, Content $content): array
{
$posixFrom = null;
@@ -80,33 +59,25 @@ public function getTranslatedFields(?string $from, ?string $to, string $remoteSe
}
$this->guard->enforceTargetLanguageExist($to);
- $sourceContent = $this->guard->fetchContent($content, $from);
- $payload = $this->encoder->encode($sourceContent);
- $posixTo = $this->localeConverter->convertToPOSIX($to);
- $remoteService = $this->clientProvider->get($remoteServiceKey);
+ $sourceContent = $this->guard->fetchContent($content, $from);
+ $payload = $this->encoder->encode($sourceContent);
+ $posixTo = $this->localeConverter->convertToPOSIX($to);
+ $remoteService = $this->clientProvider->get($remoteServiceKey);
+
$translatedPayload = $remoteService->translate($payload, $posixFrom, $posixTo);
- return $this->encoder->decode($translatedPayload);
+ return $this->encoder->decode($translatedPayload, $sourceContent);
}
- /**
- * @param string $from
- * @param string $to
- * @param string $remoteServiceKey
- * @param Content $content
- *
- * @return Content
- */
public function getTranslatedContent(string $from, string $to, string $remoteServiceKey, Content $content): Content
{
$translatedFields = $this->getTranslatedFields($from, $to, $remoteServiceKey, $content);
- $contentService = $this->repository->getContentService();
- $contentDraft = $contentService->createContentDraft($content->contentInfo);
- $contentUpdateStruct = $contentService->newContentUpdateStruct();
+ $contentDraft = $this->contentService->createContentDraft($content->contentInfo);
+ $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
$contentUpdateStruct->initialLanguageCode = $to;
- $contentType = $this->repository->getContentTypeService()->loadContentType(
+ $contentType = $this->contentTypeService->loadContentType(
$content->contentInfo->contentTypeId
);
@@ -117,10 +88,10 @@ public function getTranslatedContent(string $from, string $to, string $remoteSer
/** @var FieldDefinition $field */
$fieldName = $field->identifier;
- $newValue = $translatedFields[$fieldName] ?? $content->getFieldValue($fieldName);
+ $newValue = $translatedFields[$fieldName] ?? $content->getFieldValue($fieldName);
$contentUpdateStruct->setField($fieldName, $newValue, $to);
}
- return $contentService->updateContent($contentDraft->versionInfo, $contentUpdateStruct);
+ return $this->contentService->updateContent($contentDraft->versionInfo, $contentUpdateStruct);
}
}
diff --git a/lib/TranslatorGuard.php b/lib/TranslatorGuard.php
index 69a7313..71be3e0 100644
--- a/lib/TranslatorGuard.php
+++ b/lib/TranslatorGuard.php
@@ -1,17 +1,15 @@
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\EzPlatformAutomatedTranslation;
+use eZ\Publish\API\Repository\ContentService;
+use eZ\Publish\API\Repository\LanguageService;
use eZ\Publish\API\Repository\Values\Content\Content;
/**
@@ -27,27 +25,26 @@
*/
class TranslatorGuard
{
- use RepositoryAware;
+ /** @var \eZ\Publish\API\Repository\ContentService */
+ private $contentService;
+
+ /** @var \eZ\Publish\API\Repository\LanguageService */
+ private $languageService;
+
+ public function __construct(ContentService $contentService, LanguageService $languageService)
+ {
+ $this->contentService = $contentService;
+ $this->languageService = $languageService;
+ }
- /**
- * @param Content $content
- * @param string $languageCode
- *
- * @return bool
- */
public function isLanguageVersionExist(Content $content, string $languageCode): bool
{
return \in_array($languageCode, $content->versionInfo->languageCodes);
}
- /**
- * @param string $languageCode
- *
- * @return bool
- */
public function isTargetLanguageVersionExist(string $languageCode): bool
{
- $languages = $this->repository->getContentLanguageService()->loadLanguages();
+ $languages = $this->languageService->loadLanguages();
foreach ($languages as $language) {
if ($language->enabled && $language->languageCode == $languageCode) {
return true;
@@ -57,10 +54,6 @@ public function isTargetLanguageVersionExist(string $languageCode): bool
return false;
}
- /**
- * @param Content $content
- * @param string $languageCode
- */
public function enforceSourceLanguageVersionExist(Content $content, string $languageCode): void
{
if (!$this->isLanguageVersionExist($content, $languageCode)) {
@@ -68,9 +61,6 @@ public function enforceSourceLanguageVersionExist(Content $content, string $lang
}
}
- /**
- * @param string $languageCode
- */
public function enforceTargetLanguageExist(string $languageCode): void
{
if (!$this->isTargetLanguageVersionExist($languageCode)) {
@@ -80,18 +70,12 @@ public function enforceTargetLanguageExist(string $languageCode): void
}
}
- /**
- * @param Content $content
- * @param string $languageCode
- *
- * @return Content
- */
public function fetchContent(Content $content, ?string $languageCode): Content
{
if (null === $languageCode) {
- return $this->repository->getContentService()->loadContentByContentInfo($content->contentInfo);
+ return $this->contentService->loadContentByContentInfo($content->contentInfo);
}
- return $this->repository->getContentService()->loadContentByContentInfo($content->contentInfo, [$languageCode]);
+ return $this->contentService->loadContentByContentInfo($content->contentInfo, [$languageCode]);
}
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index bb6d8fa..e395239 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -14,7 +14,7 @@
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
backupGlobals="false"
colors="true"
- bootstrap="vendor/autoload.php"
+ bootstrap="tests/bootstrap.php"
>
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
new file mode 100644
index 0000000..84caaff
--- /dev/null
+++ b/tests/bootstrap.php
@@ -0,0 +1,11 @@
+
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
- * @license For full copyright and license information view LICENSE file distributed with this source code.
+ * @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
-namespace EzSystems\EzPlatformDesignEngineBundle\Tests\DependencyInjection;
+namespace EzSystems\EzPlatformAutomatedTranslationBundle\Tests\DependencyInjection;
use PHPUnit\Framework\TestCase;
-use \Symfony\Component\HttpKernel\DependencyInjection\Extension;
-use \EzSystems\EzPlatformAutomatedTranslationBundle\DependencyInjection\EzPlatformAutomatedTranslationExtension;
+use EzSystems\EzPlatformAutomatedTranslationBundle\DependencyInjection\EzPlatformAutomatedTranslationExtension;
class EzPlatformAutomatedTranslationExtensionTest extends TestCase
{
public function clientConfigurationDataProvider()
{
return [
- #set 1
+ //set 1
[['system' => ['default' => ['configurations' => []]]], false],
- #set 2
+ //set 2
[['system' => ['default' => ['configurations' => [
- 'client1' => ['key1' => 'value1']
+ 'client1' => ['key1' => 'value1'],
]]]], true],
- #set 3
+ //set 3
[['system' => ['default' => ['configurations' => [
'client1' => [
'key1' => 'value1',
- 'key2' => 'value2'
+ 'key2' => 'value2',
],
]]]], true],
- #set 3
+ //set 3
[['system' => ['default' => ['configurations' => [
'client1' => [
'key1' => 'value1',
- 'key2' => 'valueX'
+ 'key2' => 'valueX',
],
'client2' => [
'key3' => 'value2',
- 'key2' => 'valueY'
+ 'key2' => 'valueY',
],
]]]], true],
- #set 4
+ //set 4
[['system' => ['default' => ['configurations' => [
'client1' => [
'key1' => 'value1',
- 'key2' => 'valueX'
+ 'key2' => 'valueX',
],
'client2' => [
'key3' => 'value2',
- 'key2' => 'valueY'
+ 'key2' => 'valueY',
],
'client3' => [
'key1' => 'ENV_TEST1',
- 'key2' => 'valueX'
+ 'key2' => 'valueX',
],
]]]], true],
];
diff --git a/tests/fixtures/testEncodeRichText_input.xml b/tests/fixtures/testEncodeRichText_input.xml
new file mode 100644
index 0000000..b0147c8
--- /dev/null
+++ b/tests/fixtures/testEncodeRichText_input.xml
@@ -0,0 +1,2 @@
+
+h1 h2 h3 h4 h5 h6 paragraph paragraph 2 anchor a1 test 1 large t11 t12 t13 t22 t31 t32 t33 primary fact 1
diff --git a/tests/fixtures/testEncodeRichText_input_encoded.xml b/tests/fixtures/testEncodeRichText_input_encoded.xml
new file mode 100644
index 0000000..3772448
--- /dev/null
+++ b/tests/fixtures/testEncodeRichText_input_encoded.xml
@@ -0,0 +1 @@
+h1 h2 h3 h4 h5 h6 paragraph formatted H558875da paragraph 2 anchor a1 test 1 H27c66e9d t11 t12 t13 t22 t31 t32 t33 H48decf6e Hd8a0244d
diff --git a/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_expectedEncodeResult.xml b/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_expectedEncodeResult.xml
new file mode 100644
index 0000000..dac1bb1
--- /dev/null
+++ b/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_expectedEncodeResult.xml
@@ -0,0 +1,2 @@
+
+ Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish. Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish. The basic staples are native foods such as corn, beans and chili peppers.
Main Features large
The ability to cook well, called "sazón" (lit. seasoning) is considered to be a gift generally gained from experience and a sense of commitment to the diners.
large
Mexican regional home cooking is completely different from the food served in most Mexican restaurants outside Mexico, which is usually some variety of Tex-Mex.
diff --git a/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_field1_richtext.xml b/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_field1_richtext.xml
new file mode 100644
index 0000000..fc6b562
--- /dev/null
+++ b/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_field1_richtext.xml
@@ -0,0 +1,5 @@
+
+ Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish.
+
diff --git a/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_field2_richtext.xml b/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_field2_richtext.xml
new file mode 100644
index 0000000..0e88c2a
--- /dev/null
+++ b/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_field2_richtext.xml
@@ -0,0 +1,15 @@
+
+ Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish. The
+ basic staples are native foods such as corn, beans and chili peppers.
+ Main Features
+ large
+ The ability to cook well, called "sazón" (lit. seasoning) is considered to be a gift generally gained from
+ experience and a sense of commitment to the diners.
+ large
+ Mexican regional home cooking is completely different from the food served in most Mexican restaurants outside
+ Mexico, which is usually some variety of Tex-Mex.
+
diff --git a/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_field2_richtext_encoded.xml b/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_field2_richtext_encoded.xml
new file mode 100644
index 0000000..fccfa01
--- /dev/null
+++ b/tests/fixtures/testEncodeTwoRichTextWithTwoEzembed_field2_richtext_encoded.xml
@@ -0,0 +1 @@
+ Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish. The basic staples are native foods such as corn, beans and chili peppers.
Main Features
data-ezalign="right"> data-ezvalue-key="size">large The ability to cook well, called "sazón" (lit. seasoning) is considered to be a gift generally gained from experience and a sense of commitment to the diners.
data-ezalign="left"> data-ezvalue-key="size">large Mexican regional home cooking is completely different from the food served in most Mexican restaurants outside Mexico, which is usually some variety of Tex-Mex.
diff --git a/tests/fixtures/testEncodeTwoRichText_expectedEncodeResult.xml b/tests/fixtures/testEncodeTwoRichText_expectedEncodeResult.xml
new file mode 100644
index 0000000..1b85674
--- /dev/null
+++ b/tests/fixtures/testEncodeTwoRichText_expectedEncodeResult.xml
@@ -0,0 +1,2 @@
+
+ Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish. Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish. File 2
diff --git a/tests/fixtures/testEncodeTwoRichText_field1_richtext.xml b/tests/fixtures/testEncodeTwoRichText_field1_richtext.xml
new file mode 100644
index 0000000..c93066e
--- /dev/null
+++ b/tests/fixtures/testEncodeTwoRichText_field1_richtext.xml
@@ -0,0 +1,7 @@
+
+
+ Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish.
+
+
diff --git a/tests/fixtures/testEncodeTwoRichText_field1_richtext_encoded.xml b/tests/fixtures/testEncodeTwoRichText_field1_richtext_encoded.xml
new file mode 100644
index 0000000..cdb0cf6
--- /dev/null
+++ b/tests/fixtures/testEncodeTwoRichText_field1_richtext_encoded.xml
@@ -0,0 +1 @@
+ xmlns:ezxhtml="http://ez.no/xmlns/ezpublish/docbook/xhtml" xmlns:ezcustom="http://ez.no/xmlns/ezpublish/docbook/custom" version="5.0-variant ezpublish-1.0"> Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish.
diff --git a/tests/fixtures/testEncodeTwoRichText_field2_richtext.xml b/tests/fixtures/testEncodeTwoRichText_field2_richtext.xml
new file mode 100644
index 0000000..cdea193
--- /dev/null
+++ b/tests/fixtures/testEncodeTwoRichText_field2_richtext.xml
@@ -0,0 +1,8 @@
+
+
+ Mexican cuisine is primarily a fusion of indigenous Mesoamerican cooking with European, especially Spanish.
+
+ File 2
+
diff --git a/tests/fixtures/testEncodeTwoTextline_expectedEncodeResult.xml b/tests/fixtures/testEncodeTwoTextline_expectedEncodeResult.xml
new file mode 100644
index 0000000..cbaf81c
--- /dev/null
+++ b/tests/fixtures/testEncodeTwoTextline_expectedEncodeResult.xml
@@ -0,0 +1,2 @@
+
+Some text 1 Some text 2
diff --git a/tests/lib/Encoder/Field/RichTextFieldEncoderTest.php b/tests/lib/Encoder/Field/RichTextFieldEncoderTest.php
new file mode 100644
index 0000000..d63e08d
--- /dev/null
+++ b/tests/lib/Encoder/Field/RichTextFieldEncoderTest.php
@@ -0,0 +1,77 @@
+getMockBuilder(RichTextEncoder::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $richTextEncoderMock
+ ->expects($this->atLeastOnce())
+ ->method('encode')
+ ->withAnyParameters()
+ ->willReturn('Some text 1');
+
+ $xml1 = $this->getFixture('testEncodeTwoRichText_field1_richtext.xml');
+
+ $field = new Field([
+ 'fieldDefIdentifier' => 'field_1_richtext',
+ 'value' => new RichText\Value($xml1),
+ ]);
+
+ $subject = new RichTextFieldEncoder($richTextEncoderMock);
+ $result = $subject->encode($field);
+
+ $this->assertEquals('Some text 1', $result);
+ }
+
+ public function testDecode()
+ {
+ $xml1 = $this->getFixture('testEncodeTwoRichText_field1_richtext.xml');
+
+ $richTextEncoderMock = $this->getMockBuilder(RichTextEncoder::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $richTextEncoderMock
+ ->expects($this->atLeastOnce())
+ ->method('decode')
+ ->withAnyParameters()
+ ->willReturn($xml1);
+
+ $field = new Field([
+ 'fieldDefIdentifier' => 'field_1_richtext',
+ 'value' => new RichText\Value($xml1),
+ ]);
+
+ $subject = new RichTextFieldEncoder($richTextEncoderMock);
+ $result = $subject->decode(
+ $xml1,
+ $field->value
+ );
+
+ $this->assertInstanceOf(RichText\Value::class, $result);
+ $this->assertEquals(new RichText\Value($xml1), $result);
+ }
+
+ protected function getFixture($name)
+ {
+ return file_get_contents(__DIR__ . '/../../../fixtures/' . $name);
+ }
+}
diff --git a/tests/lib/Encoder/Field/TextLineFieldEncoderTest.php b/tests/lib/Encoder/Field/TextLineFieldEncoderTest.php
new file mode 100644
index 0000000..53c2599
--- /dev/null
+++ b/tests/lib/Encoder/Field/TextLineFieldEncoderTest.php
@@ -0,0 +1,44 @@
+ 'field_1_textline',
+ 'value' => new TextLine\Value('Some text 1'),
+ ]);
+
+ $subject = new TextLineFieldEncoder();
+ $result = $subject->encode($field);
+
+ $this->assertEquals('Some text 1', $result);
+ }
+
+ public function testDecode()
+ {
+ $field = new Field([
+ 'fieldDefIdentifier' => 'field_1_textline',
+ 'value' => new TextLine\Value('Some text 1'),
+ ]);
+
+ $subject = new TextLineFieldEncoder();
+ $result = $subject->decode('Some text 1', $field->value);
+
+ $this->assertInstanceOf(TextLine\Value::class, $result);
+ $this->assertEquals(new TextLine\Value('Some text 1'), $result);
+ }
+}
diff --git a/tests/lib/Encoder/RichText/RichTextEncoderTest.php b/tests/lib/Encoder/RichText/RichTextEncoderTest.php
new file mode 100644
index 0000000..54e011e
--- /dev/null
+++ b/tests/lib/Encoder/RichText/RichTextEncoderTest.php
@@ -0,0 +1,122 @@
+configResolver = $this
+ ->getMockBuilder(ConfigResolverInterface::class)
+ ->getMock();
+
+ $this->configResolver
+ ->expects($this->at(0))
+ ->method('getParameter')
+ ->with(
+ $this->equalTo('non_translatable_tags'),
+ $this->equalTo('ez_platform_automated_translation')
+ )
+ ->willReturn([]);
+
+ $this->configResolver
+ ->expects($this->at(1))
+ ->method('getParameter')
+ ->with(
+ $this->equalTo('non_translatable_self_closed_tags'),
+ $this->equalTo('ez_platform_automated_translation')
+ )
+ ->willReturn([]);
+
+ $this->configResolver
+ ->expects($this->at(2))
+ ->method('getParameter')
+ ->with(
+ $this->equalTo('non_translatable_characters'),
+ $this->equalTo('ez_platform_automated_translation')
+ )
+ ->willReturn([]);
+
+ $this->configResolver
+ ->expects($this->at(3))
+ ->method('getParameter')
+ ->with(
+ $this->equalTo('non_valid_attribute_tags'),
+ $this->equalTo('ez_platform_automated_translation')
+ )
+ ->willReturn([]);
+ }
+
+ public function testEncodeAndDecodeRichtext()
+ {
+ $xml1 = $this->getFixture('testEncodeTwoRichText_field1_richtext.xml');
+
+ $subject = new RichTextEncoder($this->configResolver);
+
+ $encodeResult = $subject->encode($xml1);
+
+ $expected = $this->getFixture('testEncodeTwoRichText_field1_richtext_encoded.xml');
+
+ $this->assertEquals($expected, $encodeResult . "\n");
+
+ $decodeResult = $subject->decode($encodeResult);
+
+ $this->assertEquals($xml1, $decodeResult);
+ }
+
+ public function testEncodeAndDecodeRichtextEmbeded()
+ {
+ $xml1 = $this->getFixture('testEncodeTwoRichTextWithTwoEzembed_field2_richtext.xml');
+
+ $subject = new RichTextEncoder($this->configResolver);
+
+ $encodeResult = $subject->encode($xml1);
+
+ $expected = $this->getFixture('testEncodeTwoRichTextWithTwoEzembed_field2_richtext_encoded.xml');
+
+ $this->assertEquals($expected, $encodeResult . "\n");
+
+ $decodeResult = $subject->decode($encodeResult);
+
+ $this->assertEquals($xml1, $decodeResult);
+ }
+
+ public function testEncodeAndDecodeRichtextExtended()
+ {
+ $xml1 = $this->getFixture('testEncodeRichText_input.xml');
+
+ $subject = new RichTextEncoder($this->configResolver);
+
+ $encodeResult = $subject->encode($xml1);
+
+ $expected = $this->getFixture('testEncodeRichText_input_encoded.xml');
+
+ $this->assertEquals(trim($expected), trim($encodeResult));
+
+ $decodeResult = $subject->decode($encodeResult);
+
+ $decodeResult = '' . "\n" . $decodeResult;
+
+ $this->assertEquals($xml1, $decodeResult);
+ }
+
+ protected function getFixture($name)
+ {
+ return file_get_contents(__DIR__ . '/../../../fixtures/' . $name);
+ }
+}
diff --git a/tests/lib/EncoderTest.php b/tests/lib/EncoderTest.php
new file mode 100644
index 0000000..8391ddd
--- /dev/null
+++ b/tests/lib/EncoderTest.php
@@ -0,0 +1,158 @@
+getContentTypeServiceMock();
+ $eventDispatcherMock = $this->getMockBuilder(EventDispatcherInterface::class)->getMock();
+ $fieldEncoderManagerMock = $this->getMockBuilder(FieldEncoderManager::class)->getMock();
+
+ $content = new Content([
+ 'versionInfo' => new VersionInfo([
+ 'contentInfo' => new ContentInfo([
+ 'id' => 1,
+ 'contentTypeId' => 123,
+ ]),
+ ]),
+ 'internalFields' => [],
+ ]);
+
+ $subject = new Encoder(
+ $contentTypeServiceMock,
+ $eventDispatcherMock,
+ $fieldEncoderManagerMock
+ );
+
+ $encodeResult = $subject->encode($content);
+
+ $expected = <<
+
+
+XML;
+
+ $this->assertEquals($expected, $encodeResult);
+ }
+
+ public function testEncodeTwoTextline()
+ {
+ $contentTypeServiceMock = $this->getContentTypeServiceMock();
+ $eventDispatcherMock = $this->getMockBuilder(EventDispatcherInterface::class)->getMock();
+ $fieldEncoderManagerMock = $this->getMockBuilder(FieldEncoderManager::class)->getMock();
+
+ $contentType = $this->getMockForAbstractClass(
+ ContentType::class,
+ [],
+ '',
+ true,
+ true,
+ true,
+ ['getFieldDefinition']
+ );
+ $fieldDefinition = $this->getMockBuilder(FieldDefinition::class)
+ ->setConstructorArgs([
+ [
+ 'fieldTypeIdentifier' => 'ezstring',
+ 'isTranslatable' => true,
+ ],
+ ])
+ ->getMockForAbstractClass();
+
+ $contentType
+ ->expects($this->at(0))
+ ->method('getFieldDefinition')
+ ->with('field_1_textline')
+ ->will($this->returnValue($fieldDefinition));
+
+ $contentType
+ ->expects($this->at(1))
+ ->method('getFieldDefinition')
+ ->with('field_2_textline')
+ ->will($this->returnValue($fieldDefinition));
+
+ $contentTypeServiceMock
+ ->expects($this->once())
+ ->method('loadContentType')
+ ->with(123)
+ ->will($this->returnValue($contentType));
+
+ $content = new Content([
+ 'versionInfo' => new VersionInfo([
+ 'contentInfo' => new ContentInfo([
+ 'id' => 1,
+ 'contentTypeId' => 123,
+ ]),
+ ]),
+ 'internalFields' => [
+ new Field([
+ 'fieldDefIdentifier' => 'field_1_textline',
+ 'value' => new TextLine\Value('Some text 1'),
+ ]),
+ new Field([
+ 'fieldDefIdentifier' => 'field_2_textline',
+ 'value' => new TextLine\Value('Some text 2'),
+ ]),
+ ],
+ ]);
+
+ $fieldEncoderManagerMock
+ ->expects($this->exactly(2))
+ ->method('encode')
+ ->withAnyParameters()
+ ->will($this->returnValue('encoded'));
+
+ $subject = new Encoder(
+ $contentTypeServiceMock,
+ $eventDispatcherMock,
+ $fieldEncoderManagerMock
+ );
+
+ $encodeResult = $subject->encode($content);
+
+ $expectedEncodeResult = <<
+encoded encoded
+
+XML;
+
+ $this->assertEquals($expectedEncodeResult, $encodeResult);
+ }
+
+ /**
+ * Returns ContentTypeService mock object.
+ *
+ * @return \eZ\Publish\API\Repository\ContentTypeService|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected function getContentTypeServiceMock()
+ {
+ return $this
+ ->getMockBuilder('eZ\Publish\API\Repository\ContentTypeService')
+ ->getMock();
+ }
+
+ protected function getFixture($name)
+ {
+ return file_get_contents(__DIR__ . '/../fixtures/' . $name);
+ }
+}