first commit
This commit is contained in:
187
vendor/symfony/translation/Catalogue/AbstractOperation.php
vendored
Normal file
187
vendor/symfony/translation/Catalogue/AbstractOperation.php
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\Exception\LogicException;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Base catalogues binary operation class.
|
||||
*
|
||||
* A catalogue binary operation performs operation on
|
||||
* source (the left argument) and target (the right argument) catalogues.
|
||||
*
|
||||
* @author Jean-François Simon <contact@jfsimon.fr>
|
||||
*/
|
||||
abstract class AbstractOperation implements OperationInterface
|
||||
{
|
||||
public const OBSOLETE_BATCH = 'obsolete';
|
||||
public const NEW_BATCH = 'new';
|
||||
public const ALL_BATCH = 'all';
|
||||
|
||||
protected $source;
|
||||
protected $target;
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* This array stores 'all', 'new' and 'obsolete' messages for all valid domains.
|
||||
*
|
||||
* The data structure of this array is as follows:
|
||||
*
|
||||
* [
|
||||
* 'domain 1' => [
|
||||
* 'all' => [...],
|
||||
* 'new' => [...],
|
||||
* 'obsolete' => [...]
|
||||
* ],
|
||||
* 'domain 2' => [
|
||||
* 'all' => [...],
|
||||
* 'new' => [...],
|
||||
* 'obsolete' => [...]
|
||||
* ],
|
||||
* ...
|
||||
* ]
|
||||
*
|
||||
* @var array The array that stores 'all', 'new' and 'obsolete' messages
|
||||
*/
|
||||
protected $messages;
|
||||
|
||||
private array $domains;
|
||||
|
||||
/**
|
||||
* @throws LogicException
|
||||
*/
|
||||
public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
|
||||
{
|
||||
if ($source->getLocale() !== $target->getLocale()) {
|
||||
throw new LogicException('Operated catalogues must belong to the same locale.');
|
||||
}
|
||||
|
||||
$this->source = $source;
|
||||
$this->target = $target;
|
||||
$this->result = new MessageCatalogue($source->getLocale());
|
||||
$this->messages = [];
|
||||
}
|
||||
|
||||
public function getDomains(): array
|
||||
{
|
||||
if (!isset($this->domains)) {
|
||||
$domains = [];
|
||||
foreach ([$this->source, $this->target] as $catalogue) {
|
||||
foreach ($catalogue->getDomains() as $domain) {
|
||||
$domains[$domain] = $domain;
|
||||
|
||||
if ($catalogue->all($domainIcu = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX)) {
|
||||
$domains[$domainIcu] = $domainIcu;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->domains = array_values($domains);
|
||||
}
|
||||
|
||||
return $this->domains;
|
||||
}
|
||||
|
||||
public function getMessages(string $domain): array
|
||||
{
|
||||
if (!\in_array($domain, $this->getDomains())) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
|
||||
}
|
||||
|
||||
if (!isset($this->messages[$domain][self::ALL_BATCH])) {
|
||||
$this->processDomain($domain);
|
||||
}
|
||||
|
||||
return $this->messages[$domain][self::ALL_BATCH];
|
||||
}
|
||||
|
||||
public function getNewMessages(string $domain): array
|
||||
{
|
||||
if (!\in_array($domain, $this->getDomains())) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
|
||||
}
|
||||
|
||||
if (!isset($this->messages[$domain][self::NEW_BATCH])) {
|
||||
$this->processDomain($domain);
|
||||
}
|
||||
|
||||
return $this->messages[$domain][self::NEW_BATCH];
|
||||
}
|
||||
|
||||
public function getObsoleteMessages(string $domain): array
|
||||
{
|
||||
if (!\in_array($domain, $this->getDomains())) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
|
||||
}
|
||||
|
||||
if (!isset($this->messages[$domain][self::OBSOLETE_BATCH])) {
|
||||
$this->processDomain($domain);
|
||||
}
|
||||
|
||||
return $this->messages[$domain][self::OBSOLETE_BATCH];
|
||||
}
|
||||
|
||||
public function getResult(): MessageCatalogueInterface
|
||||
{
|
||||
foreach ($this->getDomains() as $domain) {
|
||||
if (!isset($this->messages[$domain])) {
|
||||
$this->processDomain($domain);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param self::*_BATCH $batch
|
||||
*/
|
||||
public function moveMessagesToIntlDomainsIfPossible(string $batch = self::ALL_BATCH): void
|
||||
{
|
||||
// If MessageFormatter class does not exists, intl domains are not supported.
|
||||
if (!class_exists(\MessageFormatter::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->getDomains() as $domain) {
|
||||
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
|
||||
$messages = match ($batch) {
|
||||
self::OBSOLETE_BATCH => $this->getObsoleteMessages($domain),
|
||||
self::NEW_BATCH => $this->getNewMessages($domain),
|
||||
self::ALL_BATCH => $this->getMessages($domain),
|
||||
default => throw new \InvalidArgumentException(sprintf('$batch argument must be one of ["%s", "%s", "%s"].', self::ALL_BATCH, self::NEW_BATCH, self::OBSOLETE_BATCH)),
|
||||
};
|
||||
|
||||
if (!$messages || (!$this->source->all($intlDomain) && $this->source->all($domain))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->getResult();
|
||||
$allIntlMessages = $result->all($intlDomain);
|
||||
$currentMessages = array_diff_key($messages, $result->all($domain));
|
||||
$result->replace($currentMessages, $domain);
|
||||
$result->replace($allIntlMessages + $messages, $intlDomain);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs operation on source and target catalogues for the given domain and
|
||||
* stores the results.
|
||||
*
|
||||
* @param string $domain The domain which the operation will be performed for
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function processDomain(string $domain);
|
||||
}
|
72
vendor/symfony/translation/Catalogue/MergeOperation.php
vendored
Normal file
72
vendor/symfony/translation/Catalogue/MergeOperation.php
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Merge operation between two catalogues as follows:
|
||||
* all = source ∪ target = {x: x ∈ source ∨ x ∈ target}
|
||||
* new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
|
||||
* obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ source ∧ x ∉ target} = ∅
|
||||
* Basically, the result contains messages from both catalogues.
|
||||
*
|
||||
* @author Jean-François Simon <contact@jfsimon.fr>
|
||||
*/
|
||||
class MergeOperation extends AbstractOperation
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function processDomain(string $domain)
|
||||
{
|
||||
$this->messages[$domain] = [
|
||||
'all' => [],
|
||||
'new' => [],
|
||||
'obsolete' => [],
|
||||
];
|
||||
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
|
||||
|
||||
foreach ($this->target->getCatalogueMetadata('', $domain) ?? [] as $key => $value) {
|
||||
if (null === $this->result->getCatalogueMetadata($key, $domain)) {
|
||||
$this->result->setCatalogueMetadata($key, $value, $domain);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->target->getCatalogueMetadata('', $intlDomain) ?? [] as $key => $value) {
|
||||
if (null === $this->result->getCatalogueMetadata($key, $intlDomain)) {
|
||||
$this->result->setCatalogueMetadata($key, $value, $intlDomain);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->source->all($domain) as $id => $message) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain;
|
||||
$this->result->add([$id => $message], $d);
|
||||
if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $d);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->target->all($domain) as $id => $message) {
|
||||
if (!$this->source->has($id, $domain)) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$this->messages[$domain]['new'][$id] = $message;
|
||||
$d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
|
||||
$this->result->add([$id => $message], $d);
|
||||
if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
61
vendor/symfony/translation/Catalogue/OperationInterface.php
vendored
Normal file
61
vendor/symfony/translation/Catalogue/OperationInterface.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Represents an operation on catalogue(s).
|
||||
*
|
||||
* An instance of this interface performs an operation on one or more catalogues and
|
||||
* stores intermediate and final results of the operation.
|
||||
*
|
||||
* The first catalogue in its argument(s) is called the 'source catalogue' or 'source' and
|
||||
* the following results are stored:
|
||||
*
|
||||
* Messages: also called 'all', are valid messages for the given domain after the operation is performed.
|
||||
*
|
||||
* New Messages: also called 'new' (new = all ∖ source = {x: x ∈ all ∧ x ∉ source}).
|
||||
*
|
||||
* Obsolete Messages: also called 'obsolete' (obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ all}).
|
||||
*
|
||||
* Result: also called 'result', is the resulting catalogue for the given domain that holds the same messages as 'all'.
|
||||
*
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
interface OperationInterface
|
||||
{
|
||||
/**
|
||||
* Returns domains affected by operation.
|
||||
*/
|
||||
public function getDomains(): array;
|
||||
|
||||
/**
|
||||
* Returns all valid messages ('all') after operation.
|
||||
*/
|
||||
public function getMessages(string $domain): array;
|
||||
|
||||
/**
|
||||
* Returns new messages ('new') after operation.
|
||||
*/
|
||||
public function getNewMessages(string $domain): array;
|
||||
|
||||
/**
|
||||
* Returns obsolete messages ('obsolete') after operation.
|
||||
*/
|
||||
public function getObsoleteMessages(string $domain): array;
|
||||
|
||||
/**
|
||||
* Returns resulting catalogue ('result').
|
||||
*/
|
||||
public function getResult(): MessageCatalogueInterface;
|
||||
}
|
86
vendor/symfony/translation/Catalogue/TargetOperation.php
vendored
Normal file
86
vendor/symfony/translation/Catalogue/TargetOperation.php
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Target operation between two catalogues:
|
||||
* intersection = source ∩ target = {x: x ∈ source ∧ x ∈ target}
|
||||
* all = intersection ∪ (target ∖ intersection) = target
|
||||
* new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
|
||||
* obsolete = source ∖ all = source ∖ target = {x: x ∈ source ∧ x ∉ target}
|
||||
* Basically, the result contains messages from the target catalogue.
|
||||
*
|
||||
* @author Michael Lee <michael.lee@zerustech.com>
|
||||
*/
|
||||
class TargetOperation extends AbstractOperation
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function processDomain(string $domain)
|
||||
{
|
||||
$this->messages[$domain] = [
|
||||
'all' => [],
|
||||
'new' => [],
|
||||
'obsolete' => [],
|
||||
];
|
||||
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
|
||||
|
||||
foreach ($this->target->getCatalogueMetadata('', $domain) ?? [] as $key => $value) {
|
||||
if (null === $this->result->getCatalogueMetadata($key, $domain)) {
|
||||
$this->result->setCatalogueMetadata($key, $value, $domain);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->target->getCatalogueMetadata('', $intlDomain) ?? [] as $key => $value) {
|
||||
if (null === $this->result->getCatalogueMetadata($key, $intlDomain)) {
|
||||
$this->result->setCatalogueMetadata($key, $value, $intlDomain);
|
||||
}
|
||||
}
|
||||
|
||||
// For 'all' messages, the code can't be simplified as ``$this->messages[$domain]['all'] = $target->all($domain);``,
|
||||
// because doing so will drop messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
|
||||
//
|
||||
// For 'new' messages, the code can't be simplified as ``array_diff_assoc($this->target->all($domain), $this->source->all($domain));``
|
||||
// because doing so will not exclude messages like {x: x ∈ target ∧ x ∉ source.all ∧ x ∈ source.fallback}
|
||||
//
|
||||
// For 'obsolete' messages, the code can't be simplified as ``array_diff_assoc($this->source->all($domain), $this->target->all($domain))``
|
||||
// because doing so will not exclude messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
|
||||
|
||||
foreach ($this->source->all($domain) as $id => $message) {
|
||||
if ($this->target->has($id, $domain)) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain;
|
||||
$this->result->add([$id => $message], $d);
|
||||
if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $d);
|
||||
}
|
||||
} else {
|
||||
$this->messages[$domain]['obsolete'][$id] = $message;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->target->all($domain) as $id => $message) {
|
||||
if (!$this->source->has($id, $domain)) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$this->messages[$domain]['new'][$id] = $message;
|
||||
$d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
|
||||
$this->result->add([$id => $message], $d);
|
||||
if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user