diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index f21d7184..6524f215 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -37,7 +37,7 @@ jobs:
strategy:
matrix:
- php-version: ['8.2', '8.3', '8.4']
+ php-version: ['8.4', '8.5']
steps:
- name: Setup PHP
diff --git a/.gitignore b/.gitignore
index 4cdb362b..7756f250 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
# Composer dependencies (installed with composer install)
vendor
+composer.lock
# PhpStorm IDE configuration and cache
.idea
diff --git a/Command/ExportTranslationsCommand.php b/Command/ExportTranslationsCommand.php
index c8fe10ea..6fe186d1 100644
--- a/Command/ExportTranslationsCommand.php
+++ b/Command/ExportTranslationsCommand.php
@@ -57,16 +57,24 @@ protected function configure(): void
{
$this->addOption(
- 'locales', 'l', InputOption::VALUE_OPTIONAL,
- 'Only export files for given locales. e.g. "--locales=en,de"', null
+ 'locales',
+ 'l',
+ InputOption::VALUE_OPTIONAL,
+ 'Only export files for given locales. e.g. "--locales=en,de"',
+ null
);
$this->addOption(
- 'domains', 'd', InputOption::VALUE_OPTIONAL,
- 'Only export files for given domains. e.g. "--domains=messages,validators"', null
+ 'domains',
+ 'd',
+ InputOption::VALUE_OPTIONAL,
+ 'Only export files for given domains. e.g. "--domains=messages,validators"',
+ null
);
$this->addOption('format', 'f', InputOption::VALUE_OPTIONAL, 'Force the output format.', null);
$this->addOption(
- 'override', 'o', InputOption::VALUE_NONE,
+ 'override',
+ 'o',
+ InputOption::VALUE_NONE,
'Only export modified phrases (app/Resources/translations are exported fully anyway)'
);
$this->addOption('export-path', 'p', InputOption::VALUE_REQUIRED, 'Export files to given path.');
@@ -164,15 +172,10 @@ protected function exportFile(FileInterface $file)
/**
* If the output file exists we merge existing translations with those from the database.
- *
- * @param FileInterface $file
- * @param string $outputFile
- * @param array $translations
- * @return array
*/
- protected function mergeExistingTranslations($file, $outputFile, $translations)
+ protected function mergeExistingTranslations(FileInterface $file, string $outputFile, array $translations): array
{
- if (file_exists($outputFile)) {
+ if (file_exists($outputFile) && method_exists($this->translator, 'getLoader')) {
$extension = pathinfo($outputFile, PATHINFO_EXTENSION);
$loader = $this->translator->getLoader($extension);
$messageCatalogue = $loader->load($outputFile, $file->getLocale(), $file->getDomain());
diff --git a/Command/ImportTranslationsCommand.php b/Command/ImportTranslationsCommand.php
index 04a9e672..ce216d4b 100644
--- a/Command/ImportTranslationsCommand.php
+++ b/Command/ImportTranslationsCommand.php
@@ -12,10 +12,11 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
-use Symfony\Component\HttpKernel\Kernel;
+use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Validator\Validation;
use Symfony\Contracts\Translation\TranslatorInterface;
@@ -53,13 +54,13 @@
)]
class ImportTranslationsCommand extends Command
{
- /**
- * @param TranslatorInterface $translator
- */
public function __construct(
private readonly TranslatorInterface $translator,
private readonly LocaleManagerInterface $localeManager,
private readonly FileImporter $fileImporter,
+ private readonly KernelInterface $kernel,
+ #[Autowire('%kernel.project_dir%')]
+ private readonly string $projectDir,
) {
parent::__construct();
}
@@ -106,7 +107,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$bundleName = $this->input->getArgument('bundle');
if ($bundleName) {
- $bundle = $this->getApplication()->getKernel()->getBundle($bundleName);
+ $bundle = $this->kernel->getBundle($bundleName);
$this->importBundleTranslationFiles($bundle, $locales, $domains, (bool)$this->input->getOption('globals'));
} else {
if (!$this->input->getOption('import-path')) {
@@ -141,7 +142,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$this->importTranslationFilesFromPath($importPath, $locales, $domains);
}
- if ($this->input->getOption('cache-clear')) {
+ if ($this->input->getOption('cache-clear') && method_exists($this->translator, 'removeLocalesCacheFiles')) {
$this->output->writeln('Removing translations cache files ...');
$this->translator->removeLocalesCacheFiles($locales);
}
@@ -181,8 +182,8 @@ protected function importTranslationFilesFromPath($path, array $locales, array $
protected function importComponentTranslationFiles(array $locales, array $domains)
{
$classes = [
- Validation::class => '/Resources/translations',
- Form::class => '/Resources/translations',
+ Validation::class => '/Resources/translations',
+ Form::class => '/Resources/translations',
AuthenticationException::class => '/../Resources/translations',
];
@@ -203,14 +204,10 @@ protected function importComponentTranslationFiles(array $locales, array $domain
/**
* Imports application translation files.
*/
- protected function importAppTranslationFiles(array $locales, array $domains)
+ protected function importAppTranslationFiles(array $locales, array $domains): void
{
- if (Kernel::MAJOR_VERSION >= 4) {
- $translationPath = $this->getApplication()->getKernel()->getProjectDir() . '/translations';
- $finder = $this->findTranslationsFiles($translationPath, $locales, $domains, false);
- } else {
- $finder = $this->findTranslationsFiles($this->getApplication()->getKernel()->getRootDir(), $locales, $domains);
- }
+ $translationPath = $this->projectDir . '/translations';
+ $finder = $this->findTranslationsFiles($translationPath, $locales, $domains, false);
$this->importTranslationFiles($finder);
}
@@ -221,7 +218,7 @@ protected function importAppTranslationFiles(array $locales, array $domains)
*/
protected function importBundlesTranslationFiles(array $locales, array $domains, $global = false)
{
- $bundles = $this->getApplication()->getKernel()->getBundles();
+ $bundles = $this->kernel->getBundles();
foreach ($bundles as $bundle) {
$this->importBundleTranslationFiles($bundle, $locales, $domains, $global);
@@ -230,20 +227,11 @@ protected function importBundlesTranslationFiles(array $locales, array $domains,
/**
* Imports translation files form the specific bundles.
- *
- * @param array $locales
- * @param array $domains
- * @param boolean $global
*/
- protected function importBundleTranslationFiles(BundleInterface $bundle, $locales, $domains, $global = false)
+ protected function importBundleTranslationFiles(BundleInterface $bundle, array $locales, array $domains, bool $global = false): void
{
if ($global) {
- $kernel = $this->getApplication()->getKernel();
- if (Kernel::MAJOR_VERSION >= 4) {
- $path = $kernel->getProjectDir() . '/app';
- } else {
- $path = $kernel->getRootDir();
- }
+ $path = $this->projectDir . '/app';
$path .= '/Resources/' . $bundle->getName() . '/translations';
@@ -261,7 +249,7 @@ protected function importBundleTranslationFiles(BundleInterface $bundle, $locale
$bundle->getPath() . '/Resources/translations',
];
- foreach($paths as $path) {
+ foreach ($paths as $path) {
$this->output->writeln(sprintf('# %s:', $bundle->getName()));
$finder = $this->findTranslationsFiles($path, $locales, $domains, false);
$this->importTranslationFiles($finder);
@@ -270,10 +258,8 @@ protected function importBundleTranslationFiles(BundleInterface $bundle, $locale
/**
* Imports some translations files.
- *
- * @param Finder $finder
*/
- protected function importTranslationFiles($finder)
+ protected function importTranslationFiles(?Finder $finder): void
{
if (!$finder instanceof Finder) {
$this->output->writeln('No file to import');
@@ -297,20 +283,17 @@ protected function importTranslationFiles($finder)
/**
* Return a Finder object if $path has a Resources/translations folder.
- *
- * @param string $path
- * @return Finder
*/
- protected function findTranslationsFiles($path, array $locales, array $domains, $autocompletePath = true)
+ protected function findTranslationsFiles(string $path, array $locales, array $domains, $autocompletePath = true): ?Finder
{
$finder = null;
- if (preg_match('#^win#i', PHP_OS)) {
+ if (0 === stripos(PHP_OS_FAMILY, "win")) {
$path = preg_replace('#' . preg_quote(DIRECTORY_SEPARATOR, '#') . '#', '/', $path);
}
if (true === $autocompletePath) {
- $dir = (str_starts_with((string) $path, $this->getApplication()->getKernel()->getProjectDir() . '/Resources')) ? $path : $path . '/Resources/translations';
+ $dir = (str_starts_with((string) $path, $this->projectDir . '/Resources')) ? $path : $path . '/Resources/translations';
} else {
$dir = $path;
}
@@ -327,12 +310,9 @@ protected function findTranslationsFiles($path, array $locales, array $domains,
return (null !== $finder && $finder->count() > 0) ? $finder : null;
}
- /**
- * @return string
- */
- protected function getFileNamePattern(array $locales, array $domains)
+ protected function getFileNamePattern(array $locales, array $domains): string
{
- $formats = $this->translator->getFormats();
+ $formats = method_exists($this->translator, 'getFormats') ? $this->translator->getFormats() : [];
if (count($domains)) {
$regex = sprintf('/((%s)\.(%s)\.(%s))/', implode('|', $domains), implode('|', $locales), implode('|', $formats));
diff --git a/Controller/RestController.php b/Controller/RestController.php
index 08243013..51b871b9 100644
--- a/Controller/RestController.php
+++ b/Controller/RestController.php
@@ -10,6 +10,7 @@
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* @author Cédric Girard
@@ -18,8 +19,6 @@ class RestController extends AbstractController
{
use CsrfCheckerTrait;
- private $csrfTokenManager;
-
public function __construct(
private readonly DataGridRequestHandler $dataGridRequestHandler,
private readonly DataGridFormatter $dataGridFormatter,
@@ -43,7 +42,7 @@ public function listByProfileAction(Request $request, string $token): JsonRespon
}
/**
- * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+ * @throws NotFoundHttpException
*/
public function updateAction(Request $request, int $id): JsonResponse
{
@@ -55,7 +54,7 @@ public function updateAction(Request $request, int $id): JsonResponse
}
/**
- * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+ * @throws NotFoundHttpException
*/
public function deleteAction(int $id): JsonResponse
{
@@ -73,7 +72,7 @@ public function deleteAction(int $id): JsonResponse
}
/**
- * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+ * @throws NotFoundHttpException
*/
public function deleteTranslationAction(int $id, string $locale): JsonResponse
{
diff --git a/Controller/TranslationController.php b/Controller/TranslationController.php
index 2df5b8b9..5993b25c 100644
--- a/Controller/TranslationController.php
+++ b/Controller/TranslationController.php
@@ -6,11 +6,11 @@
use Lexik\Bundle\TranslationBundle\Form\Type\TransUnitType;
use Lexik\Bundle\TranslationBundle\Manager\LocaleManagerInterface;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
-use Lexik\Bundle\TranslationBundle\Translation\TranslatorDecorator;
use Lexik\Bundle\TranslationBundle\Util\Csrf\CsrfCheckerTrait;
use Lexik\Bundle\TranslationBundle\Util\Overview\StatsAggregator;
use Lexik\Bundle\TranslationBundle\Util\Profiler\TokenFinder;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\Form\SubmitButton;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -23,8 +23,14 @@ class TranslationController extends AbstractController
{
use CsrfCheckerTrait;
- public function __construct(private readonly StorageInterface $translationStorage, private readonly StatsAggregator $statsAggregator, private readonly TransUnitFormHandler $transUnitFormHandler, private readonly TranslatorInterface $lexikTranslator, private readonly TranslatorInterface $translator, private readonly LocaleManagerInterface $localeManager, private readonly ?TokenFinder $tokenFinder)
- {
+ public function __construct(
+ private readonly StorageInterface $translationStorage,
+ private readonly StatsAggregator $statsAggregator,
+ private readonly TransUnitFormHandler $transUnitFormHandler,
+ private readonly TranslatorInterface $translator,
+ private readonly LocaleManagerInterface $localeManager,
+ private readonly ?TokenFinder $tokenFinder
+ ) {
}
/**
@@ -34,7 +40,13 @@ public function overviewAction(): Response
{
$stats = $this->statsAggregator->getStats();
- return $this->render('@LexikTranslation/Translation/overview.html.twig', ['layout' => $this->getParameter('lexik_translation.base_layout'), 'locales' => $this->getManagedLocales(), 'domains' => $this->translationStorage->getTransUnitDomains(), 'latestTrans' => $this->translationStorage->getLatestUpdatedAt(), 'stats' => $stats]);
+ return $this->render('@LexikTranslation/Translation/overview.html.twig', [
+ 'layout' => $this->getParameter('lexik_translation.base_layout'),
+ 'locales' => $this->getManagedLocales(),
+ 'domains' => $this->translationStorage->getTransUnitDomains(),
+ 'latestTrans' => $this->translationStorage->getLatestUpdatedAt(),
+ 'stats' => $stats,
+ ]);
}
/**
@@ -47,7 +59,14 @@ public function gridAction(): Response
$tokens = $this->tokenFinder->find();
}
- return $this->render('@LexikTranslation/Translation/grid.html.twig', ['layout' => $this->getParameter('lexik_translation.base_layout'), 'inputType' => $this->getParameter('lexik_translation.grid_input_type'), 'autoCacheClean' => $this->getParameter('lexik_translation.auto_cache_clean'), 'toggleSimilar' => $this->getParameter('lexik_translation.grid_toggle_similar'), 'locales' => $this->getManagedLocales(), 'tokens' => $tokens]);
+ return $this->render('@LexikTranslation/Translation/grid.html.twig', [
+ 'layout' => $this->getParameter('lexik_translation.base_layout'),
+ 'inputType' => $this->getParameter('lexik_translation.grid_input_type'),
+ 'autoCacheClean' => $this->getParameter('lexik_translation.auto_cache_clean'),
+ 'toggleSimilar' => $this->getParameter('lexik_translation.grid_toggle_similar'),
+ 'locales' => $this->getManagedLocales(),
+ 'tokens' => $tokens,
+ ]);
}
/**
@@ -55,8 +74,8 @@ public function gridAction(): Response
*/
public function invalidateCacheAction(Request $request): Response
{
- if (method_exists($this->lexikTranslator, 'removeLocalesCacheFiles')) {
- $this->lexikTranslator->removeLocalesCacheFiles($this->getManagedLocales());
+ if (method_exists($this->translator, 'removeLocalesCacheFiles')) {
+ $this->translator->removeLocalesCacheFiles($this->getManagedLocales());
}
$message = $this->translator->trans('translations.cache_removed', [], 'LexikTranslationBundle');
@@ -67,7 +86,7 @@ public function invalidateCacheAction(Request $request): Response
return new JsonResponse(['message' => $message]);
}
- $request->getSession()->getFlashBag()->add('success', $message);
+ $this->addFlash('success', $message);
return $this->redirect($this->generateUrl('lexik_translation_grid'));
}
@@ -82,22 +101,22 @@ public function newAction(Request $request): Response
if ($this->transUnitFormHandler->process($form, $request)) {
$message = $this->translator->trans('translations.successfully_added', [], 'LexikTranslationBundle');
- $request->getSession()->getFlashBag()->add('success', $message);
+ $this->addFlash('success', $message);
- $redirectUrl = $form->get('save_add')->isClicked() ? 'lexik_translation_new' : 'lexik_translation_grid';
+ /** @var SubmitButton $btn */
+ $btn = $form->get('save_add');
+ $redirectUrl = $btn->isClicked() ? 'lexik_translation_new' : 'lexik_translation_grid';
return $this->redirect($this->generateUrl($redirectUrl));
}
- return $this->render('@LexikTranslation/Translation/new.html.twig', ['layout' => $this->getParameter('lexik_translation.base_layout'), 'form' => $form->createView()]);
+ return $this->render('@LexikTranslation/Translation/new.html.twig', ['layout' => $this->getParameter('lexik_translation.base_layout'), 'form' => $form->createView()]);
}
/**
* Returns managed locales.
- *
- * @return array
*/
- protected function getManagedLocales()
+ protected function getManagedLocales(): array
{
return $this->localeManager->getLocales();
}
diff --git a/DependencyInjection/Compiler/RegisterMappingPass.php b/DependencyInjection/Compiler/RegisterMappingPass.php
index 7bdbc892..ac183d75 100644
--- a/DependencyInjection/Compiler/RegisterMappingPass.php
+++ b/DependencyInjection/Compiler/RegisterMappingPass.php
@@ -5,10 +5,10 @@
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
/**
* Doctrine metadata pass to add a driver to load model class mapping.
@@ -26,7 +26,7 @@ public function process(ContainerBuilder $container): void
$name = empty($storage['object_manager']) ? 'default' : $storage['object_manager'];
- $ormDriverId = sprintf('doctrine.orm.%s_metadata_driver', $name);
+ $ormDriverId = sprintf('doctrine.orm.%s_metadata_driver', $name);
$mongodbDriverId = sprintf('doctrine_mongodb.odm.%s_metadata_driver', $name);
if (StorageInterface::STORAGE_ORM == $storage['type'] && $container->hasDefinition($ormDriverId)) {
diff --git a/DependencyInjection/Compiler/TranslatorPass.php b/DependencyInjection/Compiler/TranslatorPass.php
index eda7d70b..1a1b8427 100644
--- a/DependencyInjection/Compiler/TranslatorPass.php
+++ b/DependencyInjection/Compiler/TranslatorPass.php
@@ -4,9 +4,9 @@
use Lexik\Bundle\TranslationBundle\Translation\Exporter\ExporterCollector;
use Lexik\Bundle\TranslationBundle\Translation\Importer\FileImporter;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
/**
@@ -21,6 +21,13 @@ class TranslatorPass implements CompilerPassInterface
*/
public function process(ContainerBuilder $container): void
{
+ // Keep the compatibility with old versions of the bundle (options fallback_locale and managed_locales).
+ $this->processEnabledLocales($container);
+ $this->processFallbacksLocales($container);
+
+ $this->processCacheDir($container);
+ $this->processRessources($container);
+
// loaders
$loaders = [];
$loadersReferences = [];
@@ -37,29 +44,13 @@ public function process(ContainerBuilder $container): void
}
}
- // Find the translator service by alias or class name
- $translatorId = null;
if ($container->hasDefinition('lexik_translation.translator')) {
- $translatorId = 'lexik_translation.translator';
- } elseif ($container->hasAlias('lexik_translation.translator')) {
- $translatorId = (string) $container->getAlias('lexik_translation.translator');
- } elseif ($container->hasDefinition('Lexik\Bundle\TranslationBundle\Translation\Translator')) {
- $translatorId = 'Lexik\Bundle\TranslationBundle\Translation\Translator';
- }
-
- if ($translatorId && $container->hasDefinition($translatorId)) {
- $translatorDef = $container->findDefinition($translatorId);
+ $translatorDef = $container->findDefinition('lexik_translation.translator');
$serviceRefs = [...$loadersReferencesById, ...['event_dispatcher' => new Reference('event_dispatcher')]];
- // Use named arguments if available, otherwise use numeric indices
- if ($translatorDef->getArguments() && array_key_exists('$container', $translatorDef->getArguments())) {
- $translatorDef->replaceArgument('$container', ServiceLocatorTagPass::register($container, $serviceRefs));
- $translatorDef->replaceArgument('$loaderIds', $loaders);
- } else {
- $translatorDef->replaceArgument(0, ServiceLocatorTagPass::register($container, $serviceRefs));
- $translatorDef->replaceArgument(3, $loaders);
- }
+ $translatorDef->replaceArgument('$container', ServiceLocatorTagPass::register($container, $serviceRefs));
+ $translatorDef->replaceArgument('$loaderIds', $loaders);
}
if ($container->hasDefinition(FileImporter::class)) {
@@ -73,4 +64,68 @@ public function process(ContainerBuilder $container): void
}
}
}
+
+ private function processRessources(ContainerBuilder $container): void
+ {
+ $translator = $container->getDefinition('translator.default');
+
+ $defaultOptions = $translator->getArgument(4);
+
+ // If the resources type is set to "database", we don't want to load any resource file, as they will be loaded from the database.
+ $ressourcesType = $container->getParameter('lexik_translation.resources_type');
+
+ if ('database' === $ressourcesType) {
+ $defaultOptions['resource_files'] = [];
+ $translator->replaceArgument(4, $defaultOptions);
+ return;
+ }
+
+ // If the option "managed_locales_only" is set to true, we only want to load the resource files for the enabled locales.
+ if (true === $container->getParameter('lexik_translation.managed_locales_only')) {
+ $enabledLocales = $translator->getArgument(5);
+
+ $defaultOptions['resource_files'] = array_filter($defaultOptions['resource_files'], static function ($locale) use ($enabledLocales) {
+ return in_array($locale, $enabledLocales, true);
+ }, \ARRAY_FILTER_USE_KEY);
+
+ $translator->replaceArgument(4, $defaultOptions);
+ }
+ }
+
+ private function processFallbacksLocales(ContainerBuilder $container): void
+ {
+ $fallbackLocale = $container->getParameter('lexik_translation.fallback_locale');
+
+ if (!empty($fallbackLocale)) {
+ $translator = $container->findDefinition('translator.default');
+ $translator->addMethodCall('setFallbackLocales', [ $fallbackLocale ]);
+ }
+ }
+
+ private function processEnabledLocales(ContainerBuilder $container): void
+ {
+ $enabledLocales = $container->getParameter('kernel.enabled_locales');
+
+ if (empty($enabledLocales)) {
+ $fallbackEnabledLocales = $container->getParameter('lexik_translation.managed_locales');
+ if (!empty($fallbackEnabledLocales)) {
+ $enabledLocales = $fallbackEnabledLocales;
+ }
+ $translator = $container->findDefinition('translator.default');
+ $translator->replaceArgument(5, $enabledLocales);
+ }
+ }
+
+ private function processCacheDir(ContainerBuilder $container): void
+ {
+ $translator = $container->findDefinition('translator.default');
+ $options = $translator->getArgument(4);
+ $cacheDir = $options['cache_dir'] ?? null;
+ if (null !== $cacheDir) {
+ $translatorDef = $container->findDefinition('lexik_translation.translator');
+ $defaultOptions = $translatorDef->getArgument('$options');
+ $defaultOptions['cache_dir'] = $cacheDir;
+ $translatorDef->replaceArgument('$options', $defaultOptions);
+ }
+ }
}
diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php
index f71c858f..f21dd3df 100644
--- a/DependencyInjection/Configuration.php
+++ b/DependencyInjection/Configuration.php
@@ -40,19 +40,19 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->arrayNode('fallback_locale')
- ->isRequired()
- ->requiresAtLeastOneElement()
+ ->setDeprecated('lexik/translation-bundle', '8.0', 'The "%node%" option is deprecated. Use "framework.translator.fallbacks" instead.')
->prototype('scalar')->end()
+ ->defaultValue([])
->beforeNormalization()
->ifString()
- ->then(fn($value) => [$value])
+ ->then(fn ($value) => [$value])
->end()
->end()
->arrayNode('managed_locales')
- ->isRequired()
- ->requiresAtLeastOneElement()
+ ->info('Locales managed in the translation grid. If not set, falls back to "framework.enabled_locales".')
->prototype('scalar')->end()
+ ->defaultValue([])
->end()
->scalarNode('grid_input_type')
@@ -60,7 +60,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultValue('text')
->validate()
->ifNotInArray($inputTypes)
- ->thenInvalid('The input type "%s" is not supported. Please use one of the following types: '.implode(', ', $inputTypes))
+ ->thenInvalid('The input type "%s" is not supported. Please use one of the following types: ' . implode(', ', $inputTypes))
->end()
->end()
@@ -84,7 +84,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultValue(StorageInterface::STORAGE_ORM)
->validate()
->ifNotInArray($storages)
- ->thenInvalid('The storage "%s" is not supported. Please use one of the following storage: '.implode(', ', $storages))
+ ->thenInvalid('The storage "%s" is not supported. Please use one of the following storage: ' . implode(', ', $storages))
->end()
->end()
->scalarNode('object_manager')
@@ -100,7 +100,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultValue('all')
->validate()
->ifNotInArray($registrationTypes)
- ->thenInvalid('Invalid registration type "%s". Please use one of the following types: '.implode(', ', $registrationTypes))
+ ->thenInvalid('Invalid registration type "%s". Please use one of the following types: ' . implode(', ', $registrationTypes))
->end()
->end()
->booleanNode('managed_locales_only')
diff --git a/DependencyInjection/LexikTranslationExtension.php b/DependencyInjection/LexikTranslationExtension.php
index d4d8c680..d20b13ba 100644
--- a/DependencyInjection/LexikTranslationExtension.php
+++ b/DependencyInjection/LexikTranslationExtension.php
@@ -2,26 +2,21 @@
namespace Lexik\Bundle\TranslationBundle\DependencyInjection;
-use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
-use Symfony\Component\Validator\Validation;
-use Symfony\Component\Form\Form;
-use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Doctrine\ORM\Events;
-use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver;
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
+use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver;
+use Lexik\Bundle\TranslationBundle\LexikTranslationBundle;
use Lexik\Bundle\TranslationBundle\Manager\LocaleManagerInterface;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
-use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Definition\Processor;
-use Symfony\Component\Config\Resource\DirectoryResource;
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
-use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Parameter;
-use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\Finder\Finder;
-use Symfony\Component\HttpKernel\Kernel;
+use Symfony\Component\DependencyInjection\Reference;
/**
* This is the class that loads and manages your bundle configuration
@@ -41,15 +36,23 @@ public function load(array $configs, ContainerBuilder $container): void
$configuration = new Configuration();
$config = $processor->processConfiguration($configuration, $configs);
- $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
+ $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('services.yaml');
- // set parameters
- sort($config['managed_locales']);
- $container->setParameter('lexik_translation.managed_locales', $config['managed_locales']);
+ // Resolve managed_locales: fallback to framework.enabled_locales if not set
+ $managedLocales = $config['managed_locales'];
+ if (empty($managedLocales)) {
+ $managedLocales = $container->hasParameter('kernel.enabled_locales')
+ ? $container->getParameter('kernel.enabled_locales')
+ : [];
+ }
+ sort($managedLocales);
+
+ $container->setParameter('lexik_translation.managed_locales', $managedLocales);
$container->setParameter('lexik_translation.fallback_locale', $config['fallback_locale']);
$container->setParameter('lexik_translation.storage', $config['storage']);
$container->setParameter('lexik_translation.resources_type', $config['resources_registration']['type']);
+ $container->setParameter('lexik_translation.managed_locales_only', $config['resources_registration']['managed_locales_only']);
$container->setParameter('lexik_translation.base_layout', $config['base_layout']);
$container->setParameter('lexik_translation.grid_input_type', $config['grid_input_type']);
$container->setParameter('lexik_translation.grid_toggle_similar', $config['grid_toggle_similar']);
@@ -60,7 +63,7 @@ public function load(array $configs, ContainerBuilder $container): void
$container->setParameter('lexik_translation.exporter.json.hierarchical_format', $config['exporter']['json_hierarchical_format']);
$container->setParameter('lexik_translation.exporter.yml.use_tree', $config['exporter']['use_yml_tree']);
- $objectManager = $config['storage']['object_manager'] ?? null;
+ $objectManager = $config['storage']['object_manager'] ?? 'default';
$this->buildTranslationStorageDefinition($container, $config['storage']['type'], $objectManager);
@@ -71,14 +74,12 @@ public function load(array $configs, ContainerBuilder $container): void
if (true === $config['dev_tools']['enable']) {
$this->buildDevServicesDefinition($container);
}
-
- $this->registerTranslatorConfiguration($config, $container);
}
/**
* @param int $cacheInterval
*/
- public function buildCacheCleanListenerDefinition(ContainerBuilder $container, $cacheInterval)
+ public function buildCacheCleanListenerDefinition(ContainerBuilder $container, $cacheInterval): void
{
$listener = new Definition();
$listener->setClass('%lexik_translation.listener.clean_translation_cache.class%');
@@ -89,7 +90,7 @@ public function buildCacheCleanListenerDefinition(ContainerBuilder $container, $
$listener->addArgument(new Reference(LocaleManagerInterface::class));
$listener->addArgument($cacheInterval);
- $listener->addTag('kernel.event_listener', ['event' => 'kernel.request', 'method' => 'onKernelRequest']);
+ $listener->addTag('kernel.event_listener', ['event' => 'kernel.request', 'method' => 'onKernelRequest']);
$container->setDefinition('lexik_translation.listener.clean_translation_cache', $listener);
}
@@ -116,12 +117,12 @@ public function prepend(ContainerBuilder $container): void
* @param string $objectManager
* @throws \RuntimeException
*/
- protected function buildTranslationStorageDefinition(ContainerBuilder $container, $storage, $objectManager)
+ protected function buildTranslationStorageDefinition(ContainerBuilder $container, $storage, string $objectManager): void
{
$container->setParameter('lexik_translation.storage.type', $storage);
- if (StorageInterface::STORAGE_ORM == $storage) {
- $args = [new Reference('doctrine'), $objectManager ?? 'default'];
+ if (StorageInterface::STORAGE_ORM === $storage) {
+ $args = [new Reference('doctrine'), $objectManager];
// Create XML driver for backward compatibility
if (class_exists(SimplifiedXmlDriver::class)) {
@@ -140,8 +141,8 @@ protected function buildTranslationStorageDefinition(ContainerBuilder $container
$container->setDefinition('lexik_translation.orm.listener', $metadataListener);
- } elseif (StorageInterface::STORAGE_MONGODB == $storage) {
- $args = [new Reference('doctrine_mongodb'), $objectManager ?? 'default'];
+ } elseif (StorageInterface::STORAGE_MONGODB === $storage) {
+ $args = [new Reference('doctrine_mongodb'), $objectManager];
$this->createDoctrineMappingDriver($container, 'lexik_translation.mongodb.metadata.xml', '%doctrine_mongodb.odm.metadata.xml.class%');
} else {
@@ -149,9 +150,9 @@ protected function buildTranslationStorageDefinition(ContainerBuilder $container
}
$args[] = [
- 'trans_unit' => new Parameter(sprintf('lexik_translation.%s.trans_unit.class', $storage)),
+ 'trans_unit' => new Parameter(sprintf('lexik_translation.%s.trans_unit.class', $storage)),
'translation' => new Parameter(sprintf('lexik_translation.%s.translation.class', $storage)),
- 'file' => new Parameter(sprintf('lexik_translation.%s.file.class', $storage))
+ 'file' => new Parameter(sprintf('lexik_translation.%s.file.class', $storage))
];
$storageDefinition = new Definition();
@@ -168,7 +169,7 @@ protected function buildTranslationStorageDefinition(ContainerBuilder $container
* @param string $driverId
* @param string $driverClass
*/
- protected function createDoctrineMappingDriver(ContainerBuilder $container, $driverId, $driverClass)
+ protected function createDoctrineMappingDriver(ContainerBuilder $container, $driverId, $driverClass): void
{
$driverDefinition = new Definition($driverClass, [
[dirname(__DIR__) . '/Resources/config/model' => 'Lexik\Bundle\TranslationBundle\Model'],
@@ -185,11 +186,11 @@ protected function createDoctrineMappingDriver(ContainerBuilder $container, $dri
* @param ContainerBuilder $container
* @param string $driverId
*/
- protected function createDoctrineAttributeDriver(ContainerBuilder $container, $driverId)
+ protected function createDoctrineAttributeDriver(ContainerBuilder $container, $driverId): void
{
// Calculate bundle path using ReflectionClass to get the actual bundle location
// This works even when the bundle is installed via Composer or symlinked
- $bundleReflection = new \ReflectionClass(\Lexik\Bundle\TranslationBundle\LexikTranslationBundle::class);
+ $bundleReflection = new \ReflectionClass(LexikTranslationBundle::class);
$bundleDir = dirname($bundleReflection->getFileName());
$modelPath = $bundleDir . '/Model';
@@ -213,7 +214,7 @@ protected function createDoctrineAttributeDriver(ContainerBuilder $container, $d
/**
* Load dev tools.
*/
- protected function buildDevServicesDefinition(ContainerBuilder $container)
+ protected function buildDevServicesDefinition(ContainerBuilder $container): void
{
$container
->getDefinition('lexik_translation.data_grid.request_handler')
@@ -225,103 +226,4 @@ protected function buildDevServicesDefinition(ContainerBuilder $container)
$container->setDefinition($container->getParameter('lexik_translation.token_finder.class'), $tokenFinderDefinition);
}
-
- /**
- * Register the "lexik_translation.translator" service configuration.
- */
- protected function registerTranslatorConfiguration(array $config, ContainerBuilder $container)
- {
- // use the Lexik translator decorator as default translator service
- $alias = $container->setAlias('translator', 'lexik_translation.translator');
- $alias->setPublic(true);
-
- // Get the inner translator (the actual Symfony translator) for adding resources
- // The decorator will delegate to it
- $innerTranslator = $container->hasDefinition('lexik_translation.translator.inner')
- ? $container->findDefinition('lexik_translation.translator.inner')
- : $container->findDefinition('translator');
-
- $innerTranslator->addMethodCall('setFallbackLocales', [$config['fallback_locale']]);
-
- // For adding file resources, we'll add them to the inner translator
- $translator = $innerTranslator;
-
- $registration = $config['resources_registration'];
-
- // Discover translation directories
- if ('all' === $registration['type'] || 'files' === $registration['type']) {
- $dirs = [];
-
- if (class_exists(Validation::class)) {
- $r = new \ReflectionClass(Validation::class);
-
- $dirs[] = dirname($r->getFilename()).'/Resources/translations';
- }
-
- if (class_exists(Form::class)) {
- $r = new \ReflectionClass(Form::class);
-
- $dirs[] = dirname($r->getFilename()).'/Resources/translations';
- }
-
- if (class_exists(AuthenticationException::class)) {
- $r = new \ReflectionClass(AuthenticationException::class);
-
- if (is_dir($dir = dirname($r->getFilename()).'/../Resources/translations')) {
- $dirs[] = $dir;
- }
- }
-
- $overridePath = $container->getParameter('kernel.project_dir').'/Resources/%s/translations';
-
- foreach ($container->getParameter('kernel.bundles') as $bundle => $class) {
- $reflection = new \ReflectionClass($class);
-
- if (is_dir($dir = dirname($reflection->getFilename()).'/Resources/translations')) {
- $dirs[] = $dir;
- }
-
- if (is_dir($dir = dirname($reflection->getFileName(), 2).'/translations')) {
- $dirs[] = $dir;
- }
-
- if (is_dir($dir = sprintf($overridePath, $bundle))) {
- $dirs[] = $dir;
- }
- }
-
- if (is_dir($dir = $container->getParameter('kernel.project_dir').'/Resources/translations')) {
- $dirs[] = $dir;
- }
-
- if (Kernel::MAJOR_VERSION >= 4 && is_dir($dir = $container->getParameter('kernel.project_dir').'/translations')) {
- $dirs[] = $dir;
- }
-
- // Register translation resources
- if (count($dirs) > 0) {
- foreach ($dirs as $dir) {
- $container->addResource(new DirectoryResource($dir));
- }
-
- $finder = Finder::create();
- $finder->files();
-
- if (true === $registration['managed_locales_only']) {
- // only look for managed locales
- $finder->name(sprintf('/(.*\.(%s)\.\w+$)/', implode('|', $config['managed_locales'])));
- } else {
- $finder->filter(fn(\SplFileInfo $file) => 2 === substr_count($file->getBasename(), '.') && preg_match('/\.\w+$/', $file->getBasename()));
- }
-
- $finder->in($dirs);
-
- foreach ($finder as $file) {
- // filename is domain.locale.format
- [$domain, $locale, $format] = explode('.', $file->getBasename(), 3);
- $translator->addMethodCall('addResource', [$format, (string) $file, $locale, $domain]);
- }
- }
- }
- }
}
diff --git a/Dockerfile b/Dockerfile
index 986dde95..7db9c737 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM php:8.3-cli-bullseye
+FROM php:8.4-cli-bullseye
ENV COMPOSER_ALLOW_SUPERUSER=1
@@ -21,8 +21,4 @@ COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /app
-COPY . .
-
-RUN composer install --prefer-dist --no-progress
-
CMD ["composer", "test"]
diff --git a/Document/File.php b/Document/File.php
index 806971ab..d57ca4a5 100644
--- a/Document/File.php
+++ b/Document/File.php
@@ -2,18 +2,14 @@
namespace Lexik\Bundle\TranslationBundle\Document;
-use Lexik\Bundle\TranslationBundle\Model\File as FileModel;
-use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
use DateTime;
+use Lexik\Bundle\TranslationBundle\Model\File as FileModel;
/**
* @author Cédric Girard
*/
-class File extends FileModel implements FileInterface
+class File extends FileModel
{
- /**
- * {@inheritdoc}
- */
public function prePersist(): void
{
$now = new DateTime("now");
@@ -22,9 +18,6 @@ public function prePersist(): void
$this->updatedAt = $now->format('U');
}
- /**
- * {@inheritdoc}
- */
public function preUpdate(): void
{
$now = new DateTime("now");
diff --git a/Document/TransUnit.php b/Document/TransUnit.php
index 0fc0b0f9..bec506cc 100644
--- a/Document/TransUnit.php
+++ b/Document/TransUnit.php
@@ -2,9 +2,8 @@
namespace Lexik\Bundle\TranslationBundle\Document;
-use Lexik\Bundle\TranslationBundle\Model\TransUnit as TransUnitModel;
use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
-use MongoTimestamp;
+use Lexik\Bundle\TranslationBundle\Model\TransUnit as TransUnitModel;
/**
* @author Cédric Girard
@@ -12,16 +11,10 @@
class TransUnit extends TransUnitModel implements TransUnitInterface
{
/**
- * Convert all MongoTimestamp object to time.
+ * @deprecated No longer needed since the legacy mongo extension is no longer supported.
*/
public function convertMongoTimestamp(): void
{
- $this->createdAt = ($this->createdAt instanceof MongoTimestamp) ? $this->createdAt->sec : $this->createdAt;
- $this->updatedAt = ($this->updatedAt instanceof MongoTimestamp) ? $this->updatedAt->sec : $this->updatedAt;
-
- foreach ($this->getTranslations() as $translation) {
- $translation->convertMongoTimestamp();
- }
}
/**
diff --git a/Document/TransUnitRepository.php b/Document/TransUnitRepository.php
index bb40979a..ac7639ea 100644
--- a/Document/TransUnitRepository.php
+++ b/Document/TransUnitRepository.php
@@ -4,7 +4,7 @@
use Doctrine\ODM\MongoDB\Query\Builder;
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
-use Lexik\Bundle\TranslationBundle\Model\File as ModelFile;
+use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
use MongoDB\BSON\ObjectId;
use MongoDB\BSON\Regex;
@@ -17,10 +17,8 @@ class TransUnitRepository extends DocumentRepository
{
/**
* Returns all domain available in database.
- *
- * @return array
*/
- public function getAllDomains()
+ public function getAllDomains(): array
{
$results = $this->createQueryBuilder()
->distinct('domain')
@@ -115,7 +113,7 @@ public function getAllDomainsByLocale(): array
}
}
- usort($domainsByLocale, function ($a, $b) {
+ usort($domainsByLocale, static function ($a, $b) {
$result = strcmp((string) $a['locale'], (string) $b['locale']);
if (0 === $result) {
$result = strcmp((string) $a['domain'], (string) $b['domain']);
@@ -133,7 +131,7 @@ public function getAllDomainsByLocale(): array
* @param string $domain
* @return array
*/
- public function getAllByLocaleAndDomain($locale, $domain)
+ public function getAllByLocaleAndDomain(string $locale, string $domain): array
{
$results = $this->createQueryBuilder()
->hydrate(false)
@@ -148,7 +146,7 @@ public function getAllByLocaleAndDomain($locale, $domain)
$i = 0;
$index = null;
while ($i < $item['translations'] && null === $index) {
- if ($item['translations'][$i]['locale'] == $locale) {
+ if ($item['translations'][$i]['locale'] === $locale) {
$index = $i;
}
$i++;
@@ -216,11 +214,15 @@ public function getTransUnitList(?array $locales = null, int $rows = 20, int $pa
/**
* Count the number of trans unit.
+ * @param array $criteria
*/
- public function count(?array $locales = null, ?array $filters = null): int
+ public function count(array $criteria = []): int
{
$builder = $this->createQueryBuilder();
+ $filters = $criteria['filters'] ?? null;
+ $locales = $criteria['locales'] ?? null;
+
$this->addTransUnitFilters($builder, $filters);
$this->addTranslationFilter($builder, $locales, $filters);
@@ -233,11 +235,8 @@ public function count(?array $locales = null, ?array $filters = null): int
/**
* Returns all translations for the given file.
- *
- * @param boolean $onlyUpdated
- * @return array
*/
- public function getTranslationsForFile(ModelFile $file, $onlyUpdated)
+ public function getTranslationsForFile(FileInterface $file, bool $onlyUpdated): array
{
$builder = $this->createQueryBuilder()
->hydrate(false)
@@ -252,12 +251,12 @@ public function getTranslationsForFile(ModelFile $file, $onlyUpdated)
$content = null;
$i = 0;
while ($i < (is_countable($result['translations']) ? count($result['translations']) : 0) && null === $content) {
- if ($file->getLocale() == $result['translations'][$i]['locale']) {
+ if ($file->getLocale() === $result['translations'][$i]['locale']) {
if ($onlyUpdated) {
// Handle MongoDB Timestamp objects - they have a 'sec' property
$createdAt = $result['translations'][$i]['createdAt'] ?? null;
$updatedAt = $result['translations'][$i]['updatedAt'] ?? null;
-
+
if ($createdAt && $updatedAt) {
$createdAtSec = \is_object($createdAt) && \property_exists($createdAt, 'sec') ? $createdAt->sec : $createdAt;
$updatedAtSec = \is_object($updatedAt) && \property_exists($updatedAt, 'sec') ? $updatedAt->sec : $updatedAt;
@@ -282,7 +281,7 @@ public function getTranslationsForFile(ModelFile $file, $onlyUpdated)
/**
* Add conditions according to given filters.
*/
- protected function addTransUnitFilters(Builder $builder, ?array $filters = null)
+ protected function addTransUnitFilters(Builder $builder, ?array $filters = null): void
{
if (isset($filters['_search']) && $filters['_search']) {
if (!empty($filters['domain'])) {
@@ -341,71 +340,53 @@ public function getLatestTranslationUpdatedAt()
->getQuery()
->getSingleResult();
- if (!isset($result['translations'], $result['translations'][0])) {
+ if (!isset($result['translations'][0])) {
return null;
}
return new \DateTime(date('Y-m-d H:i:s', $result['translations'][0]['updated_at']->sec));
}
- /**
- * @return array
- */
- public function countByDomains()
+ public function countByDomains(): array
{
- $reduce = <<createAggregationBuilder();
+ $results = $aggregationBuilder
+ ->group()
+ ->field('_id')->expression('$domain')
+ ->field('number')->sum(1)
+ ->execute();
- $results = $this->createQueryBuilder()
- ->group([],
- []) // @todo: group and reduce won't work anymore, but this method seems to be untested
- ->reduce($reduce)
- ->hydrate(false)
- ->getQuery()
- ->execute();
+ $counts = [];
+ foreach ($results as $row) {
+ $counts[] = [
+ 'domain' => $row['_id'],
+ 'number' => $row['number'],
+ ];
+ }
- return $results[0]['count'] ?? [];
+ return $counts;
}
- /**
- * @param string $domain
- * @return array
- */
- public function countTranslationsByLocales($domain)
+ public function countTranslationsByLocales(string $domain): array
{
- $reduce = <<createAggregationBuilder();
+ $results = $aggregationBuilder
+ ->match()
+ ->field('domain')->equals($domain)
+ ->unwind('$translations')
+ ->group()
+ ->field('_id')->expression('$translations.locale')
+ ->field('number')->sum(1)
+ ->execute();
- $results = $this->createQueryBuilder()
- ->field('domain')->equals($domain)
- ->group([], []) // @todo: won't work, untested
- ->reduce($reduce)
- ->hydrate(false)
- ->getQuery()
- ->execute();
+ $counts = [];
+ foreach ($results as $row) {
+ $counts[] = [
+ 'locale' => $row['_id'],
+ 'number' => $row['number'],
+ ];
+ }
- return $results[0]['count'] ?? [];
+ return $counts;
}
}
diff --git a/Document/Translation.php b/Document/Translation.php
index b7bd6b4a..1bc124da 100644
--- a/Document/Translation.php
+++ b/Document/Translation.php
@@ -2,8 +2,9 @@
namespace Lexik\Bundle\TranslationBundle\Document;
-use Lexik\Bundle\TranslationBundle\Model\Translation as TranslationModel;
+use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
use Lexik\Bundle\TranslationBundle\Manager\TranslationInterface;
+use Lexik\Bundle\TranslationBundle\Model\Translation as TranslationModel;
/**
* @author Cédric Girard
@@ -11,25 +12,13 @@
class Translation extends TranslationModel implements TranslationInterface
{
// Relationship mapping is defined in XML: Resources/config/doctrine/Translation.mongodb-odm.xml
- protected $file;
-
- public function setFile($file): void
- {
- $this->file = $file;
- }
-
- public function getFile()
- {
- return $this->file;
- }
+ protected ?FileInterface $file = null;
/**
- * Convert all MongoTimestamp object to time.
+ * @deprecated No longer needed since the legacy mongo extension is no longer supported.
*/
public function convertMongoTimestamp(): void
{
- $this->createdAt = ($this->createdAt instanceof \MongoTimestamp) ? $this->createdAt->sec : $this->createdAt;
- $this->updatedAt = ($this->updatedAt instanceof \MongoTimestamp) ? $this->updatedAt->sec : $this->updatedAt;
}
/**
diff --git a/Entity/File.php b/Entity/File.php
index 0f65c5ee..9c5fa7a7 100644
--- a/Entity/File.php
+++ b/Entity/File.php
@@ -6,7 +6,6 @@
use Doctrine\ORM\Mapping\HasLifecycleCallbacks;
use Doctrine\ORM\Mapping\PrePersist;
use Doctrine\ORM\Mapping\PreUpdate;
-use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
use Lexik\Bundle\TranslationBundle\Model\File as FileModel;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
@@ -15,7 +14,7 @@
*/
#[HasLifecycleCallbacks]
#[UniqueEntity(fields: ['hash'])]
-class File extends FileModel implements FileInterface
+class File extends FileModel
{
protected $id;
@@ -23,9 +22,6 @@ class File extends FileModel implements FileInterface
// Relationship mapping is defined in XML: Resources/config/doctrine/File.orm.xml
protected Collection $translations;
- /**
- * {@inheritdoc}
- */
#[PrePersist]
public function prePersist(): void
{
@@ -33,9 +29,6 @@ public function prePersist(): void
$this->updatedAt = new \DateTime("now");
}
- /**
- * {@inheritdoc}
- */
#[PreUpdate]
public function preUpdate(): void
{
diff --git a/Entity/TransUnit.php b/Entity/TransUnit.php
index b097fd2e..5b72be6b 100644
--- a/Entity/TransUnit.php
+++ b/Entity/TransUnit.php
@@ -2,15 +2,15 @@
namespace Lexik\Bundle\TranslationBundle\Entity;
+use DateTime;
+use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\HasLifecycleCallbacks;
use Doctrine\ORM\Mapping\PrePersist;
use Doctrine\ORM\Mapping\PreUpdate;
-use Lexik\Bundle\TranslationBundle\Entity\Translation;
+use Lexik\Bundle\TranslationBundle\Document\Translation as DocumentTranslation;
use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
use Lexik\Bundle\TranslationBundle\Model\TransUnit as TransUnitModel;
-use Lexik\Bundle\TranslationBundle\Document\Translation as DocumentTranslation;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
-use DateTime;
/**
* @author Cédric Girard
@@ -23,12 +23,10 @@ class TransUnit extends TransUnitModel implements TransUnitInterface
// translations property is inherited from TransUnitModel
// Relationship mapping is defined in XML: Resources/config/doctrine/TransUnit.orm.xml
- protected $translations;
+ protected Collection $translations;
/**
* Add translations
- *
- * @param \Lexik\Bundle\TranslationBundle\Entity\Translation $translations
*/
public function addTranslation(DocumentTranslation|Translation $translation): void
{
diff --git a/Entity/TransUnitRepository.php b/Entity/TransUnitRepository.php
index 277aa5f1..d272a19d 100644
--- a/Entity/TransUnitRepository.php
+++ b/Entity/TransUnitRepository.php
@@ -2,11 +2,10 @@
namespace Lexik\Bundle\TranslationBundle\Entity;
-use Lexik\Bundle\TranslationBundle\Util\Doctrine\SingleColumnArrayHydrator;
-use Doctrine\ORM\Query;
-use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\EntityRepository;
-use Lexik\Bundle\TranslationBundle\Model\File as ModelFile;
+use Doctrine\ORM\QueryBuilder;
+use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
+use Lexik\Bundle\TranslationBundle\Util\Doctrine\SingleColumnArrayHydrator;
/**
* Repository for TransUnit entity.
@@ -17,10 +16,8 @@ class TransUnitRepository extends EntityRepository
{
/**
* Returns all domain available in database.
- *
- * @return array
*/
- public function getAllDomainsByLocale()
+ public function getAllDomainsByLocale(): array
{
return $this->createQueryBuilder('tu')
->select('te.locale, tu.domain')
@@ -34,10 +31,8 @@ public function getAllDomainsByLocale()
/**
* Returns all domains for each locale.
- *
- * @return array
*/
- public function getAllByLocaleAndDomain($locale, $domain): mixed
+ public function getAllByLocaleAndDomain(string $locale, string $domain): array
{
return $this->createQueryBuilder('tu')
->select('tu, te')
@@ -68,12 +63,8 @@ public function getAllDomains(): mixed
/**
* Returns some trans units with their translations.
- *
- * @param int $rows
- * @param int $page
- * @return array
*/
- public function getTransUnitList(?array $locales = null, $rows = 20, $page = 1, ?array $filters = null): mixed
+ public function getTransUnitList(?array $locales = null, int $rows = 20, int $page = 1, ?array $filters = null): array
{
$this->loadCustomHydrator();
@@ -130,10 +121,7 @@ public function count(array $criteria = []): int
return (int) $builder->getQuery()->getSingleScalarResult();
}
- /**
- * @return array
- */
- public function countByDomains(): mixed
+ public function countByDomains(): array
{
return $this->createQueryBuilder('tu')
->select('COUNT(DISTINCT tu.id) AS number, tu.domain')
@@ -144,11 +132,8 @@ public function countByDomains(): mixed
/**
* Returns all translations for the given file.
- *
- * @param boolean $onlyUpdated
- * @return array
*/
- public function getTranslationsForFile(ModelFile $file, $onlyUpdated): array
+ public function getTranslationsForFile(FileInterface $file, bool $onlyUpdated): array
{
$builder = $this->createQueryBuilder('tu')
->select('tu.key, te.content')
diff --git a/Entity/Translation.php b/Entity/Translation.php
index 6c609059..8d05ec8b 100644
--- a/Entity/Translation.php
+++ b/Entity/Translation.php
@@ -2,14 +2,15 @@
namespace Lexik\Bundle\TranslationBundle\Entity;
+use DateTime;
use Doctrine\ORM\Mapping\HasLifecycleCallbacks;
use Doctrine\ORM\Mapping\PrePersist;
use Doctrine\ORM\Mapping\PreUpdate;
+use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
use Lexik\Bundle\TranslationBundle\Manager\TranslationInterface;
-use Lexik\Bundle\TranslationBundle\Model\TransUnit;
use Lexik\Bundle\TranslationBundle\Model\Translation as TranslationModel;
+use Lexik\Bundle\TranslationBundle\Model\TransUnit;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
-use DateTime;
/**
* @author Cédric Girard
@@ -23,17 +24,7 @@ class Translation extends TranslationModel implements TranslationInterface
// Relationship mappings are defined in XML: Resources/config/doctrine/Translation.orm.xml
protected $transUnit;
- protected $file;
-
- public function setFile($file): void
- {
- $this->file = $file;
- }
-
- public function getFile()
- {
- return $this->file;
- }
+ protected ?FileInterface $file = null;
// modifiedManually is inherited from TranslationModel
@@ -73,7 +64,7 @@ public function getTransUnit(): TransUnit
#[PrePersist]
public function prePersist(): void
{
- $now = new DateTime("now");
+ $now = new DateTime("now");
$this->createdAt = $now;
$this->updatedAt = $now;
}
diff --git a/Entity/TranslationRepository.php b/Entity/TranslationRepository.php
index 08e763d2..20567553 100644
--- a/Entity/TranslationRepository.php
+++ b/Entity/TranslationRepository.php
@@ -2,8 +2,8 @@
namespace Lexik\Bundle\TranslationBundle\Entity;
-use Doctrine\ORM\EntityRepository;
use Datetime;
+use Doctrine\ORM\EntityRepository;
/**
* Repository for Translation entity.
diff --git a/EventDispatcher/CleanTranslationCacheListener.php b/EventDispatcher/CleanTranslationCacheListener.php
index 1213559f..b6b0af4c 100644
--- a/EventDispatcher/CleanTranslationCacheListener.php
+++ b/EventDispatcher/CleanTranslationCacheListener.php
@@ -4,8 +4,8 @@
use Lexik\Bundle\TranslationBundle\Manager\LocaleManagerInterface;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
-use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Finder\Finder;
+use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
@@ -32,10 +32,10 @@ public function onKernelRequest(RequestEvent $event)
$finder = new Finder();
$finder->files()
- ->in($this->cacheDirectory.'/translations')
- ->date('< '.$lastUpdateTime->format('Y-m-d H:i:s'));
+ ->in($this->cacheDirectory . '/translations')
+ ->date('< ' . $lastUpdateTime->format('Y-m-d H:i:s'));
- if ($finder->count() > 0) {
+ if ($finder->count() > 0 && method_exists($this->translator, 'removeLocalesCacheFiles')) {
$this->translator->removeLocalesCacheFiles($this->localeManager->getLocales());
}
}
@@ -53,15 +53,15 @@ private function isCacheExpired()
return true;
}
- $cache_file = $this->cacheDirectory.'/translations/cache_timestamp';
- $cache_dir =$this->cacheDirectory.'/translations';
+ $cache_file = $this->cacheDirectory . '/translations/cache_timestamp';
+ $cache_dir = $this->cacheDirectory . '/translations';
if ('\\' === DIRECTORY_SEPARATOR) {
$cache_file = strtr($cache_file, '/', '\\');
$cache_dir = strtr($cache_dir, '/', '\\');
}
if (!\is_dir($cache_dir) && !\mkdir($cache_dir, 0777, true) && !\is_dir($cache_dir)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $cache_dir));
- }
+ }
if (!\file_exists($cache_file)) {
\touch($cache_file);
return true;
@@ -77,7 +77,7 @@ private function isCacheExpired()
private function checkCacheFolder()
{
- if (!is_dir($dirName = $this->cacheDirectory.'/translations') && !mkdir($dirName) && !is_dir($dirName)) {
+ if (!is_dir($dirName = $this->cacheDirectory . '/translations') && !mkdir($dirName) && !is_dir($dirName)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $dirName));
}
}
diff --git a/EventDispatcher/DatabaseResourcesListener.php b/EventDispatcher/DatabaseResourcesListener.php
deleted file mode 100644
index e0b27edb..00000000
--- a/EventDispatcher/DatabaseResourcesListener.php
+++ /dev/null
@@ -1,80 +0,0 @@
-
- */
-class DatabaseResourcesListener implements EventSubscriberInterface
-{
- private bool $resourcesAdded = false;
-
- public function __construct(
- #[Autowire(service: 'translator')]
- private readonly TranslatorInterface $translator,
- #[Autowire(service: 'Lexik\Bundle\TranslationBundle\Translation\Loader')]
- private readonly DatabaseLoader $databaseLoader,
- #[Autowire([
- 'resources_type' => '%lexik_translation.resources_type%'
- ])]
- private readonly array $options
- ) {
- }
-
- public static function getSubscribedEvents(): array
- {
- return [
- KernelEvents::REQUEST => ['addDatabaseResources', 10],
- ];
- }
-
- public function addDatabaseResources(RequestEvent $event): void
- {
- if ($this->resourcesAdded) {
- return;
- }
-
- $resourcesType = $this->options['resources_type'] ?? 'all';
- if ('all' !== $resourcesType && 'database' !== $resourcesType) {
- return;
- }
-
- // Get database resources via event
- $eventDispatcher = $event->getKernel()->getContainer()->get('event_dispatcher');
- $getResourcesEvent = new GetDatabaseResourcesEvent();
- $eventDispatcher->dispatch($getResourcesEvent);
-
- $resources = $getResourcesEvent->getResources();
-
- // Add resources to translator if it's our decorator
- if ($this->translator instanceof TranslatorDecorator) {
- $this->translator->addDatabaseResources();
- } elseif (method_exists($this->translator, 'addResource')) {
- // Fallback for direct translator access
- foreach ($resources as $resource) {
- $locale = $resource['locale'];
- $domain = $resource['domain'] ?? 'messages';
- $this->translator->addResource('database', 'DB', $locale, $domain);
- }
- }
- // Note: If neither works, the DatabaseLoader will still be called
- // automatically when translations are requested for a locale/domain
-
- $this->resourcesAdded = true;
- }
-}
diff --git a/EventDispatcher/GetDatabaseResourcesListener.php b/EventDispatcher/GetDatabaseResourcesListener.php
index 14cd70f6..6df69e25 100644
--- a/EventDispatcher/GetDatabaseResourcesListener.php
+++ b/EventDispatcher/GetDatabaseResourcesListener.php
@@ -3,6 +3,7 @@
namespace Lexik\Bundle\TranslationBundle\EventDispatcher;
use Lexik\Bundle\TranslationBundle\EventDispatcher\Event\GetDatabaseResourcesEvent;
+use Lexik\Bundle\TranslationBundle\Storage\DoctrineORMStorage;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
/**
@@ -19,10 +20,10 @@ public function __construct(
/**
* Query the database to get translation resources and set it on the event.
*/
- public function onGetDatabaseResources(GetDatabaseResourcesEvent $event)
+ public function onGetDatabaseResources(GetDatabaseResourcesEvent $event): void
{
// prevent errors on command such as cache:clear if doctrine schema has not been updated yet
- if (StorageInterface::STORAGE_ORM == $this->storageType && !$this->storage->translationsTablesExist()) {
+ if (StorageInterface::STORAGE_ORM === $this->storageType && $this->storage instanceof DoctrineORMStorage && !$this->storage->translationsTablesExist()) {
$resources = [];
} else {
$resources = $this->storage->getTransUnitDomainsByLocale();
diff --git a/Form/Handler/TransUnitFormHandler.php b/Form/Handler/TransUnitFormHandler.php
index 68bbc4f7..8e5272db 100644
--- a/Form/Handler/TransUnitFormHandler.php
+++ b/Form/Handler/TransUnitFormHandler.php
@@ -2,10 +2,10 @@
namespace Lexik\Bundle\TranslationBundle\Form\Handler;
-use Lexik\Bundle\TranslationBundle\Manager\LocaleManagerInterface;
-use Lexik\Bundle\TranslationBundle\Manager\TransUnitManagerInterface;
use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
use Lexik\Bundle\TranslationBundle\Manager\FileManagerInterface;
+use Lexik\Bundle\TranslationBundle\Manager\LocaleManagerInterface;
+use Lexik\Bundle\TranslationBundle\Manager\TransUnitManagerInterface;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
@@ -41,8 +41,8 @@ public function createFormData()
public function getFormOptions()
{
return [
- 'domains' => $this->storage->getTransUnitDomains(),
- 'data_class' => $this->storage->getModelClass('trans_unit'),
+ 'domains' => $this->storage->getTransUnitDomains(),
+ 'data_class' => $this->storage->getModelClass('trans_unit'),
'translation_class' => $this->storage->getModelClass('translation'),
];
}
diff --git a/Form/Type/TransUnitType.php b/Form/Type/TransUnitType.php
index 9f6cfc91..15cda4da 100644
--- a/Form/Type/TransUnitType.php
+++ b/Form/Type/TransUnitType.php
@@ -2,11 +2,11 @@
namespace Lexik\Bundle\TranslationBundle\Form\Type;
-use Symfony\Component\Form\Extension\Core\Type\TextType;
+use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
-use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -20,14 +20,14 @@ class TransUnitType extends AbstractType
/**
* {@inheritdoc}
*/
- public function buildForm(FormBuilderInterface $builder, array $options)
+ public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('key', TextType::class, ['label' => 'translations.key']);
- $builder->add('domain', ChoiceType::class, ['label' => 'translations.domain', 'choices' => array_merge(
+ $builder->add('domain', ChoiceType::class, ['label' => 'translations.domain', 'choices' => array_merge(
array_combine($options['default_domain'], $options['default_domain']),
array_combine($options['domains'], $options['domains'])
)]);
- $builder->add('translations', CollectionType::class, ['entry_type' => TranslationType::class, 'label' => 'translations.page_title', 'required' => false, 'entry_options' => ['data_class' => $options['translation_class']]]);
+ $builder->add('translations', CollectionType::class, ['entry_type' => TranslationType::class, 'label' => 'translations.page_title', 'required' => false, 'entry_options' => ['data_class' => $options['translation_class']]]);
$builder->add('save', SubmitType::class, ['label' => 'translations.save']);
$builder->add('save_add', SubmitType::class, ['label' => 'translations.save_add']);
}
@@ -35,15 +35,15 @@ public function buildForm(FormBuilderInterface $builder, array $options)
/**
* {@inheritdoc}
*/
- public function configureOptions(OptionsResolver $resolver)
+ public function configureOptions(OptionsResolver $resolver): void
{
- $resolver->setDefaults(['data_class' => null, 'default_domain' => ['messages'], 'domains' => [], 'translation_class' => null, 'translation_domain' => 'LexikTranslationBundle']);
+ $resolver->setDefaults(['data_class' => null, 'default_domain' => ['messages'], 'domains' => [], 'translation_class' => null, 'translation_domain' => 'LexikTranslationBundle']);
}
/**
* {@inheritdoc}
*/
- public function getName()
+ public function getName(): string
{
return $this->getBlockPrefix();
}
@@ -51,7 +51,7 @@ public function getName()
/**
* {@inheritdoc}
*/
- public function getBlockPrefix()
+ public function getBlockPrefix(): string
{
return 'lxk_trans_unit';
}
diff --git a/Form/Type/TranslationType.php b/Form/Type/TranslationType.php
index 2adb5a69..3c9c1ef6 100644
--- a/Form/Type/TranslationType.php
+++ b/Form/Type/TranslationType.php
@@ -6,8 +6,8 @@
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
-use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
+use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
@@ -20,7 +20,7 @@ class TranslationType extends AbstractType
/**
* {@inheritdoc}
*/
- public function buildForm(FormBuilderInterface $builder, array $options)
+ public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('locale', HiddenType::class);
$builder->add('content', TextareaType::class, ['required' => false]);
@@ -29,7 +29,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
/**
* {@inheritdoc}
*/
- public function buildView(FormView $view, FormInterface $form, array $options)
+ public function buildView(FormView $view, FormInterface $form, array $options): void
{
$view->vars['label'] = $form['locale']->getData();
}
@@ -37,15 +37,15 @@ public function buildView(FormView $view, FormInterface $form, array $options)
/**
* {@inheritdoc}
*/
- public function configureOptions(OptionsResolver $resolver)
+ public function configureOptions(OptionsResolver $resolver): void
{
- $resolver->setDefaults(['data_class' => null, 'translation_domain' => 'LexikTranslationBundle']);
+ $resolver->setDefaults(['data_class' => null, 'translation_domain' => 'LexikTranslationBundle']);
}
/**
* {@inheritdoc}
*/
- public function getName()
+ public function getName(): string
{
return $this->getBlockPrefix();
}
@@ -53,7 +53,7 @@ public function getName()
/**
* {@inheritdoc}
*/
- public function getBlockPrefix()
+ public function getBlockPrefix(): string
{
return 'lxk_translation';
}
diff --git a/Manager/FileInterface.php b/Manager/FileInterface.php
index 3f889c49..55b42e1f 100644
--- a/Manager/FileInterface.php
+++ b/Manager/FileInterface.php
@@ -2,8 +2,6 @@
namespace Lexik\Bundle\TranslationBundle\Manager;
-use Symfony\Component\HttpFoundation\File\File;
-
/**
* File interface.
*
@@ -11,4 +9,17 @@
*/
interface FileInterface
{
+ public function getId();
+ public function setDomain(string $domain): void;
+ public function getDomain(): string;
+ public function setLocale(string $locale): void;
+ public function getLocale(): string;
+ public function setExtention(string $extention): void;
+ public function getExtention(): string;
+ public function setPath(string $path): void;
+ public function getPath(): string;
+ public function setName(string $name): void;
+ public function getName(): string;
+ public function setHash(string $hash): void;
+ public function getHash(): string;
}
diff --git a/Manager/FileManager.php b/Manager/FileManager.php
index 743b4782..540411a0 100644
--- a/Manager/FileManager.php
+++ b/Manager/FileManager.php
@@ -12,21 +12,16 @@
*/
class FileManager implements FileManagerInterface
{
- /**
- * Construct.
- *
- * @param string $rootDir
- */
public function __construct(
private readonly StorageInterface $storage,
- private $rootDir,
+ private readonly string $rootDir,
) {
}
/**
* {@inheritdoc}
*/
- public function getFor($name, $path = null)
+ public function getFor(string $name, ?string $path = null): FileInterface
{
if (null === $path) {
$path = sprintf('%s/Resources/translations', $this->rootDir);
@@ -42,7 +37,7 @@ public function getFor($name, $path = null)
/**
* {@inheritdoc}
*/
- public function create($name, $path, $flush = false)
+ public function create(string $name, string $path, bool $flush = false): FileInterface
{
$path = $this->getFileRelativePath($path);
@@ -64,23 +59,16 @@ public function create($name, $path, $flush = false)
/**
* Returns the has for the given file.
- *
- * @param string $name
- * @param string $relativePath
- * @return string
*/
- protected function generateHash($name, $relativePath)
+ protected function generateHash(string $name, string $relativePath): string
{
return md5($relativePath . DIRECTORY_SEPARATOR . $name);
}
/**
* Returns the relative according to the kernel.root_dir value.
- *
- * @param string $filePath
- * @return string
*/
- protected function getFileRelativePath($filePath)
+ protected function getFileRelativePath(string $filePath): string
{
$commonParts = [];
@@ -98,7 +86,7 @@ protected function getFileRelativePath($filePath)
$i = 0;
while ($i < count($rootDirParts)) {
- if (isset($rootDirParts[$i], $filePathParts[$i]) && $rootDirParts[$i] == $filePathParts[$i]) {
+ if (isset($rootDirParts[$i], $filePathParts[$i]) && $rootDirParts[$i] === $filePathParts[$i]) {
$commonParts[] = $rootDirParts[$i];
}
$i++;
diff --git a/Manager/FileManagerInterface.php b/Manager/FileManagerInterface.php
index 4c66fc4c..b734f121 100644
--- a/Manager/FileManagerInterface.php
+++ b/Manager/FileManagerInterface.php
@@ -3,6 +3,7 @@
namespace Lexik\Bundle\TranslationBundle\Manager;
use Lexik\Bundle\TranslationBundle\Entity\File;
+
/**
* File manager interface.
*
@@ -12,20 +13,12 @@ interface FileManagerInterface
{
/**
* Create a new file.
- *
- * @param string $name
- * @param string $path
- * @return File
*/
- public function create($name, $path, $flush = false);
+ public function create(string $name, string $path, bool $flush = false): FileInterface;
/**
* Returns a translation file according to the given name and path.
* If path is null, app/Resources/translations will be used as default path.
- *
- * @param string $name
- * @param string $path
- * @return File
*/
- public function getFor($name, $path = null);
+ public function getFor(string $name, ?string $path = null): FileInterface;
}
diff --git a/Manager/LocaleManager.php b/Manager/LocaleManager.php
index 64eb8194..dcb5cad5 100644
--- a/Manager/LocaleManager.php
+++ b/Manager/LocaleManager.php
@@ -8,17 +8,14 @@
class LocaleManager implements LocaleManagerInterface
{
/**
- * Constructor
+ * @param list $managedLocales
*/
public function __construct(
protected array $managedLocales
) {
}
- /**
- * @return array
- */
- public function getLocales()
+ public function getLocales(): array
{
return $this->managedLocales;
}
diff --git a/Manager/TransUnitInterface.php b/Manager/TransUnitInterface.php
index a23c78aa..1a48b1a5 100644
--- a/Manager/TransUnitInterface.php
+++ b/Manager/TransUnitInterface.php
@@ -3,6 +3,9 @@
namespace Lexik\Bundle\TranslationBundle\Manager;
use Doctrine\Common\Collections\Collection;
+use Lexik\Bundle\TranslationBundle\Document\Translation as DocumentTranslation;
+use Lexik\Bundle\TranslationBundle\Entity\Translation;
+
/**
* TransUnit manager interface.
*
@@ -10,32 +13,23 @@
*/
interface TransUnitInterface
{
- /**
- * @return TranslationInterface[]
- */
- public function getTranslations(): array|Collection;
-
- /**
- * @param string $locale
- *
- * @return bool
- */
+ public function getId();
+
+ public function addTranslation(DocumentTranslation|Translation $translation): void;
+
+ public function removeTranslation(DocumentTranslation|Translation $translation): void;
+
+ public function getTranslations(): Collection;
+
public function hasTranslation(string $locale): bool;
- /**
- * @param string $locale
- *
- * @return TranslationInterface
- */
public function getTranslation(string $locale): ?TranslationInterface;
- /**
- * @param string $key
- */
public function setKey(string $key): void;
- /**
- * @param string $domain
- */
+ public function getKey(): string;
+
public function setDomain(string $domain): void;
+
+ public function getDomain(): string;
}
diff --git a/Manager/TransUnitManager.php b/Manager/TransUnitManager.php
index 8676787f..4fa82e83 100644
--- a/Manager/TransUnitManager.php
+++ b/Manager/TransUnitManager.php
@@ -4,7 +4,6 @@
use Lexik\Bundle\TranslationBundle\Model\Translation;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
-use Lexik\Bundle\TranslationBundle\Storage\PropelStorage;
/**
* Class to manage TransUnit entities or documents.
@@ -67,7 +66,7 @@ public function addTranslation(
$content,
?FileInterface $file = null,
bool $flush = false
- ): ?TranslationInterface{
+ ): ?TranslationInterface {
$translation = null;
if (!$transUnit->hasTranslation(locale: $locale)) {
$class = $this->storage->getModelClass(name: 'translation');
@@ -103,15 +102,15 @@ public function updateTranslation(TransUnitInterface $transUnit, $locale, $conte
$found = false;
while ($i < $end && !$found) {
- $found = ($transUnit->getTranslations()->get($i)->getLocale() == $locale);
+ $found = ($transUnit->getTranslations()->get($i)->getLocale() === $locale);
$i++;
}
if ($found) {
- /* @var Translation $translation */
+ /* @var TranslationInterface $translation */
$translation = $transUnit->getTranslations()->get($i - 1);
if ($merge) {
- if ($translation->isModifiedManually() || $translation->getContent() == $content) {
+ if ($translation->isModifiedManually() || $translation->getContent() === $content) {
return null;
}
@@ -127,10 +126,6 @@ public function updateTranslation(TransUnitInterface $transUnit, $locale, $conte
$translation->setContent($content);
}
- if (null !== $translation && $this->storage instanceof PropelStorage) {
- $this->storage->persist($translation);
- }
-
if ($flush) {
$this->storage->flush();
}
@@ -141,7 +136,7 @@ public function updateTranslation(TransUnitInterface $transUnit, $locale, $conte
/**
* {@inheritdoc}
*/
- public function updateTranslationsContent(TransUnitInterface $transUnit, array $translations, $flush = false): void
+ public function updateTranslationsContent(TransUnitInterface $transUnit, array $translations, $flush = false): void
{
foreach ($translations as $locale => $content) {
if (!empty($content)) {
@@ -153,11 +148,8 @@ public function updateTranslationsContent(TransUnitInterface $transUnit, array $
$originalContent = $translation->getContent();
$translation = $this->updateTranslation($transUnit, $locale, $content);
- $contentUpdated = ($translation->getContent() != $originalContent);
+ $contentUpdated = ($translation->getContent() !== $originalContent);
- if ($this->storage instanceof PropelStorage) {
- $this->storage->persist($transUnit);
- }
} else {
//We need to get a proper file for this translation
$file = $this->getTranslationFile($transUnit, $locale);
@@ -178,7 +170,7 @@ public function updateTranslationsContent(TransUnitInterface $transUnit, array $
/**
* Get the proper File for this TransUnit and locale
*/
- public function getTranslationFile(TransUnitInterface &$transUnit, string $locale)
+ public function getTranslationFile(TransUnitInterface $transUnit, string $locale)
{
$file = null;
foreach ($transUnit->getTranslations() as $translation) {
@@ -197,10 +189,7 @@ public function getTranslationFile(TransUnitInterface &$transUnit, string $local
return $file;
}
- /**
- * @return bool
- */
- public function delete(TransUnitInterface $transUnit)
+ public function delete(TransUnitInterface $transUnit): bool
{
try {
$this->storage->remove($transUnit);
@@ -213,11 +202,7 @@ public function delete(TransUnitInterface $transUnit)
}
}
- /**
- * @param string $locale
- * @return bool
- */
- public function deleteTranslation(TransUnitInterface $transUnit, $locale)
+ public function deleteTranslation(TransUnitInterface $transUnit, string $locale): bool
{
try {
$translation = $transUnit->getTranslation($locale);
diff --git a/Manager/TransUnitManagerInterface.php b/Manager/TransUnitManagerInterface.php
index ca6f8b95..8e4d88ae 100644
--- a/Manager/TransUnitManagerInterface.php
+++ b/Manager/TransUnitManagerInterface.php
@@ -48,12 +48,15 @@ public function addTranslation(TransUnitInterface $transUnit, $locale, $content,
* @param boolean $merge
* @return TranslationInterface
*/
- public function updateTranslation(TransUnitInterface $transUnit, $locale, $content, $flush = false, bool $merge = false): ?TranslationInterface;
+ public function updateTranslation(TransUnitInterface $transUnit, string $locale, $content, bool $flush = false, bool $merge = false): ?TranslationInterface;
/**
- * Update the content of each translations for the given trans unit.
- *
- * @param boolean $flush
+ * Update the content of each translation for the given trans unit.
*/
public function updateTranslationsContent(TransUnitInterface $transUnit, array $translations, bool $flush = false): void;
+
+ public function delete(TransUnitInterface $transUnit): bool;
+
+ public function deleteTranslation(TransUnitInterface $transUnit, string $locale): bool;
+
}
diff --git a/Model/File.php b/Model/File.php
index 9dbca1b8..24d2ea4b 100644
--- a/Model/File.php
+++ b/Model/File.php
@@ -6,6 +6,7 @@
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
+use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
@@ -14,7 +15,7 @@
* @author Cédric Girard
*/
#[ORM\MappedSuperclass]
-abstract class File
+abstract class File implements FileInterface
{
protected $id;
diff --git a/Model/TransUnit.php b/Model/TransUnit.php
index 3d6ba81f..d4e995c7 100644
--- a/Model/TransUnit.php
+++ b/Model/TransUnit.php
@@ -2,15 +2,15 @@
namespace Lexik\Bundle\TranslationBundle\Model;
-use Doctrine\Common\Collections\Collection;
+use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
+use Lexik\Bundle\TranslationBundle\Document\Translation as DocumentTranslation;
+use Lexik\Bundle\TranslationBundle\Entity\Translation;
use Lexik\Bundle\TranslationBundle\Manager\TranslationInterface;
use Symfony\Component\Validator\Constraints as Assert;
-use Lexik\Bundle\TranslationBundle\Entity\Translation;
-use Lexik\Bundle\TranslationBundle\Document\Translation as DocumentTranslation;
-use DateTime;
/**
* This class represent a trans unit which contain translations for a given domain and key.
@@ -34,9 +34,9 @@ abstract class TransUnit
protected string $domain;
/**
- * @var \Doctrine\Common\Collections\Collection
+ * @var Collection
*/
- protected $translations;
+ protected Collection $translations;
#[ORM\Column(name: 'created_at', type: Types::DATETIME_MUTABLE, nullable: true)]
protected DateTime|string $createdAt;
@@ -105,8 +105,6 @@ public function getDomain(): string
/**
* Add translations
- *
- * @param Translation $translations
*/
public function addTranslation(DocumentTranslation|Translation $translation): void
{
@@ -115,8 +113,6 @@ public function addTranslation(DocumentTranslation|Translation $translation): vo
/**
* Remove translations
- *
- * @param Translation $translations
*/
public function removeTranslation(DocumentTranslation|Translation $translation): void
{
@@ -125,10 +121,8 @@ public function removeTranslation(DocumentTranslation|Translation $translation):
/**
* Get translations
- *
- * @return \Doctrine\Common\Collections\Collection
*/
- public function getTranslations(): array|Collection
+ public function getTranslations(): Collection
{
return $this->translations;
}
@@ -146,13 +140,11 @@ public function hasTranslation(string $locale): bool
/**
* Return the content of translation for the given locale.
- *
- * @param string $locale
*/
public function getTranslation(string $locale): ?TranslationInterface
{
foreach ($this->getTranslations() as $translation) {
- if ($translation->getLocale() == $locale) {
+ if ($translation->getLocale() === $locale) {
return $translation;
}
}
@@ -173,9 +165,9 @@ public function setTranslations(Collection $collection): void
}
/**
- * Return transaltions with not blank content.
+ * Return translations with not blank content.
*
- * @return \Doctrine\Common\Collections\Collection
+ * @return Collection
*/
public function filterNotBlankTranslations(): Collection
{
diff --git a/Model/Translation.php b/Model/Translation.php
index bd529f32..b0b842d7 100644
--- a/Model/Translation.php
+++ b/Model/Translation.php
@@ -2,9 +2,10 @@
namespace Lexik\Bundle\TranslationBundle\Model;
+use DateTime;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
-use DateTime;
+use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
@@ -17,7 +18,7 @@ abstract class Translation
{
#[ORM\Column(name: 'locale', type: Types::STRING, length: 10)]
#[Assert\NotBlank]
- protected $locale;
+ protected string $locale;
#[ORM\Column(name: 'content', type: Types::TEXT, nullable: true)]
#[Assert\NotBlank(groups: ['contentNotBlank'])]
@@ -29,18 +30,15 @@ abstract class Translation
#[ORM\Column(name: 'updated_at', type: Types::DATETIME_MUTABLE, nullable: true)]
protected $updatedAt;
- /**
- * @var boolean
- */
- #[ORM\Column(name: 'modified_manually', type: Types::BOOLEAN, nullable: true)]
- protected $modifiedManually = false;
+ #[ORM\Column(name: 'modified_manually', type: Types::BOOLEAN, options: ['default' => false])]
+ protected bool $modifiedManually = false;
+
+ protected ?FileInterface $file = null;
/**
* Set locale
- *
- * @param string $locale
*/
- public function setLocale($locale)
+ public function setLocale(string $locale): void
{
$this->locale = $locale;
$this->content = '';
@@ -48,10 +46,8 @@ public function setLocale($locale)
/**
* Get locale
- *
- * @return string
*/
- public function getLocale()
+ public function getLocale(): string
{
return $this->locale;
}
@@ -76,7 +72,6 @@ public function getContent()
return $this->content;
}
-
/**
* Get createdAt
*
@@ -97,19 +92,23 @@ public function getUpdatedAt()
return $this->updatedAt;
}
- /**
- * @return bool
- */
- public function isModifiedManually()
+ public function isModifiedManually(): bool
{
return $this->modifiedManually;
}
- /**
- * @param bool $modifiedManually
- */
- public function setModifiedManually($modifiedManually)
+ public function setModifiedManually(bool $modifiedManually): void
{
$this->modifiedManually = $modifiedManually;
}
+
+ public function setFile(FileInterface $file): void
+ {
+ $this->file = $file;
+ }
+
+ public function getFile(): ?FileInterface
+ {
+ return $this->file;
+ }
}
diff --git a/Resources/config/services.yaml b/Resources/config/services.yaml
index 3219ba58..28f83d47 100644
--- a/Resources/config/services.yaml
+++ b/Resources/config/services.yaml
@@ -51,38 +51,27 @@ services:
# Translator
lexik_translation.translator:
class: Lexik\Bundle\TranslationBundle\Translation\Translator
+ decorates: 'translator'
+ decoration_on_invalid: ignore
arguments:
+ $translator: '@.inner'
$container: '@service_container'
- $formatter: '@translator.formatter.default'
- $defaultLocale: '%kernel.default_locale%'
$loaderIds: []
$options:
cache_dir: '%kernel.cache_dir%/translations'
debug: '%kernel.debug%'
- resource_files: []
- scanned_directories: []
- cache_vary: []
resources_type: '%lexik_translation.resources_type%'
- calls:
- - [setConfigCacheFactory, ['@config_cache_factory']]
- tags:
- - { name: kernel.locale_aware }
public: true
Lexik\Bundle\TranslationBundle\Translation\Translator:
alias: lexik_translation.translator
public: true
- # TranslatorDecorator alias for backward compatibility
- Lexik\Bundle\TranslationBundle\Translation\TranslatorDecorator:
- alias: lexik_translation.translator
- public: true
-
Lexik\Bundle\TranslationBundle\Storage\StorageInterface:
alias: lexik_translation.translation_storage
# Loader
- Lexik\Bundle\TranslationBundle\Translation\Loader:
+ Lexik\Bundle\TranslationBundle\Translation\Loader\DatabaseLoader:
class: '%lexik_translation.loader.database.class%'
arguments:
- '@lexik_translation.translation_storage'
diff --git a/Resources/doc/index.md b/Resources/doc/index.md
index bb1e6c5b..187fca74 100644
--- a/Resources/doc/index.md
+++ b/Resources/doc/index.md
@@ -52,13 +52,29 @@ Configuration
#### Minimum configuration
-You must at least define the fallback locale(s) as for the `framework.translator` node, and define all locales you will manage.
+The bundle decorates the Symfony Translator service instead of extending it. This means the bundle now leverages the standard Symfony translator configuration. As a result, `fallback_locale` and `managed_locales` are no longer required:
+
+- `fallback_locale` is **deprecated**. Use `framework.translator.fallbacks` instead.
+- `managed_locales` is now **optional**. If not set, it falls back to `framework.enabled_locales`.
+
+**Minimal setup** — the bundle works with no specific configuration if your `framework` config already defines `enabled_locales` and `translator.fallbacks`:
+
+```yml
+# config/packages/framework.yaml
+framework:
+ default_locale: en
+ enabled_locales: [en, fr, de]
+ translator:
+ fallbacks: [en]
+```
+
+**Legacy setup** — for backward compatibility, you can still use the bundle's own options. They will override the framework values:
```yml
-# app/config/config.yml
+# config/packages/lexik_translation.yaml
lexik_translation:
- fallback_locale: [en] # (required) default locale(s) to use
- managed_locales: [en, fr, de] # (required) locales that the bundle has to manage
+ fallback_locale: [en] # (deprecated) use framework.translator.fallbacks instead
+ managed_locales: [en, fr, de] # (optional) falls back to framework.enabled_locales
```
#### Additional configuration options
diff --git a/Storage/AbstractDoctrineStorage.php b/Storage/AbstractDoctrineStorage.php
index 73c32ad4..d04ad6c3 100644
--- a/Storage/AbstractDoctrineStorage.php
+++ b/Storage/AbstractDoctrineStorage.php
@@ -3,11 +3,12 @@
namespace Lexik\Bundle\TranslationBundle\Storage;
use Doctrine\Persistence\ObjectManager;
-use Symfony\Bridge\Doctrine\ManagerRegistry;
-use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
-use Lexik\Bundle\TranslationBundle\Entity\TransUnitRepository;
-use Lexik\Bundle\TranslationBundle\Entity\FileRepository;
use Lexik\Bundle\TranslationBundle\Document\FileRepository as DocumentFileRepository;
+use Lexik\Bundle\TranslationBundle\Document\TransUnitRepository as DocumentTransUnitRepository;
+use Lexik\Bundle\TranslationBundle\Entity\FileRepository;
+use Lexik\Bundle\TranslationBundle\Entity\TransUnitRepository;
+use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
+use Symfony\Bridge\Doctrine\ManagerRegistry;
/**
* Common doctrine storage logic.
@@ -30,22 +31,24 @@ protected function getManager(): ObjectManager
/**
* Returns the TransUnit repository.
- *
- * @return object
*/
- protected function getTransUnitRepository(): TransUnitRepository
+ protected function getTransUnitRepository(): TransUnitRepository|DocumentTransUnitRepository
{
- return $this->getManager()->getRepository($this->classes['trans_unit']);
+ /** @var TransUnitRepository|DocumentTransUnitRepository $repository */
+ $repository = $this->getManager()->getRepository($this->classes['trans_unit']);
+
+ return $repository;
}
/**
* Returns the File repository.
- *
- * @return object
*/
protected function getFileRepository(): FileRepository|DocumentFileRepository
{
- return $this->getManager()->getRepository($this->classes['file']);
+ /** @var FileRepository|DocumentFileRepository $repository */
+ $repository = $this->getManager()->getRepository($this->classes['file']);
+
+ return $repository;
}
/**
@@ -75,9 +78,9 @@ public function flush($entity = null): void
/**
* {@inheritdoc}
*/
- public function clear($entityName = null): void
+ public function clear(): void
{
- $this->getManager()->clear($entityName);
+ $this->getManager()->clear();
}
/**
@@ -121,22 +124,18 @@ public function getTransUnitDomains(): mixed
*/
public function getTransUnitById($id): ?TransUnitInterface
{
- return $this->getTransUnitRepository()->findOneById($id);
+ return $this->getTransUnitRepository()->find($id);
}
/**
* Returns a TransUnit by its key and domain.
- *
- * @param string $key
- * @param string $domain
- * @return TransUnitInterface
*/
public function getTransUnitByKeyAndDomain(string $key, string $domain): ?TransUnitInterface
{
$key = mb_substr($key, 0, 255, 'UTF-8');
$fields = [
- 'key' => $key,
+ 'key' => $key,
'domain' => $domain,
];
@@ -146,7 +145,7 @@ public function getTransUnitByKeyAndDomain(string $key, string $domain): ?TransU
/**
* {@inheritdoc}
*/
- public function getTransUnitDomainsByLocale()
+ public function getTransUnitDomainsByLocale(): array
{
return $this->getTransUnitRepository()->getAllDomainsByLocale();
}
diff --git a/Storage/DoctrineMongoDBStorage.php b/Storage/DoctrineMongoDBStorage.php
index 33de8881..cac72ba7 100644
--- a/Storage/DoctrineMongoDBStorage.php
+++ b/Storage/DoctrineMongoDBStorage.php
@@ -1,6 +1,7 @@
getTransUnitRepository()->countByDomains();
}
@@ -29,7 +30,7 @@ public function getCountTransUnitByDomains(): array
/**
* {@inheritdoc}
*/
- public function getCountTranslationByLocales(string $domain):array
+ public function getCountTranslationByLocales(string $domain): array
{
return $this->getTransUnitRepository()->countTranslationsByLocales($domain);
}
diff --git a/Storage/DoctrineORMStorage.php b/Storage/DoctrineORMStorage.php
index 038d467b..ab16d135 100644
--- a/Storage/DoctrineORMStorage.php
+++ b/Storage/DoctrineORMStorage.php
@@ -2,13 +2,8 @@
namespace Lexik\Bundle\TranslationBundle\Storage;
-use Doctrine\DBAL\DriverManager;
-use Doctrine\DBAL\Driver\PDO\SQLite\Driver as SQLiteDriver;
-use Doctrine\DBAL\Exception\ConnectionException;
-use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory;
-use Doctrine\ORM\Configuration;
-use Doctrine\ORM\EntityManager;
use DateTime;
+use Doctrine\ORM\EntityManager;
/**
* Doctrine ORM storage class.
@@ -19,58 +14,22 @@ class DoctrineORMStorage extends AbstractDoctrineStorage
{
/**
* Returns true if translation tables exist.
- *
- * @return boolean
*/
- public function translationsTablesExist()
+ public function translationsTablesExist(): bool
{
/** @var EntityManager $em */
$em = $this->getManager();
- $connection = $em->getConnection();
-
- // listDatabases() is not available for SQLite
- if (!$connection->getDriver() instanceof SQLiteDriver) {
- // init a tmp connection without dbname/path/url in case it does not exist yet
- $params = $connection->getParams();
- if (isset($params['master'])) {
- $params = $params['master'];
- }
-
- unset($params['dbname'], $params['path'], $params['url']);
- try {
- $configuration = new Configuration();
- if (class_exists(DefaultSchemaManagerFactory::class)) {
- $configuration->setSchemaManagerFactory(new DefaultSchemaManagerFactory());
- }
+ try {
+ $tables = [
+ $em->getClassMetadata($this->getModelClass('trans_unit'))->getTableName(),
+ $em->getClassMetadata($this->getModelClass('translation'))->getTableName(),
+ ];
- $tmpConnection = DriverManager::getConnection($params, $configuration);
- $schemaManager = method_exists($tmpConnection, 'createSchemaManager')
- ? $tmpConnection->createSchemaManager()
- : $tmpConnection->getSchemaManager();
-
- $dbExists = in_array($connection->getDatabase(), $schemaManager->listDatabases());
- $tmpConnection->close();
- } catch (ConnectionException|\Exception) {
- $dbExists = false;
- }
-
- if (!$dbExists) {
- return false;
- }
+ return $em->getConnection()->createSchemaManager()->tablesExist($tables);
+ } catch (\Exception) {
+ return false;
}
-
- // checks tables exist
- $tables = [
- $em->getClassMetadata($this->getModelClass('trans_unit'))->getTableName(),
- $em->getClassMetadata($this->getModelClass('translation'))->getTableName(),
- ];
-
- $schemaManager = method_exists($connection, 'createSchemaManager')
- ? $connection->createSchemaManager()
- : $connection->getSchemaManager();
-
- return $schemaManager->tablesExist($tables);
}
/**
diff --git a/Storage/Listener/DoctrineORMListener.php b/Storage/Listener/DoctrineORMListener.php
index a18ab6f3..c95052b0 100644
--- a/Storage/Listener/DoctrineORMListener.php
+++ b/Storage/Listener/DoctrineORMListener.php
@@ -3,11 +3,11 @@
namespace Lexik\Bundle\TranslationBundle\Storage\Listener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
-use Doctrine\ORM\Mapping\ClassMetadataInfo;
+use Doctrine\ORM\Mapping\ClassMetadata;
class DoctrineORMListener
{
- public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
+ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs): void
{
$params = $eventArgs->getEntityManager()->getConnection()->getParams();
@@ -15,10 +15,10 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
return;
}
- /** @var ClassMetadataInfo $metadata */
+ /** @var ClassMetadata $metadata */
$metadata = $eventArgs->getClassMetadata();
- if (!str_contains((string) $metadata->getName(), 'TranslationBundle')) {
+ if (!str_contains($metadata->getName(), 'TranslationBundle')) {
return;
}
diff --git a/Storage/StorageInterface.php b/Storage/StorageInterface.php
index dcd5ee53..9514289b 100644
--- a/Storage/StorageInterface.php
+++ b/Storage/StorageInterface.php
@@ -2,9 +2,9 @@
namespace Lexik\Bundle\TranslationBundle\Storage;
-use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
use DateTime;
use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
+use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
/**
* Translation storage interface.
@@ -16,7 +16,7 @@ interface StorageInterface
/**
* All the available config storage types.
*/
- public const STORAGE_ORM = 'orm';
+ public const STORAGE_ORM = 'orm';
public const STORAGE_MONGODB = 'mongodb';
/**
@@ -42,10 +42,8 @@ public function flush($entity = null);
/**
* Clear managed objects.
- *
- * @param string $entityName
*/
- public function clear($entityName = null);
+ public function clear(): void;
/**
* Returns the class's namespace according to the given name.
@@ -122,7 +120,7 @@ public function getTransUnitList(?array $locales = null, ?int $rows = 20, ?int $
*
* @return int
*/
- public function countTransUnits(?array $locales = null, ?array $filters = null): int;
+ public function countTransUnits(?array $locales = null, ?array $filters = null): int;
/**
* Returns all translations for the given file.
diff --git a/Tests/Command/ImportTranslationsCommandTest.php b/Tests/Command/ImportTranslationsCommandTest.php
index 24e46e4c..be0107ef 100644
--- a/Tests/Command/ImportTranslationsCommandTest.php
+++ b/Tests/Command/ImportTranslationsCommandTest.php
@@ -2,17 +2,15 @@
namespace Lexik\Bundle\TranslationBundle\Tests\Command;
-use Doctrine\ORM\Tools\Console\EntityManagerProvider\SingleManagerProvider;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Console\Command\SchemaTool\CreateCommand;
use Doctrine\ORM\Tools\Console\Command\SchemaTool\DropCommand;
-use Lexik\Bundle\TranslationBundle\Manager\LocaleManagerInterface;
-use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+use Doctrine\ORM\Tools\Console\EntityManagerProvider\SingleManagerProvider;
use Symfony\Bundle\FrameworkBundle\Console\Application;
+use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Tester\CommandTester;
-use Lexik\Bundle\TranslationBundle\Command\ImportTranslationsCommand;
/**
* Test the translations import command, with option and arguments
@@ -48,8 +46,8 @@ public function setUp(): void
*/
private static function addDoctrineCommands(DropCommand $dropCommand, CreateCommand $createCommand)
{
- static::$application->add($dropCommand);
- static::$application->add($createCommand);
+ static::$application->addCommand($dropCommand);
+ static::$application->addCommand($createCommand);
}
/**
@@ -81,27 +79,18 @@ private static function runCommand($commandName, $options = [])
*
* @group command
*/
- public function testExecute()
+ public function testExecute(): void
{
- $container = self::$kernel->getContainer();
- static::$application->add(
- command: new ImportTranslationsCommand(
- translator: $container->get('lexik_translation.translator'),
- localeManager: $container->get(LocaleManagerInterface::class),
- fileImporter: $container->get('lexik_translation.importer.file')
- )
- );
-
$command = static::$application->find("lexik:translations:import");
$commandTester = new CommandTester($command);
$commandTester->execute(
[
- 'command' => $command->getName(),
- 'bundle' => 'LexikTranslationBundle',
+ 'command' => $command->getName(),
+ 'bundle' => 'LexikTranslationBundle',
'--cache-clear' => true,
- '--force' => true,
- '--locales' => ['en', 'fr'],
+ '--force' => true,
+ '--locales' => ['en', 'fr'],
]
);
diff --git a/Tests/Fixtures/test.fr.php b/Tests/Fixtures/test.fr.php
index a4293d56..238b9d4d 100644
--- a/Tests/Fixtures/test.fr.php
+++ b/Tests/Fixtures/test.fr.php
@@ -1,5 +1,6 @@
'Hey mec :D',
+ 'key.dude' => 'Hey mec :D',
'key.stuff' => 'Truc cool',
];
diff --git a/Tests/Unit/BaseUnitTestCase.php b/Tests/Unit/BaseUnitTestCase.php
index 88a9eb55..b2b2cc4c 100644
--- a/Tests/Unit/BaseUnitTestCase.php
+++ b/Tests/Unit/BaseUnitTestCase.php
@@ -2,23 +2,23 @@
namespace Lexik\Bundle\TranslationBundle\Tests\Unit;
-use Doctrine\DBAL\DriverManager;
-use Doctrine\ODM\MongoDB\Mapping\Driver\SimplifiedXmlDriver as XmlDriver;
use Doctrine\Common\DataFixtures\Executor\MongoDBExecutor;
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Purger\MongoDBPurger;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
+use Doctrine\DBAL\DriverManager;
use Doctrine\ODM\MongoDB\Configuration;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
+use Doctrine\ODM\MongoDB\Mapping\Driver\SimplifiedXmlDriver as XmlDriver;
use Doctrine\ODM\MongoDB\MongoDBException;
use Doctrine\ODM\MongoDB\SchemaManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Mapping\ClassMetadataFactory as DoctrineClassMetadataFactory;
use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver;
-use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\ORM\ORMSetup as Setup;
+use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\Persistence\ObjectManager;
use Lexik\Bundle\TranslationBundle\Storage\DoctrineMongoDBStorage;
use Lexik\Bundle\TranslationBundle\Storage\DoctrineORMStorage;
@@ -37,13 +37,13 @@
*/
abstract class BaseUnitTestCase extends TestCase
{
- final const ENTITY_TRANS_UNIT_CLASS = 'Lexik\Bundle\TranslationBundle\Entity\TransUnit';
- final const ENTITY_TRANSLATION_CLASS = 'Lexik\Bundle\TranslationBundle\Entity\Translation';
- final const ENTITY_FILE_CLASS = 'Lexik\Bundle\TranslationBundle\Entity\File';
+ final public const ENTITY_TRANS_UNIT_CLASS = 'Lexik\Bundle\TranslationBundle\Entity\TransUnit';
+ final public const ENTITY_TRANSLATION_CLASS = 'Lexik\Bundle\TranslationBundle\Entity\Translation';
+ final public const ENTITY_FILE_CLASS = 'Lexik\Bundle\TranslationBundle\Entity\File';
- final const DOCUMENT_TRANS_UNIT_CLASS = 'Lexik\Bundle\TranslationBundle\Document\TransUnit';
- final const DOCUMENT_TRANSLATION_CLASS = 'Lexik\Bundle\TranslationBundle\Document\Translation';
- final const DOCUMENT_FILE_CLASS = 'Lexik\Bundle\TranslationBundle\Document\File';
+ final public const DOCUMENT_TRANS_UNIT_CLASS = 'Lexik\Bundle\TranslationBundle\Document\TransUnit';
+ final public const DOCUMENT_TRANSLATION_CLASS = 'Lexik\Bundle\TranslationBundle\Document\Translation';
+ final public const DOCUMENT_FILE_CLASS = 'Lexik\Bundle\TranslationBundle\Document\File';
/**
* Create a storage class form doctrine ORM.
@@ -55,9 +55,9 @@ protected function getORMStorage(EntityManager $em)
$registryMock = $this->getDoctrineRegistryMock($em);
$storage = new DoctrineORMStorage($registryMock, 'default', [
- 'trans_unit' => self::ENTITY_TRANS_UNIT_CLASS,
+ 'trans_unit' => self::ENTITY_TRANS_UNIT_CLASS,
'translation' => self::ENTITY_TRANSLATION_CLASS,
- 'file' => self::ENTITY_FILE_CLASS,
+ 'file' => self::ENTITY_FILE_CLASS,
]);
return $storage;
@@ -71,9 +71,9 @@ protected function getMongoDBStorage(DocumentManager $dm): DoctrineMongoDBStorag
$registryMock = $this->getDoctrineRegistryMock($dm);
$storage = new DoctrineMongoDBStorage($registryMock, 'default', [
- 'trans_unit' => self::DOCUMENT_TRANS_UNIT_CLASS,
+ 'trans_unit' => self::DOCUMENT_TRANS_UNIT_CLASS,
'translation' => self::DOCUMENT_TRANSLATION_CLASS,
- 'file' => self::DOCUMENT_FILE_CLASS,
+ 'file' => self::DOCUMENT_FILE_CLASS,
]);
return $storage;
@@ -152,7 +152,7 @@ protected function getMockSqliteEntityManager($mockCustomHydrator = false)
// xml driver
$xmlDriver = new SimplifiedXmlDriver(
[
- __DIR__ . '/../../Resources/config/model' => 'Lexik\Bundle\TranslationBundle\Model',
+ __DIR__ . '/../../Resources/config/model' => 'Lexik\Bundle\TranslationBundle\Model',
__DIR__ . '/../../Resources/config/doctrine' => 'Lexik\Bundle\TranslationBundle\Entity',
]
);
@@ -161,7 +161,10 @@ protected function getMockSqliteEntityManager($mockCustomHydrator = false)
[
__DIR__ . '/../../Model',
__DIR__ . '/../../Entity',
- ], false, null, null
+ ],
+ false,
+ null,
+ null
);
$config->setMetadataDriverImpl($xmlDriver);
@@ -201,7 +204,7 @@ protected function getMockSqliteEntityManager($mockCustomHydrator = false)
protected function getMockMongoDbDocumentManager(): DocumentManager
{
$prefixes = [
- __DIR__ . '/../../Resources/config/model' => 'Lexik\Bundle\TranslationBundle\Model',
+ __DIR__ . '/../../Resources/config/model' => 'Lexik\Bundle\TranslationBundle\Model',
__DIR__ . '/../../Resources/config/doctrine' => 'Lexik\Bundle\TranslationBundle\Document',
];
$xmlDriver = new XmlDriver($prefixes);
@@ -224,7 +227,7 @@ protected function getMockMongoDbDocumentManager(): DocumentManager
$server = MONGO_SERVER;
$driverOptions = [
'typeMap' => [
- 'root' => 'array',
+ 'root' => 'array',
'document' => 'array',
],
];
@@ -232,7 +235,6 @@ protected function getMockMongoDbDocumentManager(): DocumentManager
$dm = DocumentManager::create($conn, $config);
-
return $dm;
}
}
diff --git a/Tests/Unit/EventDispatcher/CleanTranslationCacheListenerTest.php b/Tests/Unit/EventDispatcher/CleanTranslationCacheListenerTest.php
index 6d380437..1ca31eed 100644
--- a/Tests/Unit/EventDispatcher/CleanTranslationCacheListenerTest.php
+++ b/Tests/Unit/EventDispatcher/CleanTranslationCacheListenerTest.php
@@ -2,16 +2,16 @@
namespace Lexik\Bundle\TranslationBundle\Tests\Unit\EventDispatcher;
+use Lexik\Bundle\TranslationBundle\EventDispatcher\CleanTranslationCacheListener;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
use Lexik\Bundle\TranslationBundle\Translation\Translator;
-use Lexik\Bundle\TranslationBundle\EventDispatcher\CleanTranslationCacheListener;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Translation\MessageSelector;
-use Symfony\Component\Finder\Finder;
-use PHPUnit\Framework\TestCase;
/**
* Unit test for CleanTranslationCacheListener class
@@ -20,7 +20,6 @@
*/
class CleanTranslationCacheListenerTest extends TestCase
{
-
private $tempDir;
public function setUp(): void
@@ -32,7 +31,7 @@ public function testDefaultLocale()
{
$request = Request::create('/');
- $date = new \DateTime;
+ $date = new \DateTime();
if (!\file_exists($this->tempDir)) {
\mkdir($this->tempDir);
@@ -49,7 +48,7 @@ public function testDefaultLocale()
$container = $this->getMock(ContainerInterface::class);
- $translator = $this->getMock(Translator::class, [], [$container, new MessageSelector]);
+ $translator = $this->getMock(Translator::class, [], [$container, new MessageSelector()]);
$translator->expects($this->any())->method('removeLocalesCacheFiles')->will($this->returnValue(true));
diff --git a/Tests/Unit/Repository/Document/FileRepositoryTest.php b/Tests/Unit/Repository/Document/FileRepositoryTest.php
index 3d6bffc0..9f431376 100644
--- a/Tests/Unit/Repository/Document/FileRepositoryTest.php
+++ b/Tests/Unit/Repository/Document/FileRepositoryTest.php
@@ -52,7 +52,7 @@ public function assertFilesPath($expected, $result)
{
$i = 0;
foreach ($result as $file) {
- $this->assertEquals($expected[$i], $file->getPath().'/'.$file->getName());
+ $this->assertEquals($expected[$i], $file->getPath() . '/' . $file->getName());
$i++;
}
}
diff --git a/Tests/Unit/Repository/Document/TransUnitRepositoryTest.php b/Tests/Unit/Repository/Document/TransUnitRepositoryTest.php
index 0b37f883..9d10ec88 100644
--- a/Tests/Unit/Repository/Document/TransUnitRepositoryTest.php
+++ b/Tests/Unit/Repository/Document/TransUnitRepositoryTest.php
@@ -93,16 +93,20 @@ public function testCount()
$dm = $this->loadDatabase();
$repository = $dm->getRepository(self::DOCUMENT_TRANS_UNIT_CLASS);
- $this->assertEquals(3, $repository->count(null, []));
- $this->assertEquals(3, $repository->count(['fr', 'de', 'en'], []));
- $this->assertEquals(3, $repository->count(['fr', 'it'], []));
- $this->assertEquals(3, $repository->count(['fr', 'de'], ['_search' => false, 'key' => 'good']));
- $this->assertEquals(1, $repository->count(['fr', 'de'], ['_search' => true, 'key' => 'good']));
- $this->assertEquals(1, $repository->count(['en', 'de'], ['_search' => true, 'domain' => 'super']));
- $this->assertEquals(1,
- $repository->count(['en', 'fr', 'de'], ['_search' => true, 'key' => 'hel', 'domain' => 'uper']));
- $this->assertEquals(2,
- $repository->count(['en', 'de'], ['_search' => true, 'key' => 'say', 'domain' => 'ssa']));
+ $this->assertEquals(3, $repository->count(['locales' => null, 'filters' => []]));
+ $this->assertEquals(3, $repository->count(['locales' => ['fr', 'de', 'en'], 'filters' => []]));
+ $this->assertEquals(3, $repository->count(['locales' => ['fr', 'it'], 'filters' => []]));
+ $this->assertEquals(3, $repository->count(['locales' => ['fr', 'de'], 'filters' => ['_search' => false, 'key' => 'good']]));
+ $this->assertEquals(1, $repository->count(['locales' => ['fr', 'de'], 'filters' => ['_search' => true, 'key' => 'good']]));
+ $this->assertEquals(1, $repository->count(['locales' => ['en', 'de'], 'filters' => ['_search' => true, 'domain' => 'super']]));
+ $this->assertEquals(
+ 1,
+ $repository->count(['locales' => ['en', 'fr', 'de'], 'filters' => ['_search' => true, 'key' => 'hel', 'domain' => 'uper']])
+ );
+ $this->assertEquals(
+ 2,
+ $repository->count(['locales' => ['en', 'de'], 'filters' => ['_search' => true, 'key' => 'say', 'domain' => 'ssa']])
+ );
}
/**
@@ -140,8 +144,12 @@ public function testGetTransUnitList()
];
$this->assertSameTransUnit($expected, $result);
- $result = $repository->getTransUnitList(['fr', 'de'], 10, 1,
- ['sidx' => 'key', 'sord' => 'DESC', '_search' => true, 'domain' => 'mess']);
+ $result = $repository->getTransUnitList(
+ ['fr', 'de'],
+ 10,
+ 1,
+ ['sidx' => 'key', 'sord' => 'DESC', '_search' => true, 'domain' => 'mess']
+ );
$expected = [
[
'key' => 'key.say_wtf',
@@ -160,8 +168,12 @@ public function testGetTransUnitList()
];
$this->assertSameTransUnit($expected, $result);
- $result = $repository->getTransUnitList(['fr', 'de'], 10, 1,
- ['sidx' => 'key', 'sord' => 'DESC', '_search' => true, 'domain' => 'mess', 'key' => 'oo']);
+ $result = $repository->getTransUnitList(
+ ['fr', 'de'],
+ 10,
+ 1,
+ ['sidx' => 'key', 'sord' => 'DESC', '_search' => true, 'domain' => 'mess', 'key' => 'oo']
+ );
$expected = [
[
'key' => 'key.say_goodbye',
@@ -173,8 +185,12 @@ public function testGetTransUnitList()
];
$this->assertSameTransUnit($expected, $result);
- $result = $repository->getTransUnitList(['fr', 'en'], 10, 1,
- ['sidx' => 'key', 'sord' => 'DESC', '_search' => true, 'fr' => 'alu']);
+ $result = $repository->getTransUnitList(
+ ['fr', 'en'],
+ 10,
+ 1,
+ ['sidx' => 'key', 'sord' => 'DESC', '_search' => true, 'fr' => 'alu']
+ );
$expected = [
[
'key' => 'key.say_hello',
diff --git a/Tests/Unit/Repository/Entity/FileRepositoryTest.php b/Tests/Unit/Repository/Entity/FileRepositoryTest.php
index 859fef35..178f22f6 100644
--- a/Tests/Unit/Repository/Entity/FileRepositoryTest.php
+++ b/Tests/Unit/Repository/Entity/FileRepositoryTest.php
@@ -52,7 +52,7 @@ public function assertFilesPath($expected, $result)
{
$i = 0;
foreach ($result as $file) {
- $this->assertEquals($expected[$i], $file->getPath().'/'.$file->getName());
+ $this->assertEquals($expected[$i], $file->getPath() . '/' . $file->getName());
$i++;
}
}
diff --git a/Tests/Unit/Repository/Entity/TransUnitRepositoryTest.php b/Tests/Unit/Repository/Entity/TransUnitRepositoryTest.php
index d6f6ffd9..7dec2058 100644
--- a/Tests/Unit/Repository/Entity/TransUnitRepositoryTest.php
+++ b/Tests/Unit/Repository/Entity/TransUnitRepositoryTest.php
@@ -22,9 +22,9 @@ public function testGetAllDomainsByLocale()
$results = $repository->getAllDomainsByLocale();
$expected = [
['locale' => 'de', 'domain' => 'superTranslations'],
- ['locale' => 'en', 'domain' => 'messages'],
- ['locale' => 'en', 'domain' => 'superTranslations'],
- ['locale' => 'fr', 'domain' => 'messages'],
+ ['locale' => 'en', 'domain' => 'messages'],
+ ['locale' => 'en', 'domain' => 'superTranslations'],
+ ['locale' => 'fr', 'domain' => 'messages'],
['locale' => 'fr', 'domain' => 'superTranslations']
];
@@ -124,11 +124,11 @@ public function testGetTranslationsForFile()
$em = $this->loadDatabase();
$repository = $em->getRepository(self::ENTITY_TRANS_UNIT_CLASS);
- $file = $em->getRepository(self::ENTITY_FILE_CLASS)->findOneBy(['domain' => 'messages', 'locale' => 'fr', 'extention' => 'yml']);
+ $file = $em->getRepository(self::ENTITY_FILE_CLASS)->findOneBy(['domain' => 'messages', 'locale' => 'fr', 'extention' => 'yml']);
$this->assertInstanceOf(self::ENTITY_FILE_CLASS, $file);
$result = $repository->getTranslationsForFile($file, false);
- $expected = ['key.say_goodbye' => 'au revoir', 'key.say_wtf' => 'c\'est quoi ce bordel !?!'];
+ $expected = ['key.say_goodbye' => 'au revoir', 'key.say_wtf' => 'c\'est quoi ce bordel !?!'];
$this->assertEquals($expected, $result);
// update a translation and then get translations with onlyUpdated = true
diff --git a/Tests/Unit/Translation/Exporter/JsonExporterTest.php b/Tests/Unit/Translation/Exporter/JsonExporterTest.php
index 159bb80d..6960f1e5 100644
--- a/Tests/Unit/Translation/Exporter/JsonExporterTest.php
+++ b/Tests/Unit/Translation/Exporter/JsonExporterTest.php
@@ -16,8 +16,8 @@ class JsonExporterTest extends TestCase
public function tearDown(): void
{
- if (file_exists(__DIR__.$this->outFileName)) {
- unlink(__DIR__.$this->outFileName);
+ if (file_exists(__DIR__ . $this->outFileName)) {
+ unlink(__DIR__ . $this->outFileName);
}
}
@@ -26,7 +26,7 @@ public function tearDown(): void
*/
public function testExport()
{
- $outFile = __DIR__.$this->outFileName;
+ $outFile = __DIR__ . $this->outFileName;
$exporter = new JsonExporter();
diff --git a/Tests/Unit/Translation/Exporter/PhpExporterTest.php b/Tests/Unit/Translation/Exporter/PhpExporterTest.php
index b3a108de..c1439149 100644
--- a/Tests/Unit/Translation/Exporter/PhpExporterTest.php
+++ b/Tests/Unit/Translation/Exporter/PhpExporterTest.php
@@ -16,10 +16,10 @@ class PhpExporterTest extends TestCase
public function tearDown(): void
{
- $outFile = __DIR__.$this->outFileName;
+ $outFile = __DIR__ . $this->outFileName;
- if (file_exists(__DIR__.$this->outFileName)) {
- unlink(__DIR__.$this->outFileName);
+ if (file_exists(__DIR__ . $this->outFileName)) {
+ unlink(__DIR__ . $this->outFileName);
}
}
@@ -28,7 +28,7 @@ public function tearDown(): void
*/
public function testExport()
{
- $outFile = __DIR__.$this->outFileName;
+ $outFile = __DIR__ . $this->outFileName;
$exporter = new PhpExporter();
diff --git a/Tests/Unit/Translation/Exporter/YamlExporterTest.php b/Tests/Unit/Translation/Exporter/YamlExporterTest.php
index b076f49c..ffb29c21 100644
--- a/Tests/Unit/Translation/Exporter/YamlExporterTest.php
+++ b/Tests/Unit/Translation/Exporter/YamlExporterTest.php
@@ -16,10 +16,10 @@ class YamlExporterTest extends TestCase
public function tearDown(): void
{
- $outFile = __DIR__.$this->outFileName;
+ $outFile = __DIR__ . $this->outFileName;
- if (file_exists(__DIR__.$this->outFileName)) {
- unlink(__DIR__.$this->outFileName);
+ if (file_exists(__DIR__ . $this->outFileName)) {
+ unlink(__DIR__ . $this->outFileName);
}
}
@@ -28,13 +28,14 @@ public function tearDown(): void
*/
public function testExport()
{
- $outFile = __DIR__.$this->outFileName;
+ $outFile = __DIR__ . $this->outFileName;
$exporter = new YamlExporter();
// export empty array
$exporter->export($outFile, []);
- $expectedContent = '{ }';
+ // Expectation changed from '{ }' to '{}', because apparently after an update, an empty array is exported differently.
+ $expectedContent = '{}';
$this->assertEquals($expectedContent, trim(file_get_contents($outFile)));
// export array with values
@@ -59,7 +60,7 @@ public function testCreateMultiArray()
$this->assertEquals($expected, $result);
$result = $exporter->createMultiArray(['foo.bar.baz' => 'foobar', 'foo.foobaz' => 'bazbar']);
- $expected = ['foo' => ['foobaz' => 'bazbar', 'bar' => ['baz' => 'foobar']]];
+ $expected = ['foo' => ['foobaz' => 'bazbar', 'bar' => ['baz' => 'foobar']]];
$this->assertEquals($expected, $result);
}
@@ -75,15 +76,15 @@ public function testflattenArray()
$this->assertEquals($expected, $result);
$result = $exporter->flattenArray(
- ['bundle' => ['foo' => ['foobaz' => 'bazbar', 'bar' => ['baz0' => 'foobar', 'baz1' => 'foobaz']]]]
+ ['bundle' => ['foo' => ['foobaz' => 'bazbar', 'bar' => ['baz0' => 'foobar', 'baz1' => 'foobaz']]]]
);
- $expected = ['bundle.foo' => ['foobaz' => 'bazbar', 'bar' => ['baz0' => 'foobar', 'baz1' => 'foobaz']]];
+ $expected = ['bundle.foo' => ['foobaz' => 'bazbar', 'bar' => ['baz0' => 'foobar', 'baz1' => 'foobaz']]];
$this->assertEquals($expected, $result);
$result = $exporter->flattenArray(
- ['bundle' => ['foo' => ['foobaz' => 'bazbar', 'bar' => ['baz' => 'foobar']]]]
+ ['bundle' => ['foo' => ['foobaz' => 'bazbar', 'bar' => ['baz' => 'foobar']]]]
);
- $expected = ['bundle.foo' => ['foobaz' => 'bazbar', 'bar' => ['baz' => 'foobar']]];
+ $expected = ['bundle.foo' => ['foobaz' => 'bazbar', 'bar' => ['baz' => 'foobar']]];
$this->assertEquals($expected, $result);
}
}
diff --git a/Tests/Unit/Translation/Importer/FileImporterTest.php b/Tests/Unit/Translation/Importer/FileImporterTest.php
index 49a54cbb..e7f2e17e 100644
--- a/Tests/Unit/Translation/Importer/FileImporterTest.php
+++ b/Tests/Unit/Translation/Importer/FileImporterTest.php
@@ -2,13 +2,13 @@
namespace Lexik\Bundle\TranslationBundle\Tests\Unit\Translation\Importer;
-use Lexik\Bundle\TranslationBundle\Translation\Importer\FileImporter;
use Lexik\Bundle\TranslationBundle\Manager\FileManager;
use Lexik\Bundle\TranslationBundle\Manager\TransUnitManager;
use Lexik\Bundle\TranslationBundle\Tests\Unit\BaseUnitTestCase;
-use Symfony\Component\Translation\Loader\YamlFileLoader;
-use Symfony\Component\Translation\Loader\PhpFileLoader;
+use Lexik\Bundle\TranslationBundle\Translation\Importer\FileImporter;
use Symfony\Component\Finder\SplFileInfo;
+use Symfony\Component\Translation\Loader\PhpFileLoader;
+use Symfony\Component\Translation\Loader\YamlFileLoader;
/**
* FileImporter tests.
@@ -37,7 +37,7 @@ public function testImport()
$this->assertDatabaseEntries($em, 0);
// import files
- $files = [new SplFileInfo(__DIR__.'/../../../Fixtures/test.en.yml', '', ''), new SplFileInfo(__DIR__.'/../../../Fixtures/test.fr.php', '', '')];
+ $files = [new SplFileInfo(__DIR__ . '/../../../Fixtures/test.en.yml', '', ''), new SplFileInfo(__DIR__ . '/../../../Fixtures/test.fr.php', '', '')];
foreach ($files as $file) {
$importer->import($file);
diff --git a/Tests/Unit/Translation/Loader/DatabaseLoaderTest.php b/Tests/Unit/Translation/Loader/DatabaseLoaderTest.php
index ccdb0eb8..305c6828 100644
--- a/Tests/Unit/Translation/Loader/DatabaseLoaderTest.php
+++ b/Tests/Unit/Translation/Loader/DatabaseLoaderTest.php
@@ -3,8 +3,8 @@
namespace Lexik\Bundle\TranslationBundle\Tests\Unit\Translation\Loader;
use Lexik\Bundle\TranslationBundle\Entity\TransUnit;
-use Lexik\Bundle\TranslationBundle\Translation\Loader\DatabaseLoader;
use Lexik\Bundle\TranslationBundle\Tests\Unit\BaseUnitTestCase;
+use Lexik\Bundle\TranslationBundle\Translation\Loader\DatabaseLoader;
use Symfony\Component\Translation\MessageCatalogue;
/**
@@ -31,7 +31,7 @@ public function testLoad()
$this->assertEquals('it', $catalogue->getLocale());
$catalogue = $loader->load(null, 'fr');
- $expectedTranslations = ['messages' => ['key.say_goodbye' => 'au revoir', 'key.say_wtf' => 'c\'est quoi ce bordel !?!']];
+ $expectedTranslations = ['messages' => ['key.say_goodbye' => 'au revoir', 'key.say_wtf' => 'c\'est quoi ce bordel !?!']];
$this->assertInstanceOf(MessageCatalogue::class, $catalogue);
$this->assertEquals($expectedTranslations, $catalogue->all());
$this->assertEquals('fr', $catalogue->getLocale());
diff --git a/Tests/Unit/Translation/Manager/TransUnitManagerTest.php b/Tests/Unit/Translation/Manager/TransUnitManagerTest.php
index e0cbc0d4..f89c46c8 100644
--- a/Tests/Unit/Translation/Manager/TransUnitManagerTest.php
+++ b/Tests/Unit/Translation/Manager/TransUnitManagerTest.php
@@ -7,8 +7,8 @@
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\UnitOfWork as ORMUnitOfWork;
use Lexik\Bundle\TranslationBundle\Entity\TransUnit;
-use Lexik\Bundle\TranslationBundle\Manager\TransUnitManager;
use Lexik\Bundle\TranslationBundle\Manager\FileManager;
+use Lexik\Bundle\TranslationBundle\Manager\TransUnitManager;
use Lexik\Bundle\TranslationBundle\Storage\DoctrineMongoDBStorage;
use Lexik\Bundle\TranslationBundle\Storage\DoctrineORMStorage;
use Lexik\Bundle\TranslationBundle\Tests\Unit\BaseUnitTestCase;
diff --git a/Tests/Unit/Translation/TranslatorTest.php b/Tests/Unit/Translation/TranslatorTest.php
index 71c2a306..88c8e958 100644
--- a/Tests/Unit/Translation/TranslatorTest.php
+++ b/Tests/Unit/Translation/TranslatorTest.php
@@ -4,11 +4,11 @@
use Lexik\Bundle\TranslationBundle\EventDispatcher\Event\GetDatabaseResourcesEvent;
use Lexik\Bundle\TranslationBundle\EventDispatcher\GetDatabaseResourcesListener;
-use Lexik\Bundle\TranslationBundle\Translation\Translator;
use Lexik\Bundle\TranslationBundle\Tests\Unit\BaseUnitTestCase;
+use Lexik\Bundle\TranslationBundle\Translation\Translator;
+use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Translation\Formatter\MessageFormatter;
-use Symfony\Component\DependencyInjection\Container;
/**
* Translator tests.
@@ -26,8 +26,8 @@ public function testAddDatabaseResources(): void
$this->createSchema($em);
$this->loadFixtures($em);
- if (file_exists(sys_get_temp_dir().'/database.resources.php')) {
- unlink(sys_get_temp_dir().'/database.resources.php');
+ if (file_exists(sys_get_temp_dir() . '/database.resources.php')) {
+ unlink(sys_get_temp_dir() . '/database.resources.php');
}
$translator = $this->createTranslator($em, sys_get_temp_dir());
@@ -36,13 +36,13 @@ public function testAddDatabaseResources(): void
$expected = [
'de' => [
['database', 'DB', 'superTranslations']
- ],
+ ],
'en' => [
- ['database', 'DB', 'messages'],
+ ['database', 'DB', 'messages'],
['database', 'DB', 'superTranslations']
- ],
+ ],
'fr' => [
- ['database', 'DB', 'messages'],
+ ['database', 'DB', 'messages'],
['database', 'DB', 'superTranslations'],
]
];
@@ -58,29 +58,29 @@ public function testAddDatabaseResources(): void
*/
public function testRemoveCacheFile(): void
{
- $cacheDir = __DIR__.'/../../../vendor/test_cache_dir';
+ $cacheDir = __DIR__ . '/../../../vendor/test_cache_dir';
$this->createFakeCacheFiles($cacheDir);
$translator = $this->createTranslator($this->getMockSqliteEntityManager(), $cacheDir);
// remove locale 'fr'
- $this->assertTrue(file_exists($cacheDir.'/catalogue.fr.php'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.fr.php.meta'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.fr_FR.php'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.fr_FR.php.meta'));
+ $this->assertFileExists($cacheDir . '/catalogue.fr.php');
+ $this->assertFileExists($cacheDir . '/catalogue.fr.php.meta');
+ $this->assertFileExists($cacheDir . '/catalogue.fr_FR.php');
+ $this->assertFileExists($cacheDir . '/catalogue.fr_FR.php.meta');
$translator->removeCacheFile('fr');
- $this->assertFalse(file_exists($cacheDir.'/catalogue.fr.php'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.fr.php.meta'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.fr_FR.php'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.fr_FR.php.meta'));
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.fr.php');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.fr.php.meta');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.fr_FR.php');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.fr_FR.php.meta');
// remove locale 'en'
- $this->assertTrue(file_exists($cacheDir.'/catalogue.en.php'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.en.php.meta'));
+ $this->assertFileExists($cacheDir . '/catalogue.en.php');
+ $this->assertFileExists($cacheDir . '/catalogue.en.php.meta');
$translator->removeCacheFile('en');
- $this->assertFalse(file_exists($cacheDir.'/catalogue.en.php'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.en.php.meta'));
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.en.php');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.en.php.meta');
}
/**
@@ -88,29 +88,29 @@ public function testRemoveCacheFile(): void
*/
public function testRemoveLocalesCacheFiles(): void
{
- $cacheDir = __DIR__.'/../../../vendor/test_cache_dir';
+ $cacheDir = __DIR__ . '/../../../vendor/test_cache_dir';
$this->createFakeCacheFiles($cacheDir);
$translator = $this->createTranslator($this->getMockSqliteEntityManager(), $cacheDir);
- $this->assertTrue(file_exists($cacheDir.'/database.resources.php'));
- $this->assertTrue(file_exists($cacheDir.'/database.resources.php.meta'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.fr.php'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.fr.php.meta'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.fr_FR.php'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.fr_FR.php.meta'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.en.php'));
- $this->assertTrue(file_exists($cacheDir.'/catalogue.en.php.meta'));
+ $this->assertFileExists($cacheDir . '/database.resources.php');
+ $this->assertFileExists($cacheDir . '/database.resources.php.meta');
+ $this->assertFileExists($cacheDir . '/catalogue.fr.php');
+ $this->assertFileExists($cacheDir . '/catalogue.fr.php.meta');
+ $this->assertFileExists($cacheDir . '/catalogue.fr_FR.php');
+ $this->assertFileExists($cacheDir . '/catalogue.fr_FR.php.meta');
+ $this->assertFileExists($cacheDir . '/catalogue.en.php');
+ $this->assertFileExists($cacheDir . '/catalogue.en.php.meta');
$translator->removeLocalesCacheFiles(['fr', 'en']);
- $this->assertFalse(file_exists($cacheDir.'/database.resources.php'));
- $this->assertFalse(file_exists($cacheDir.'/database.resources.php.meta'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.fr.php'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.fr.php.meta'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.fr_FR.php'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.fr_FR.php.meta'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.en.php'));
- $this->assertFalse(file_exists($cacheDir.'/catalogue.en.php.meta'));
+ $this->assertFileDoesNotExist($cacheDir . '/database.resources.php');
+ $this->assertFileDoesNotExist($cacheDir . '/database.resources.php.meta');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.fr.php');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.fr.php.meta');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.fr_FR.php');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.fr_FR.php.meta');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.en.php');
+ $this->assertFileDoesNotExist($cacheDir . '/catalogue.en.php.meta');
}
protected function createTranslator($em, $cacheDir): TranslatorMock
@@ -128,22 +128,18 @@ protected function createTranslator($em, $cacheDir): TranslatorMock
$container->set('event_dispatcher', $dispatcher);
$container->compile();
- $loaderIds = [];
+ $innerTranslator = new \Symfony\Component\Translation\Translator('en', new MessageFormatter());
+
$options = [
'cache_dir' => $cacheDir,
'debug' => true,
- 'resource_files' => [],
- 'cache_vary' => [],
- 'scanned_directories' => [],
- 'enabled_locales' => ['en', 'fr'],
- 'default_locale' => 'en',
+ 'resources_type' => 'all',
];
return new TranslatorMock(
+ translator: $innerTranslator,
container: $container,
- formatter: new MessageFormatter(),
- defaultLocale: 'en',
- loaderIds: $loaderIds,
+ loaderIds: [],
options: $options
);
}
@@ -154,47 +150,30 @@ protected function createFakeCacheFiles($cacheDir): void
mkdir($cacheDir);
}
- touch($cacheDir.'/catalogue.fr.php');
- touch($cacheDir.'/catalogue.fr.php.meta');
+ touch($cacheDir . '/catalogue.fr.php');
+ touch($cacheDir . '/catalogue.fr.php.meta');
- touch($cacheDir.'/catalogue.fr_FR.php');
- touch($cacheDir.'/catalogue.fr_FR.php.meta');
+ touch($cacheDir . '/catalogue.fr_FR.php');
+ touch($cacheDir . '/catalogue.fr_FR.php.meta');
- touch($cacheDir.'/catalogue.en.php');
- touch($cacheDir.'/catalogue.en.php.meta');
+ touch($cacheDir . '/catalogue.en.php');
+ touch($cacheDir . '/catalogue.en.php.meta');
- touch($cacheDir.'/database.resources.php');
- touch($cacheDir.'/database.resources.php.meta');
+ touch($cacheDir . '/database.resources.php');
+ touch($cacheDir . '/database.resources.php.meta');
}
}
class TranslatorMock extends Translator
{
public array $dbResources = [];
- public array $options = [
- 'cache_dir' => '',
- 'debug' => false,
- 'resource_files' => [],
- 'cache_vary' => [],
- 'scanned_directories' => [],
- 'enabled_locales' => [],
- 'default_locale' => 'en',
- 'loader_ids' => [],
- 'formatter' => null,
- 'container' => null
- ];
public function addResource(string $format, mixed $resource, string $locale, ?string $domain = null): void
{
- if(empty( $domain )) {
- var_dump('Domain is empty in TranslatorMock::addResource');
- var_dump($format, $resource, $locale);
- exit;
- }
if ('database' === $format) {
$this->dbResources[$locale][] = [$format, $resource, $domain];
}
parent::addResource($format, $resource, $locale, $domain);
}
-}
+}
\ No newline at end of file
diff --git a/Tests/Unit/Util/DataGrid/DataGridFormatterTest.php b/Tests/Unit/Util/DataGrid/DataGridFormatterTest.php
index 8f881f9a..40857a0e 100644
--- a/Tests/Unit/Util/DataGrid/DataGridFormatterTest.php
+++ b/Tests/Unit/Util/DataGrid/DataGridFormatterTest.php
@@ -4,8 +4,8 @@
use Lexik\Bundle\TranslationBundle\Manager\LocaleManager;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
-use Lexik\Bundle\TranslationBundle\Util\DataGrid\DataGridFormatter;
use Lexik\Bundle\TranslationBundle\Tests\Unit\BaseUnitTestCase;
+use Lexik\Bundle\TranslationBundle\Util\DataGrid\DataGridFormatter;
/**
* @author Cédric Girard
@@ -20,7 +20,7 @@ public function testCreateListResponse()
$datas = [['id' => 2, 'key' => 'key.say_goodbye', 'domain' => 'messages', 'translations' => [['locale' => 'fr', 'content' => 'au revoir'], ['locale' => 'en', 'content' => 'good bye']]], ['id' => 1, 'key' => 'key.say_hello', 'domain' => 'superTranslations', 'translations' => [['locale' => 'fr', 'content' => 'salut'], ['locale' => 'de', 'content' => 'heil']]], ['id' => 3, 'key' => 'key.say_wtf', 'domain' => 'messages', 'translations' => [['locale' => 'fr', 'content' => 'c\'est quoi ce bordel !?!'], ['locale' => 'xx', 'content' => 'xxx xxx xxx']]]];
$total = 3;
- $expected = ['translations' => [['_id' => 2, '_domain' => 'messages', '_key' => 'key.say_goodbye', 'de' => '', 'en' => 'good bye', 'fr' => 'au revoir'], ['_id' => 1, '_domain' => 'superTranslations', '_key' => 'key.say_hello', 'de' => 'heil', 'en' => '', 'fr' => 'salut'], ['_id' => 3, '_domain' => 'messages', '_key' => 'key.say_wtf', 'de' => '', 'en' => '', 'fr' => 'c\'est quoi ce bordel !?!']], 'total' => 3];
+ $expected = ['translations' => [['_id' => 2, '_domain' => 'messages', '_key' => 'key.say_goodbye', 'de' => '', 'en' => 'good bye', 'fr' => 'au revoir'], ['_id' => 1, '_domain' => 'superTranslations', '_key' => 'key.say_hello', 'de' => 'heil', 'en' => '', 'fr' => 'salut'], ['_id' => 3, '_domain' => 'messages', '_key' => 'key.say_wtf', 'de' => '', 'en' => '', 'fr' => 'c\'est quoi ce bordel !?!']], 'total' => 3];
$formatter = new DataGridFormatter(new LocaleManager(['de', 'en', 'fr']), StorageInterface::STORAGE_ORM);
$this->assertEquals(json_encode($expected, JSON_HEX_APOS), $formatter->createListResponse($datas, $total)->getContent());
diff --git a/Tests/Unit/Util/DataGrid/DataGridRequestHandlerTest.php b/Tests/Unit/Util/DataGrid/DataGridRequestHandlerTest.php
index 7f62f49c..49672ba5 100644
--- a/Tests/Unit/Util/DataGrid/DataGridRequestHandlerTest.php
+++ b/Tests/Unit/Util/DataGrid/DataGridRequestHandlerTest.php
@@ -2,13 +2,12 @@
namespace Lexik\Bundle\TranslationBundle\Tests\Unit\Util\DataGrid;
-use Lexik\Bundle\TranslationBundle\Manager\TransUnitManager;
use Lexik\Bundle\TranslationBundle\Manager\FileManagerInterface;
-use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
use Lexik\Bundle\TranslationBundle\Manager\LocaleManager;
+use Lexik\Bundle\TranslationBundle\Manager\TransUnitManager;
+use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
use Lexik\Bundle\TranslationBundle\Tests\Unit\BaseUnitTestCase;
use Lexik\Bundle\TranslationBundle\Util\DataGrid\DataGridRequestHandler;
-use Symfony\Component\HttpFoundation\Request;
/**
* @author Cédric Girard
diff --git a/Tests/app/test/config.yml b/Tests/app/test/config.yml
index 503d2db9..a224fda4 100644
--- a/Tests/app/test/config.yml
+++ b/Tests/app/test/config.yml
@@ -4,9 +4,12 @@ imports:
framework:
fragments: ~
secret: afasfsf
+ default_locale: 'en'
+ enabled_locales: ['en', 'pl', 'de', 'sv']
translator:
enabled: true
+ fallbacks: ['en']
-lexik_translation:
- fallback_locale: en
- managed_locales: [en, pl, de, sv]
+#lexik_translation:
+# fallback_locale: en
+# managed_locales: [en, pl, de, sv]
diff --git a/Tests/app/test/database.php b/Tests/app/test/database.php
index fcb43a7b..19a0dafb 100644
--- a/Tests/app/test/database.php
+++ b/Tests/app/test/database.php
@@ -3,7 +3,7 @@
if (ORM_TYPE == "doctrine") {
$container->loadFromExtension(
'doctrine',
- ['orm' => ['mappings' => ['Mapping' => ['type' => 'xml', 'prefix' => 'Lexik\Bundle\TranslationBundle\Entity', 'is_bundle' => false, 'dir' => '%kernel.project_dir%/Resources/config/doctrine']]], 'dbal' => ['charset' => 'UTF8', 'driver' => DB_ENGINE, 'host' => DB_HOST, 'port' => DB_PORT, 'dbname' => DB_NAME, 'user' => DB_USER, 'password' => DB_PASSWD]]
+ ['orm' => ['mappings' => ['Mapping' => ['type' => 'xml', 'prefix' => 'Lexik\Bundle\TranslationBundle\Entity', 'is_bundle' => false, 'dir' => '%kernel.project_dir%/Resources/config/doctrine']]], 'dbal' => ['charset' => 'UTF8', 'driver' => DB_ENGINE, 'host' => DB_HOST, 'port' => DB_PORT, 'dbname' => DB_NAME, 'user' => DB_USER, 'password' => DB_PASSWD]]
);
} else {
throw new Exception("Currently only doctrine is supported");
diff --git a/Tests/bootstrap.php b/Tests/bootstrap.php
index 7dd2f835..83bf11e9 100644
--- a/Tests/bootstrap.php
+++ b/Tests/bootstrap.php
@@ -1,4 +1,5 @@
hierarchicalFormat ? $this->hierarchicalFormat($translations) : $translations, JSON_PRETTY_PRINT));
@@ -30,9 +30,9 @@ public function export($file, $translations)
/**
* {@inheritdoc}
*/
- public function support($format)
+ public function support(string $format): bool
{
- return ('json' == $format);
+ return ('json' === $format);
}
/**
diff --git a/Translation/Exporter/PhpExporter.php b/Translation/Exporter/PhpExporter.php
index 89140636..f9ba8e8b 100644
--- a/Translation/Exporter/PhpExporter.php
+++ b/Translation/Exporter/PhpExporter.php
@@ -12,7 +12,7 @@ class PhpExporter implements ExporterInterface
/**
* {@inheritdoc}
*/
- public function export($file, $translations)
+ public function export(string $file, array $translations): bool
{
$phpContent = sprintf("createXmlDocument();
@@ -39,9 +39,9 @@ public function export($file, $translations)
/**
* {@inheritdoc}
*/
- public function support($format)
+ public function support(string $format): bool
{
- return ('xlf' == $format || 'xliff' == $format);
+ return ('xlf' === $format || 'xliff' === $format);
}
/**
@@ -49,7 +49,7 @@ public function support($format)
*
* @return \DOMDocument
*/
- protected function createXmlDocument()
+ protected function createXmlDocument(): \DOMDocument
{
$dom = new \DOMDocument('1.0', 'utf-8');
$dom->formatOutput = true;
@@ -59,11 +59,9 @@ protected function createXmlDocument()
/**
* Add root nodes to a document.
- *
- * @param string|null $targetLanguage
- * @return \DOMElement
+ * @throws \DOMException
*/
- protected function addRootNodes(\DOMDocument $dom, $targetLanguage = null)
+ protected function addRootNodes(\DOMDocument $dom, ?string $targetLanguage = null): \DOMElement
{
$xliff = $dom->appendChild($dom->createElement('xliff'));
$xliff->appendChild(new \DOMAttr('xmlns', 'urn:oasis:names:tc:xliff:document:1.2'));
@@ -78,28 +76,26 @@ protected function addRootNodes(\DOMDocument $dom, $targetLanguage = null)
$fileNode->appendChild(new \DOMAttr('target-language', $targetLanguage));
}
- $bodyNode = $fileNode->appendChild($dom->createElement('body'));
+ $body = $dom->createElement('body');
+ $fileNode->appendChild($body);
- return $bodyNode;
+ return $body;
}
/**
* Create a new trans-unit node.
*
- * @param int $id
- * @param string $key
- * @param string $value
- * @return \DOMElement
+ * @throws \DOMException
*/
- protected function createTranslationNode(\DOMDocument $dom, $id, $key, $value)
+ protected function createTranslationNode(\DOMDocument $dom, int $id, string $key, string $value): \DOMElement
{
$translationNode = $dom->createElement('trans-unit');
- $translationNode->appendChild(new \DOMAttr('id', $id));
-
+ $translationNode->appendChild(new \DOMAttr('id', (string) $id));
+
/**
* @see http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#approved
*/
- if ($value != '') {
+ if ($value !== '') {
$translationNode->appendChild(new \DOMAttr('approved', 'yes'));
}
diff --git a/Translation/Exporter/YamlExporter.php b/Translation/Exporter/YamlExporter.php
index 59beb1b1..c369c908 100644
--- a/Translation/Exporter/YamlExporter.php
+++ b/Translation/Exporter/YamlExporter.php
@@ -20,7 +20,7 @@ public function __construct(
/**
* {@inheritdoc}
*/
- public function export($file, $translations)
+ public function export(string $file, array $translations): bool
{
if ($this->createTree) {
$result = $this->createMultiArray($translations);
@@ -122,8 +122,8 @@ protected function flattenArray($array, $prefix = '')
/**
* {@inheritdoc}
*/
- public function support($format)
+ public function support(string $format): bool
{
- return ('yml' == $format || 'yaml' == $format);
+ return ('yml' === $format || 'yaml' === $format);
}
}
diff --git a/Translation/Importer/FileImporter.php b/Translation/Importer/FileImporter.php
index 46019e65..d8c100c2 100644
--- a/Translation/Importer/FileImporter.php
+++ b/Translation/Importer/FileImporter.php
@@ -2,14 +2,14 @@
namespace Lexik\Bundle\TranslationBundle\Translation\Importer;
-use Symfony\Component\Finder\SplFileInfo;
-use Lexik\Bundle\TranslationBundle\Entity\Translation;
-use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
use Lexik\Bundle\TranslationBundle\Document\TransUnit as TransUnitDocument;
+use Lexik\Bundle\TranslationBundle\Entity\Translation;
use Lexik\Bundle\TranslationBundle\Manager\FileManagerInterface;
-use Lexik\Bundle\TranslationBundle\Manager\TransUnitManagerInterface;
-use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
use Lexik\Bundle\TranslationBundle\Manager\TranslationInterface;
+use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
+use Lexik\Bundle\TranslationBundle\Manager\TransUnitManagerInterface;
+use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
+use Symfony\Component\Finder\SplFileInfo;
/**
* Import a translation file into the database.
@@ -123,10 +123,7 @@ public function import(SplFileInfo $file, $forceUpdate = false, $merge = false)
$this->storage->flush();
- // clear only Lexik entities
- foreach (['file', 'trans_unit', 'translation'] as $name) {
- $this->storage->clear($this->storage->getModelClass($name));
- }
+ $this->storage->clear();
return $imported;
}
diff --git a/Translation/Translator.php b/Translation/Translator.php
index b6dad880..e99d09b2 100644
--- a/Translation/Translator.php
+++ b/Translation/Translator.php
@@ -3,140 +3,120 @@
namespace Lexik\Bundle\TranslationBundle\Translation;
use Lexik\Bundle\TranslationBundle\EventDispatcher\Event\GetDatabaseResourcesEvent;
-use Symfony\Component\Translation\Loader\LoaderInterface;
+
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\ContainerInterface;
+use Psr\Container\NotFoundExceptionInterface;
use Symfony\Component\Config\ConfigCache;
+use Symfony\Component\Config\ConfigCacheFactoryInterface;
use Symfony\Component\Finder\Finder;
-use Psr\Container\ContainerInterface;
-use Symfony\Component\Translation\Formatter\MessageFormatter;
-use Symfony\Bundle\FrameworkBundle\Translation\Translator as SymfonyTranslator;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+use Symfony\Contracts\Translation\TranslatableInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
-use Symfony\Contracts\Translation\LocaleAwareInterface;
-use Symfony\Component\Translation\TranslatorBagInterface;
/**
- * Translator service class that decorates Symfony's Translator.
+ * Decorator for Symfony Translator service to add database translation resources.
*
- * Uses composition instead of inheritance to be compatible with Symfony 8
- * where the Translator class is final.
+ * This decorator wraps the original translator service and adds functionality
+ * to load translations from the database. It implements TranslatorInterface
+ * to maintain compatibility with Symfony 8 where Translator is final.
*
* @author Cédric Girard
*/
-class Translator implements TranslatorInterface, LocaleAwareInterface, TranslatorBagInterface
+class Translator implements TranslatorInterface
{
- private SymfonyTranslator $translator;
- protected array $resourceLocales = [];
- protected array $resources = [];
- protected array $resourceFiles = [];
- protected array $scannedDirectories = [];
- protected string $cacheFile;
private bool $isResourcesLoaded = false;
-
- /** @var array For tracking database resources (mainly for testing) */
- public array $dbResources = [];
+ private string $cacheFile;
public function __construct(
- protected ContainerInterface $container,
- MessageFormatter $formatter,
- string $defaultLocale,
- protected array $loaderIds,
- protected array $options
+ private $translator,
+ private readonly ContainerInterface $container,
+ private readonly array $loaderIds,
+ private array $options
) {
- $this->resourceLocales = [];
- $this->resources = [];
- $this->resourceFiles = [];
- $this->scannedDirectories = [];
-
- $this->options['resource_files'] = $this->options['resource_files'] ?? [];
- $this->options['scanned_directories'] = $this->options['scanned_directories'] ?? [];
- $this->options['cache_vary'] = $this->options['cache_vary'] ?? [];
$this->options['cache_dir'] = $this->options['cache_dir'] ?? sys_get_temp_dir();
$this->options['debug'] = $this->options['debug'] ?? false;
$this->options['resources_type'] = $this->options['resources_type'] ?? 'all';
-
$this->cacheFile = sprintf('%s/database.resources.php', $this->options['cache_dir']);
+ }
- // Filter out custom options that Symfony translator doesn't recognize
- // Only pass valid Symfony translator options
- $symfonyOptions = [
- 'cache_dir' => $this->options['cache_dir'],
- 'debug' => $this->options['debug'],
- ];
-
- // Add other valid Symfony options if they exist
- $validSymfonyOptions = ['cache_dir', 'debug', 'resource_files', 'scanned_directories', 'cache_vary'];
- foreach ($validSymfonyOptions as $key) {
- if (isset($this->options[$key])) {
- $symfonyOptions[$key] = $this->options[$key];
- }
- }
+ public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory): void
+ {
+ $this->translator->setConfigCacheFactory($configCacheFactory);
+ }
- // Create the inner Symfony translator
- $this->translator = new SymfonyTranslator(
- container: $this->container,
- formatter: $formatter,
- defaultLocale: $defaultLocale,
- loaderIds: $this->loaderIds,
- options: $symfonyOptions,
- enabledLocales: []
- );
+ public function addLoader(string $format, LoaderInterface $loader): void
+ {
+ $this->translator->addLoader($format, $loader);
}
- /**
- * {@inheritdoc}
- */
- public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
+ public function addResource(string $format, mixed $resource, string $locale, ?string $domain = null): void
{
- $this->loadDatabaseResourcesIfNeeded();
- return $this->translator->trans($id, $parameters, $domain, $locale);
+ $this->translator->addResource($format, $resource, $locale, $domain);
+ }
+
+ public function setLocale(string $locale): void
+ {
+ $this->translator->setLocale($locale);
}
- /**
- * {@inheritdoc}
- */
public function getLocale(): string
{
return $this->translator->getLocale();
}
- /**
- * {@inheritdoc}
- */
- public function setLocale(string $locale): void
+ public function setFallbackLocales(array $locales): void
{
- $this->translator->setLocale($locale);
+ $this->translator->setFallbackLocales($locales);
}
- /**
- * {@inheritdoc}
- */
- public function getCatalogue(?string $locale = null): \Symfony\Component\Translation\MessageCatalogueInterface
+ public function getFallbackLocales(): array
{
- $this->loadDatabaseResourcesIfNeeded();
- return $this->translator->getCatalogue($locale);
+ return $this->translator->getFallbackLocales();
}
- /**
- * {@inheritdoc}
- */
- public function getCatalogues(): array
+ public function addGlobalParameter(string $id, string|int|float|TranslatableInterface $value): void
{
- return $this->translator->getCatalogues();
+ $this->translator->addGlobalParameter($id, $value);
}
- /**
- * Load database resources if needed.
- */
- private function loadDatabaseResourcesIfNeeded(): void
+ public function getGlobalParameters(): array
{
- $resourcesType = $this->options['resources_type'] ?? 'all';
+ return $this->translator->getGlobalParameters();
+ }
+
+ public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
+ {
+ $resourcesType = $this->options['resources_type'];
if (!$this->isResourcesLoaded && ('all' === $resourcesType || 'database' === $resourcesType)) {
$this->addDatabaseResources();
}
+
+ return $this->translator->trans($id, $parameters, $domain, $locale);
+ }
+
+ public function getCatalogue(?string $locale = null): MessageCatalogueInterface
+ {
+ return $this->translator->getCatalogue($locale);
+ }
+
+ public function getCatalogues(): array
+ {
+ return $this->translator->getCatalogues();
+ }
+
+ public function warmUp(string $cacheDir, ?string $buildDir = null): array
+ {
+ return $this->translator->warmUp($cacheDir, $buildDir);
}
/**
* Add all resources available in database.
+ *
+ * This method is called by DatabaseResourcesListener to register
+ * database translation resources with the translator.
*/
public function addDatabaseResources(): void
{
@@ -159,17 +139,8 @@ public function addDatabaseResources(): void
$resources = include $this->cacheFile;
}
- // Use reflection to access the addResource method on the inner translator
- $reflection = new \ReflectionClass($this->translator);
- $addResourceMethod = $reflection->getMethod('addResource');
-
foreach ($resources as $resource) {
- $locale = $resource['locale'];
- $domain = $resource['domain'] ?? 'messages';
- $addResourceMethod->invoke($this->translator, 'database', 'DB', $locale, $domain);
-
- // Track for testing purposes
- $this->dbResources[$locale][] = ['database', 'DB', $domain];
+ $this->addResource('database', 'DB', $resource['locale'], $resource['domain'] ?? 'messages');
}
$this->isResourcesLoaded = true;
@@ -177,11 +148,8 @@ public function addDatabaseResources(): void
/**
* Remove the cache file corresponding to the given locale.
- *
- * @param string $locale
- * @return boolean
*/
- public function removeCacheFile($locale)
+ public function removeCacheFile(string $locale): bool
{
if (!file_exists($this->cacheFile)) {
return true;
@@ -189,7 +157,7 @@ public function removeCacheFile($locale)
$localeExploded = explode('_', $locale);
$finder = new Finder();
- $finder->files()->in($this->options['cache_dir'])->name(sprintf( '/catalogue\.%s.*\.php$/', $localeExploded[0]));
+ $finder->files()->in($this->options['cache_dir'])->name(sprintf('/catalogue\.%s.*\.php$/', $localeExploded[0]));
$deleted = true;
foreach ($finder as $file) {
@@ -197,7 +165,7 @@ public function removeCacheFile($locale)
$this->invalidateSystemCacheForFile($path);
$deleted = unlink($path);
- $metadata = $path.'.meta';
+ $metadata = $path . '.meta';
if (file_exists($metadata)) {
$this->invalidateSystemCacheForFile($metadata);
unlink($metadata);
@@ -210,7 +178,7 @@ public function removeCacheFile($locale)
/**
* Remove the cache file corresponding to each given locale.
*/
- public function removeLocalesCacheFiles(array $locales)
+ public function removeLocalesCacheFiles(array $locales): void
{
foreach ($locales as $locale) {
$this->removeCacheFile($locale);
@@ -223,7 +191,7 @@ public function removeLocalesCacheFiles(array $locales)
unlink($file);
}
- $metadata = $file.'.meta';
+ $metadata = $file . '.meta';
if (file_exists($metadata)) {
$this->invalidateSystemCacheForFile($metadata);
unlink($metadata);
@@ -233,17 +201,15 @@ public function removeLocalesCacheFiles(array $locales)
}
/**
- * @param string $path
- *
* @throws \RuntimeException
*/
- protected function invalidateSystemCacheForFile($path)
+ protected function invalidateSystemCacheForFile(string $path): void
{
if (ini_get('apc.enabled') && function_exists('apc_delete_file')) {
if (apc_exists($path) && !apc_delete_file($path)) {
throw new \RuntimeException(sprintf('Failed to clear APC Cache for file %s', $path));
}
- } elseif ('cli' === php_sapi_name() ? ini_get('opcache.enable_cli') : ini_get('opcache.enable')) {
+ } elseif ('cli' === PHP_SAPI ? ini_get('opcache.enable_cli') : ini_get('opcache.enable')) {
if (function_exists("opcache_invalidate") && !opcache_invalidate($path, true)) {
throw new \RuntimeException(sprintf('Failed to clear OPCache for file %s', $path));
}
@@ -255,11 +221,11 @@ protected function invalidateSystemCacheForFile($path)
*
* @return array
*/
- public function getFormats()
+ public function getFormats(): array
{
$allFormats = [];
- foreach ($this->loaderIds as $id => $formats) {
+ foreach ($this->loaderIds as $formats) {
foreach ($formats as $format) {
if ('database' !== $format) {
$allFormats[] = $format;
@@ -273,18 +239,17 @@ public function getFormats()
/**
* Returns a loader according to the given format.
*
- * @param string $format
- * @throws \RuntimeException
- * @return LoaderInterface
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
*/
- public function getLoader($format)
+ public function getLoader(string $format): LoaderInterface
{
$loader = null;
$i = 0;
$ids = array_keys($this->loaderIds);
while ($i < count($ids) && null === $loader) {
- if (in_array($format, $this->loaderIds[$ids[$i]])) {
+ if (\in_array($format, $this->loaderIds[ $ids[ $i ] ], true)) {
$loader = $this->container->get($ids[$i]);
}
$i++;
@@ -296,47 +261,4 @@ public function getLoader($format)
return $loader;
}
-
- /**
- * Set fallback locales.
- */
- public function setFallbackLocales(array $locales): void
- {
- $this->translator->setFallbackLocales($locales);
- }
-
- /**
- * Get fallback locales.
- */
- public function getFallbackLocales(): array
- {
- return $this->translator->getFallbackLocales();
- }
-
- /**
- * Warms up the cache.
- */
- public function warmUp(string $cacheDir): array
- {
- return $this->translator->warmUp($cacheDir);
- }
-
- /**
- * Set config cache factory.
- */
- public function setConfigCacheFactory(\Symfony\Component\Config\ConfigCacheFactoryInterface $configCacheFactory): void
- {
- $this->translator->setConfigCacheFactory($configCacheFactory);
- }
-
- /**
- * Add resource to the inner translator.
- */
- public function addResource(string $format, mixed $resource, string $locale, ?string $domain = null): void
- {
- // Use reflection to access the protected addResource method
- $reflection = new \ReflectionClass($this->translator);
- $addResourceMethod = $reflection->getMethod('addResource');
- $addResourceMethod->invoke($this->translator, $format, $resource, $locale, $domain);
- }
}
diff --git a/Translation/TranslatorDecorator.php b/Translation/TranslatorDecorator.php
deleted file mode 100644
index 99849f1d..00000000
--- a/Translation/TranslatorDecorator.php
+++ /dev/null
@@ -1,195 +0,0 @@
-
- */
-class TranslatorDecorator implements TranslatorInterface
-{
- private bool $isResourcesLoaded = false;
- private string $cacheFile;
-
- public function __construct(
- private readonly TranslatorInterface $translator,
- private readonly \Psr\Container\ContainerInterface $container,
- private readonly array $options
- ) {
- $this->options['cache_dir'] = $this->options['cache_dir'] ?? sys_get_temp_dir();
- $this->options['debug'] = $this->options['debug'] ?? false;
- $this->options['resources_type'] = $this->options['resources_type'] ?? 'all';
- $this->cacheFile = sprintf('%s/database.resources.php', $this->options['cache_dir']);
- }
-
- /**
- * {@inheritdoc}
- */
- public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
- {
- // Database resources are loaded via DatabaseResourcesListener event subscriber
- // No need to load here as the loader is registered and will be called automatically
- return $this->translator->trans($id, $parameters, $domain, $locale);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getLocale(): string
- {
- return $this->translator->getLocale();
- }
-
- /**
- * {@inheritdoc}
- */
- public function setLocale(string $locale): void
- {
- $this->translator->setLocale($locale);
- }
-
- /**
- * Add all resources available in database.
- *
- * This method is called by DatabaseResourcesListener to register
- * database translation resources with the translator.
- */
- public function addDatabaseResources(): void
- {
- if ($this->isResourcesLoaded) {
- return;
- }
-
- $cache = new ConfigCache($this->cacheFile, $this->options['debug'] ?? false);
-
- if (!$cache->isFresh()) {
- $event = new GetDatabaseResourcesEvent();
- $this->container->get('event_dispatcher')->dispatch($event);
-
- $resources = $event->getResources();
- $metadata = [];
-
- foreach ($resources as $resource) {
- $metadata[] = new DatabaseFreshResource($resource['locale'], $resource['domain'] ?? 'messages');
- }
-
- $content = sprintf("write($content, $metadata);
- } else {
- $resources = include $this->cacheFile;
- }
-
- // Add resources using reflection to access protected addResource method
- // or use the public API if available in Symfony 8
- $reflection = new \ReflectionClass($this->translator);
- if ($reflection->hasMethod('addResource')) {
- $addResource = $reflection->getMethod('addResource');
- $addResource->setAccessible(true);
- foreach ($resources as $resource) {
- $addResource->invoke(
- $this->translator,
- 'database',
- 'DB',
- $resource['locale'],
- $resource['domain'] ?? 'messages'
- );
- }
- }
-
- $this->isResourcesLoaded = true;
- }
-
- /**
- * Remove the cache file corresponding to the given locale.
- *
- * @param string $locale
- * @return boolean
- */
- public function removeCacheFile(string $locale): bool
- {
- if (!file_exists($this->cacheFile)) {
- return true;
- }
-
- $localeExploded = explode('_', $locale);
- $finder = new Finder();
- $finder->files()->in($this->options['cache_dir'])->name(sprintf('/catalogue\.%s.*\.php$/', $localeExploded[0]));
- $deleted = true;
- foreach ($finder as $file) {
- $path = $file->getRealPath();
- $this->invalidateSystemCacheForFile($path);
- $deleted = unlink($path);
-
- $metadata = $path.'.meta';
- if (file_exists($metadata)) {
- $this->invalidateSystemCacheForFile($metadata);
- unlink($metadata);
- }
- }
-
- return $deleted;
- }
-
- /**
- * Remove the cache file corresponding to each given locale.
- */
- public function removeLocalesCacheFiles(array $locales): void
- {
- foreach ($locales as $locale) {
- $this->removeCacheFile($locale);
- }
-
- // also remove database.resources.php cache file
- $file = sprintf('%s/database.resources.php', $this->options['cache_dir']);
- if (file_exists($file)) {
- $this->invalidateSystemCacheForFile($file);
- unlink($file);
- }
-
- $metadata = $file.'.meta';
- if (file_exists($metadata)) {
- $this->invalidateSystemCacheForFile($metadata);
- unlink($metadata);
- }
-
- $this->isResourcesLoaded = false;
- }
-
- /**
- * @param string $path
- *
- * @throws \RuntimeException
- */
- protected function invalidateSystemCacheForFile(string $path): void
- {
- if (ini_get('apc.enabled') && function_exists('apc_delete_file')) {
- if (apc_exists($path) && !apc_delete_file($path)) {
- throw new \RuntimeException(sprintf('Failed to clear APC Cache for file %s', $path));
- }
- } elseif ('cli' === php_sapi_name() ? ini_get('opcache.enable_cli') : ini_get('opcache.enable')) {
- if (function_exists("opcache_invalidate") && !opcache_invalidate($path, true)) {
- throw new \RuntimeException(sprintf('Failed to clear OPCache for file %s', $path));
- }
- }
- }
-
- /**
- * Get the decorated translator instance.
- * Useful for accessing methods not in TranslatorInterface.
- */
- public function getDecoratedTranslator(): TranslatorInterface
- {
- return $this->translator;
- }
-}
diff --git a/Util/Csrf/CsrfCheckerTrait.php b/Util/Csrf/CsrfCheckerTrait.php
index 5a4de918..128b2855 100644
--- a/Util/Csrf/CsrfCheckerTrait.php
+++ b/Util/Csrf/CsrfCheckerTrait.php
@@ -2,8 +2,8 @@
namespace Lexik\Bundle\TranslationBundle\Util\Csrf;
-use Symfony\Component\Security\Csrf\CsrfTokenManager;
use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\Security\Csrf\CsrfTokenManager;
use Symfony\Contracts\Service\Attribute\Required;
/**
diff --git a/Util/DataGrid/DataGridFormatter.php b/Util/DataGrid/DataGridFormatter.php
index 95b6ee6b..20487632 100644
--- a/Util/DataGrid/DataGridFormatter.php
+++ b/Util/DataGrid/DataGridFormatter.php
@@ -3,53 +3,41 @@
namespace Lexik\Bundle\TranslationBundle\Util\DataGrid;
use Lexik\Bundle\TranslationBundle\Manager\LocaleManagerInterface;
+use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
-use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
/**
* @author Cédric Girard
*/
class DataGridFormatter
{
- /**
- * Constructor.
- *
- * @param string $storage
- */
- public function __construct(protected LocaleManagerInterface $localeManager, protected $storage)
- {
+ public function __construct(
+ protected LocaleManagerInterface $localeManager,
+ protected string $storage
+ ) {
}
/**
* Returns a JSON response with formatted data.
- *
- * @param array $transUnits
- * @param integer $total
- * @return \Symfony\Component\HttpFoundation\JsonResponse
*/
- public function createListResponse($transUnits, $total)
+ public function createListResponse(array $transUnits, int $total): JsonResponse
{
- return new JsonResponse(['translations' => $this->format($transUnits), 'total' => $total]);
+ return new JsonResponse(['translations' => $this->format($transUnits), 'total' => $total]);
}
/**
* Returns a JSON response with formatted data.
- *
- * @return \Symfony\Component\HttpFoundation\JsonResponse
*/
- public function createSingleResponse(mixed $transUnit)
+ public function createSingleResponse(mixed $transUnit): JsonResponse
{
return new JsonResponse($this->formatOne($transUnit));
}
/**
- * Format the tanslations list.
- *
- * @param array $transUnits
- * @return array
+ * Format the translations list.
*/
- protected function format($transUnits)
+ protected function format(array $transUnits): array
{
$formatted = [];
@@ -62,19 +50,20 @@ protected function format($transUnits)
/**
* Format a single TransUnit.
- *
- * @param array $transUnit
- * @return array
*/
- protected function formatOne($transUnit)
+ protected function formatOne(TransUnitInterface|array $transUnit): array
{
if (is_object($transUnit)) {
$transUnit = $this->toArray($transUnit);
- } elseif (StorageInterface::STORAGE_MONGODB == $this->storage) {
+ } elseif (StorageInterface::STORAGE_MONGODB === $this->storage) {
$transUnit['id'] = $transUnit['_id']->{'$id'};
}
- $formatted = ['_id' => $transUnit['id'], '_domain' => $transUnit['domain'], '_key' => $transUnit['key']];
+ $formatted = [
+ '_id' => $transUnit['id'],
+ '_domain' => $transUnit['domain'],
+ '_key' => $transUnit['key'],
+ ];
// add locales in the same order as in managed_locales param
foreach ($this->localeManager->getLocales() as $locale) {
@@ -83,7 +72,7 @@ protected function formatOne($transUnit)
// then fill locales value
foreach ($transUnit['translations'] as $translation) {
- if (in_array($translation['locale'], $this->localeManager->getLocales())) {
+ if (in_array($translation['locale'], $this->localeManager->getLocales(), true)) {
$formatted[$translation['locale']] = $translation['content'];
}
}
@@ -93,15 +82,18 @@ protected function formatOne($transUnit)
/**
* Convert a trans unit into an array.
- *
- * @return array
*/
- protected function toArray(TransUnitInterface $transUnit)
+ protected function toArray(TransUnitInterface $transUnit): array
{
- $data = ['id' => $transUnit->getId(), 'domain' => $transUnit->getDomain(), 'key' => $transUnit->getKey(), 'translations' => []];
+ $data = [
+ 'id' => $transUnit->getId(),
+ 'domain' => $transUnit->getDomain(),
+ 'key' => $transUnit->getKey(),
+ 'translations' => [],
+ ];
foreach ($transUnit->getTranslations() as $translation) {
- $data['translations'][] = ['locale' => $translation->getLocale(), 'content' => $translation->getContent()];
+ $data['translations'][] = ['locale' => $translation->getLocale(), 'content' => $translation->getContent()];
}
return $data;
diff --git a/Util/DataGrid/DataGridRequestHandler.php b/Util/DataGrid/DataGridRequestHandler.php
index 05a536fc..db847bc5 100644
--- a/Util/DataGrid/DataGridRequestHandler.php
+++ b/Util/DataGrid/DataGridRequestHandler.php
@@ -2,9 +2,10 @@
namespace Lexik\Bundle\TranslationBundle\Util\DataGrid;
+use Lexik\Bundle\TranslationBundle\Document\TransUnit as TransUnitDocument;
use Lexik\Bundle\TranslationBundle\Manager\FileManagerInterface;
use Lexik\Bundle\TranslationBundle\Manager\LocaleManagerInterface;
-use Lexik\Bundle\TranslationBundle\Document\TransUnit as TransUnitDocument;
+use Lexik\Bundle\TranslationBundle\Manager\TransUnitInterface;
use Lexik\Bundle\TranslationBundle\Manager\TransUnitManagerInterface;
use Lexik\Bundle\TranslationBundle\Model\TransUnit;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
@@ -152,12 +153,8 @@ public function getByToken($token)
/**
* Updates a trans unit from the request.
- *
- * @param integer $id
- * @throws NotFoundHttpException
- * @return \Lexik\Bundle\TranslationBundle\Model\TransUnit
*/
- public function updateFromRequest($id, Request $request)
+ public function updateFromRequest(int $id, Request $request): TransUnitInterface
{
$transUnit = $this->storage->getTransUnitById($id);
@@ -203,7 +200,7 @@ protected function filterTokenTranslations($transUnits, $count, $parameters)
if (count($filters) > 0) {
$end = count($transUnits);
- for ($i=0; $i<$end; $i++) {
+ for ($i = 0; $i < $end; $i++) {
$match = true;
foreach ($filters as $column => $str) {
diff --git a/Util/Overview/StatsAggregator.php b/Util/Overview/StatsAggregator.php
index 38add9b9..c3b012f6 100644
--- a/Util/Overview/StatsAggregator.php
+++ b/Util/Overview/StatsAggregator.php
@@ -32,9 +32,9 @@ public function getStats()
foreach ($this->localeManager->getLocales() as $locale) {
$localeCount = $byLocale[$locale] ?? 0;
- $stats[$domain][$locale] = ['keys' => $total,
+ $stats[$domain][$locale] = ['keys' => $total,
'translated' => $localeCount,
- 'completed' => ($total > 0) ? floor(($localeCount / $total) * 100) : 0,
+ 'completed' => ($total > 0) ? floor(($localeCount / $total) * 100) : 0,
];
}
}
diff --git a/composer.json b/composer.json
index 766aee90..b8aa5253 100644
--- a/composer.json
+++ b/composer.json
@@ -22,7 +22,7 @@
}
],
"require": {
- "php": "^8.1|^8.2|^8.3|^8.4",
+ "php": "^8.2|^8.3|^8.4",
"doctrine/orm": "^3",
"monolog/monolog": "^3.2",
"symfony/asset": "^7.0|^8.0",
@@ -41,7 +41,7 @@
"doctrine/annotations": "^2",
"doctrine/cache": "^1.4|^2.0",
"doctrine/data-fixtures": "^1.1|^2.0",
- "doctrine/doctrine-bundle": "^2.2",
+ "doctrine/doctrine-bundle": "^2.2 || ^3.0",
"doctrine/mongodb-odm": "^2.7",
"doctrine/mongodb-odm-bundle": "^5.0",
"friendsofphp/php-cs-fixer": "^3.64",
@@ -73,7 +73,6 @@
},
"config": {
"platform": {
- "php": "8.2.0",
"ext-mongodb": "2.1.4"
},
"sort-packages": true
diff --git a/composer.lock b/composer.lock
index fffd5241..8bf274fb 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "2f22c916da236e6c350a1e7cab9f61bf",
+ "content-hash": "b8d2269beaad4139f7b57df745e01ca2",
"packages": [
{
"name": "doctrine/collections",
@@ -94,16 +94,16 @@
},
{
"name": "doctrine/dbal",
- "version": "4.4.2",
+ "version": "4.4.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
- "reference": "476f7f0fa6ea4aa5364926db7fabdf6049075722"
+ "reference": "61e730f1658814821a85f2402c945f3883407dec"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/dbal/zipball/476f7f0fa6ea4aa5364926db7fabdf6049075722",
- "reference": "476f7f0fa6ea4aa5364926db7fabdf6049075722",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/61e730f1658814821a85f2402c945f3883407dec",
+ "reference": "61e730f1658814821a85f2402c945f3883407dec",
"shasum": ""
},
"require": {
@@ -180,7 +180,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
- "source": "https://github.com/doctrine/dbal/tree/4.4.2"
+ "source": "https://github.com/doctrine/dbal/tree/4.4.3"
},
"funding": [
{
@@ -196,7 +196,7 @@
"type": "tidelift"
}
],
- "time": "2026-02-26T12:12:19+00:00"
+ "time": "2026-03-20T08:52:12+00:00"
},
{
"name": "doctrine/deprecations",
@@ -248,63 +248,58 @@
},
{
"name": "doctrine/doctrine-bundle",
- "version": "2.18.2",
+ "version": "3.2.4",
"source": {
"type": "git",
"url": "https://github.com/doctrine/DoctrineBundle.git",
- "reference": "0ff098b29b8b3c68307c8987dcaed7fd829c6546"
+ "reference": "75f1bf75d0ba099f23e7d43ebd804df5bec58c29"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0ff098b29b8b3c68307c8987dcaed7fd829c6546",
- "reference": "0ff098b29b8b3c68307c8987dcaed7fd829c6546",
+ "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/75f1bf75d0ba099f23e7d43ebd804df5bec58c29",
+ "reference": "75f1bf75d0ba099f23e7d43ebd804df5bec58c29",
"shasum": ""
},
"require": {
- "doctrine/dbal": "^3.7.0 || ^4.0",
+ "doctrine/dbal": "^4.0",
"doctrine/deprecations": "^1.0",
- "doctrine/persistence": "^3.1 || ^4",
+ "doctrine/persistence": "^4",
"doctrine/sql-formatter": "^1.0.1",
- "php": "^8.1",
- "symfony/cache": "^6.4 || ^7.0",
- "symfony/config": "^6.4 || ^7.0",
- "symfony/console": "^6.4 || ^7.0",
- "symfony/dependency-injection": "^6.4 || ^7.0",
- "symfony/doctrine-bridge": "^6.4.3 || ^7.0.3",
- "symfony/framework-bundle": "^6.4 || ^7.0",
- "symfony/service-contracts": "^2.5 || ^3"
+ "php": "^8.4",
+ "symfony/cache": "^6.4 || ^7.0 || ^8.0",
+ "symfony/config": "^6.4 || ^7.0 || ^8.0",
+ "symfony/console": "^6.4 || ^7.0 || ^8.0",
+ "symfony/dependency-injection": "^6.4 || ^7.0 || ^8.0",
+ "symfony/doctrine-bridge": "^6.4.3 || ^7.0.3 || ^8.0",
+ "symfony/framework-bundle": "^6.4 || ^7.0 || ^8.0",
+ "symfony/service-contracts": "^3"
},
"conflict": {
- "doctrine/annotations": ">=3.0",
- "doctrine/cache": "< 1.11",
- "doctrine/orm": "<2.17 || >=4.0",
- "symfony/var-exporter": "< 6.4.1 || 7.0.0",
- "twig/twig": "<2.13 || >=3.0 <3.0.4"
+ "doctrine/orm": "<3.0 || >=4.0",
+ "twig/twig": "<3.0.4"
},
"require-dev": {
- "doctrine/annotations": "^1 || ^2",
- "doctrine/cache": "^1.11 || ^2.0",
"doctrine/coding-standard": "^14",
- "doctrine/orm": "^2.17 || ^3.1",
- "friendsofphp/proxy-manager-lts": "^1.0",
- "phpstan/phpstan": "2.1.1",
+ "doctrine/orm": "^3.4.4",
+ "phpstan/phpstan": "^2.1.13",
"phpstan/phpstan-phpunit": "2.0.3",
"phpstan/phpstan-strict-rules": "^2",
- "phpunit/phpunit": "^10.5.53 || ^12.3.10",
- "psr/log": "^1.1.4 || ^2.0 || ^3.0",
- "symfony/doctrine-messenger": "^6.4 || ^7.0",
- "symfony/expression-language": "^6.4 || ^7.0",
- "symfony/messenger": "^6.4 || ^7.0",
- "symfony/property-info": "^6.4 || ^7.0",
- "symfony/security-bundle": "^6.4 || ^7.0",
- "symfony/stopwatch": "^6.4 || ^7.0",
- "symfony/string": "^6.4 || ^7.0",
- "symfony/twig-bridge": "^6.4 || ^7.0",
- "symfony/validator": "^6.4 || ^7.0",
- "symfony/var-exporter": "^6.4.1 || ^7.0.1",
- "symfony/web-profiler-bundle": "^6.4 || ^7.0",
- "symfony/yaml": "^6.4 || ^7.0",
- "twig/twig": "^2.14.7 || ^3.0.4"
+ "phpstan/phpstan-symfony": "^2.0.9",
+ "phpunit/phpunit": "^12.3.10",
+ "psr/log": "^3.0",
+ "symfony/doctrine-messenger": "^6.4 || ^7.0 || ^8.0",
+ "symfony/expression-language": "^6.4 || ^7.0 || ^8.0",
+ "symfony/http-kernel": "^6.4 || ^7.0 || ^8.0",
+ "symfony/messenger": "^6.4 || ^7.0 || ^8.0",
+ "symfony/property-info": "^6.4 || ^7.0 || ^8.0",
+ "symfony/security-bundle": "^6.4 || ^7.0 || ^8.0",
+ "symfony/stopwatch": "^6.4 || ^7.0 || ^8.0",
+ "symfony/string": "^6.4 || ^7.0 || ^8.0",
+ "symfony/twig-bridge": "^6.4 || ^7.0 || ^8.0",
+ "symfony/validator": "^6.4 || ^7.0 || ^8.0",
+ "symfony/web-profiler-bundle": "^6.4 || ^7.0 || ^8.0",
+ "symfony/yaml": "^6.4 || ^7.0 || ^8.0",
+ "twig/twig": "^3.21.1"
},
"suggest": {
"doctrine/orm": "The Doctrine ORM integration is optional in the bundle.",
@@ -349,7 +344,7 @@
],
"support": {
"issues": "https://github.com/doctrine/DoctrineBundle/issues",
- "source": "https://github.com/doctrine/DoctrineBundle/tree/2.18.2"
+ "source": "https://github.com/doctrine/DoctrineBundle/tree/3.2.4"
},
"funding": [
{
@@ -365,41 +360,48 @@
"type": "tidelift"
}
],
- "time": "2025-12-20T21:35:32+00:00"
+ "time": "2026-06-09T19:11:55+00:00"
},
{
"name": "doctrine/doctrine-migrations-bundle",
- "version": "3.7.0",
+ "version": "4.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/DoctrineMigrationsBundle.git",
- "reference": "1e380c6dd8ac8488217f39cff6b77e367f1a644b"
+ "reference": "20505da78735744fb4a42a3bb9a416b345ad6f7c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1e380c6dd8ac8488217f39cff6b77e367f1a644b",
- "reference": "1e380c6dd8ac8488217f39cff6b77e367f1a644b",
+ "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/20505da78735744fb4a42a3bb9a416b345ad6f7c",
+ "reference": "20505da78735744fb4a42a3bb9a416b345ad6f7c",
"shasum": ""
},
"require": {
- "doctrine/doctrine-bundle": "^2.4 || ^3.0",
+ "doctrine/dbal": "^4",
+ "doctrine/doctrine-bundle": "^3",
"doctrine/migrations": "^3.2",
- "php": "^7.2 || ^8.0",
- "symfony/deprecation-contracts": "^2.1 || ^3",
- "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0"
+ "php": "^8.4",
+ "psr/log": "^3",
+ "symfony/config": "^6.4 || ^7.0 || ^8.0",
+ "symfony/console": "^6.4 || ^7.0 || ^8.0",
+ "symfony/dependency-injection": "^6.4 || ^7.0 || ^8.0",
+ "symfony/deprecation-contracts": "^3",
+ "symfony/framework-bundle": "^6.4 || ^7.0 || ^8.0",
+ "symfony/http-foundation": "^6.4 || ^7.0 || ^8.0",
+ "symfony/http-kernel": "^6.4 || ^7.0 || ^8.0",
+ "symfony/service-contracts": "^3.0"
},
"require-dev": {
"composer/semver": "^3.0",
- "doctrine/coding-standard": "^12 || ^14",
- "doctrine/orm": "^2.6 || ^3",
- "phpstan/phpstan": "^1.4 || ^2",
- "phpstan/phpstan-deprecation-rules": "^1 || ^2",
- "phpstan/phpstan-phpunit": "^1 || ^2",
- "phpstan/phpstan-strict-rules": "^1.1 || ^2",
- "phpstan/phpstan-symfony": "^1.3 || ^2",
- "phpunit/phpunit": "^8.5 || ^9.5",
- "symfony/phpunit-bridge": "^6.3 || ^7 || ^8",
- "symfony/var-exporter": "^5.4 || ^6 || ^7 || ^8"
+ "doctrine/coding-standard": "^14",
+ "doctrine/orm": "^3",
+ "phpstan/phpstan": "^2",
+ "phpstan/phpstan-deprecation-rules": "^2",
+ "phpstan/phpstan-phpunit": "^2",
+ "phpstan/phpstan-strict-rules": "^2",
+ "phpstan/phpstan-symfony": "^2",
+ "phpunit/phpunit": "^12.5",
+ "symfony/var-exporter": "^6.4 || ^7 || ^8"
},
"type": "symfony-bundle",
"autoload": {
@@ -434,7 +436,7 @@
],
"support": {
"issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues",
- "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.7.0"
+ "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/4.0.0"
},
"funding": [
{
@@ -450,7 +452,7 @@
"type": "tidelift"
}
],
- "time": "2025-11-15T19:02:59+00:00"
+ "time": "2025-12-05T08:14:38+00:00"
},
{
"name": "doctrine/event-manager",
@@ -635,30 +637,29 @@
},
{
"name": "doctrine/instantiator",
- "version": "2.0.0",
+ "version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
- "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0"
+ "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
- "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/23da848e1a2308728fe5fdddabf4be17ff9720c7",
+ "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7",
"shasum": ""
},
"require": {
- "php": "^8.1"
+ "php": "^8.4"
},
"require-dev": {
- "doctrine/coding-standard": "^11",
+ "doctrine/coding-standard": "^14",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^1.2",
- "phpstan/phpstan": "^1.9.4",
- "phpstan/phpstan-phpunit": "^1.3",
- "phpunit/phpunit": "^9.5.27",
- "vimeo/psalm": "^5.4"
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5.58"
},
"type": "library",
"autoload": {
@@ -685,7 +686,7 @@
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
- "source": "https://github.com/doctrine/instantiator/tree/2.0.0"
+ "source": "https://github.com/doctrine/instantiator/tree/2.1.0"
},
"funding": [
{
@@ -701,7 +702,7 @@
"type": "tidelift"
}
],
- "time": "2022-12-30T00:23:10+00:00"
+ "time": "2026-01-05T06:47:08+00:00"
},
{
"name": "doctrine/lexer",
@@ -782,16 +783,16 @@
},
{
"name": "doctrine/migrations",
- "version": "3.9.6",
+ "version": "3.9.7",
"source": {
"type": "git",
"url": "https://github.com/doctrine/migrations.git",
- "reference": "ffd8355cdd8505fc650d9604f058bf62aedd80a1"
+ "reference": "96cb2a89b56c9efb0bac38e606dc0b0f13e650ec"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/migrations/zipball/ffd8355cdd8505fc650d9604f058bf62aedd80a1",
- "reference": "ffd8355cdd8505fc650d9604f058bf62aedd80a1",
+ "url": "https://api.github.com/repos/doctrine/migrations/zipball/96cb2a89b56c9efb0bac38e606dc0b0f13e650ec",
+ "reference": "96cb2a89b56c9efb0bac38e606dc0b0f13e650ec",
"shasum": ""
},
"require": {
@@ -865,7 +866,7 @@
],
"support": {
"issues": "https://github.com/doctrine/migrations/issues",
- "source": "https://github.com/doctrine/migrations/tree/3.9.6"
+ "source": "https://github.com/doctrine/migrations/tree/3.9.7"
},
"funding": [
{
@@ -881,20 +882,20 @@
"type": "tidelift"
}
],
- "time": "2026-02-11T06:46:11+00:00"
+ "time": "2026-04-23T19:33:20+00:00"
},
{
"name": "doctrine/orm",
- "version": "3.6.2",
+ "version": "3.6.7",
"source": {
"type": "git",
"url": "https://github.com/doctrine/orm.git",
- "reference": "4262eb495b4d2a53b45de1ac58881e0091f2970f"
+ "reference": "bc217c0e19c3a9eadfa67697143b87c9ba01272c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/orm/zipball/4262eb495b4d2a53b45de1ac58881e0091f2970f",
- "reference": "4262eb495b4d2a53b45de1ac58881e0091f2970f",
+ "url": "https://api.github.com/repos/doctrine/orm/zipball/bc217c0e19c3a9eadfa67697143b87c9ba01272c",
+ "reference": "bc217c0e19c3a9eadfa67697143b87c9ba01272c",
"shasum": ""
},
"require": {
@@ -967,25 +968,26 @@
],
"support": {
"issues": "https://github.com/doctrine/orm/issues",
- "source": "https://github.com/doctrine/orm/tree/3.6.2"
+ "source": "https://github.com/doctrine/orm/tree/3.6.7"
},
- "time": "2026-01-30T21:41:41+00:00"
+ "time": "2026-05-25T16:45:47+00:00"
},
{
"name": "doctrine/persistence",
- "version": "4.1.1",
+ "version": "4.2.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/persistence.git",
- "reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09"
+ "reference": "49ab73e0d3e2ac8d1f5ecda3dd8acd5503781e8b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/persistence/zipball/b9c49ad3558bb77ef973f4e173f2e9c2eca9be09",
- "reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09",
+ "url": "https://api.github.com/repos/doctrine/persistence/zipball/49ab73e0d3e2ac8d1f5ecda3dd8acd5503781e8b",
+ "reference": "49ab73e0d3e2ac8d1f5ecda3dd8acd5503781e8b",
"shasum": ""
},
"require": {
+ "doctrine/deprecations": "^1",
"doctrine/event-manager": "^1 || ^2",
"php": "^8.1",
"psr/cache": "^1.0 || ^2.0 || ^3.0"
@@ -996,13 +998,13 @@
"phpstan/phpstan-phpunit": "^2",
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "^10.5.58 || ^12",
- "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0",
- "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0"
+ "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0 || ^8.0",
+ "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0 || ^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
- "Doctrine\\Persistence\\": "src/Persistence"
+ "Doctrine\\Persistence\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -1046,7 +1048,7 @@
],
"support": {
"issues": "https://github.com/doctrine/persistence/issues",
- "source": "https://github.com/doctrine/persistence/tree/4.1.1"
+ "source": "https://github.com/doctrine/persistence/tree/4.2.0"
},
"funding": [
{
@@ -1062,7 +1064,7 @@
"type": "tidelift"
}
],
- "time": "2025-10-16T20:13:18+00:00"
+ "time": "2026-04-26T12:12:52+00:00"
},
{
"name": "doctrine/sql-formatter",
@@ -1426,28 +1428,25 @@
},
{
"name": "symfony/asset",
- "version": "v7.4.6",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/asset.git",
- "reference": "d944ae87e4697af05aadeacfc5e603c3c18ef4fb"
+ "reference": "4bd4d143b7e53f40d45877df52eb2b18282bdac4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/asset/zipball/d944ae87e4697af05aadeacfc5e603c3c18ef4fb",
- "reference": "d944ae87e4697af05aadeacfc5e603c3c18ef4fb",
+ "url": "https://api.github.com/repos/symfony/asset/zipball/4bd4d143b7e53f40d45877df52eb2b18282bdac4",
+ "reference": "4bd4d143b7e53f40d45877df52eb2b18282bdac4",
"shasum": ""
},
"require": {
- "php": ">=8.2"
- },
- "conflict": {
- "symfony/http-foundation": "<6.4"
+ "php": ">=8.4.1"
},
"require-dev": {
- "symfony/http-client": "^6.4|^7.0|^8.0",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0"
+ "symfony/http-client": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -1475,7 +1474,7 @@
"description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/asset/tree/v7.4.6"
+ "source": "https://github.com/symfony/asset/tree/v8.1.0"
},
"funding": [
{
@@ -1495,38 +1494,33 @@
"type": "tidelift"
}
],
- "time": "2026-02-09T09:33:46+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/cache",
- "version": "v7.4.13",
+ "version": "v8.0.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache.git",
- "reference": "4c09e18a92cce126cc0d1155825279fca8cd0673"
+ "reference": "76ec84217eb39e4787d03928bba86a25cc859f76"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/cache/zipball/4c09e18a92cce126cc0d1155825279fca8cd0673",
- "reference": "4c09e18a92cce126cc0d1155825279fca8cd0673",
+ "url": "https://api.github.com/repos/symfony/cache/zipball/76ec84217eb39e4787d03928bba86a25cc859f76",
+ "reference": "76ec84217eb39e4787d03928bba86a25cc859f76",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4",
"psr/cache": "^2.0|^3.0",
"psr/log": "^1.1|^2|^3",
"symfony/cache-contracts": "^3.6",
- "symfony/deprecation-contracts": "^2.5|^3",
"symfony/service-contracts": "^2.5|^3",
- "symfony/var-exporter": "^6.4|^7.0|^8.0"
+ "symfony/var-exporter": "^7.4|^8.0"
},
"conflict": {
- "doctrine/dbal": "<3.6",
"ext-redis": "<6.1",
- "ext-relay": "<0.12.1",
- "symfony/dependency-injection": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/var-dumper": "<6.4"
+ "ext-relay": "<0.12.1"
},
"provide": {
"psr/cache-implementation": "2.0|3.0",
@@ -1535,16 +1529,16 @@
},
"require-dev": {
"cache/integration-tests": "dev-master",
- "doctrine/dbal": "^3.6|^4",
+ "doctrine/dbal": "^4.3",
"predis/predis": "^1.1|^2.0",
"psr/simple-cache": "^1.0|^2.0|^3.0",
- "symfony/clock": "^6.4|^7.0|^8.0",
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/filesystem": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
- "symfony/messenger": "^6.4|^7.0|^8.0",
- "symfony/var-dumper": "^6.4|^7.0|^8.0"
+ "symfony/clock": "^7.4|^8.0",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/filesystem": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/messenger": "^7.4|^8.0",
+ "symfony/var-dumper": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -1579,7 +1573,7 @@
"psr6"
],
"support": {
- "source": "https://github.com/symfony/cache/tree/v7.4.13"
+ "source": "https://github.com/symfony/cache/tree/v8.0.14"
},
"funding": [
{
@@ -1599,20 +1593,20 @@
"type": "tidelift"
}
],
- "time": "2026-05-24T08:43:14+00:00"
+ "time": "2026-06-17T15:00:27+00:00"
},
{
"name": "symfony/cache-contracts",
- "version": "v3.7.0",
+ "version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache-contracts.git",
- "reference": "225e8a254166bd3442e370c6f50145465db63831"
+ "reference": "9789738bc19af1106dc54d6afba9a0b467516cf2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/225e8a254166bd3442e370c6f50145465db63831",
- "reference": "225e8a254166bd3442e370c6f50145465db63831",
+ "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/9789738bc19af1106dc54d6afba9a0b467516cf2",
+ "reference": "9789738bc19af1106dc54d6afba9a0b467516cf2",
"shasum": ""
},
"require": {
@@ -1659,7 +1653,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/cache-contracts/tree/v3.7.0"
+ "source": "https://github.com/symfony/cache-contracts/tree/v3.7.1"
},
"funding": [
{
@@ -1679,38 +1673,37 @@
"type": "tidelift"
}
],
- "time": "2026-05-05T15:33:14+00:00"
+ "time": "2026-06-05T06:23:12+00:00"
},
{
"name": "symfony/config",
- "version": "v7.4.7",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "6c17162555bfb58957a55bb0e43e00035b6ae3d5"
+ "reference": "c18ae45733f9a5006ba81a13047d08a93e0dea1c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/6c17162555bfb58957a55bb0e43e00035b6ae3d5",
- "reference": "6c17162555bfb58957a55bb0e43e00035b6ae3d5",
+ "url": "https://api.github.com/repos/symfony/config/zipball/c18ae45733f9a5006ba81a13047d08a93e0dea1c",
+ "reference": "c18ae45733f9a5006ba81a13047d08a93e0dea1c",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/filesystem": "^7.1|^8.0",
- "symfony/polyfill-ctype": "~1.8"
+ "symfony/filesystem": "^7.4|^8.0",
+ "symfony/polyfill-ctype": "^1.8"
},
"conflict": {
- "symfony/finder": "<6.4",
"symfony/service-contracts": "<2.5"
},
"require-dev": {
- "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
- "symfony/finder": "^6.4|^7.0|^8.0",
- "symfony/messenger": "^6.4|^7.0|^8.0",
+ "symfony/event-dispatcher": "^7.4|^8.0",
+ "symfony/finder": "^7.4|^8.0",
+ "symfony/messenger": "^7.4|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/yaml": "^6.4|^7.0|^8.0"
+ "symfony/yaml": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -1738,7 +1731,7 @@
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/config/tree/v7.4.7"
+ "source": "https://github.com/symfony/config/tree/v8.1.1"
},
"funding": [
{
@@ -1758,51 +1751,43 @@
"type": "tidelift"
}
],
- "time": "2026-03-06T10:41:14+00:00"
+ "time": "2026-06-09T10:54:51+00:00"
},
{
"name": "symfony/console",
- "version": "v7.4.7",
+ "version": "v8.0.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d"
+ "reference": "e2a77289192c413abfe54f1d507159f911a20728"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d",
- "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d",
+ "url": "https://api.github.com/repos/symfony/console/zipball/e2a77289192c413abfe54f1d507159f911a20728",
+ "reference": "e2a77289192c413abfe54f1d507159f911a20728",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3",
- "symfony/polyfill-mbstring": "~1.0",
+ "php": ">=8.4",
+ "symfony/polyfill-mbstring": "^1.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/string": "^7.2|^8.0"
- },
- "conflict": {
- "symfony/dependency-injection": "<6.4",
- "symfony/dotenv": "<6.4",
- "symfony/event-dispatcher": "<6.4",
- "symfony/lock": "<6.4",
- "symfony/process": "<6.4"
+ "symfony/string": "^7.4|^8.0"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
- "symfony/lock": "^6.4|^7.0|^8.0",
- "symfony/messenger": "^6.4|^7.0|^8.0",
- "symfony/process": "^6.4|^7.0|^8.0",
- "symfony/stopwatch": "^6.4|^7.0|^8.0",
- "symfony/var-dumper": "^6.4|^7.0|^8.0"
+ "symfony/config": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/event-dispatcher": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/lock": "^7.4|^8.0",
+ "symfony/messenger": "^7.4|^8.0",
+ "symfony/process": "^7.4|^8.0",
+ "symfony/stopwatch": "^7.4|^8.0",
+ "symfony/var-dumper": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -1836,7 +1821,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.4.7"
+ "source": "https://github.com/symfony/console/tree/v8.0.14"
},
"funding": [
{
@@ -1856,43 +1841,40 @@
"type": "tidelift"
}
],
- "time": "2026-03-06T14:06:20+00:00"
+ "time": "2026-06-16T12:45:11+00:00"
},
{
"name": "symfony/dependency-injection",
- "version": "v7.4.7",
+ "version": "v8.0.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db"
+ "reference": "55d83c634f0bd7d6b5f64be8950dc389dca17a17"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db",
- "reference": "0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/55d83c634f0bd7d6b5f64be8950dc389dca17a17",
+ "reference": "55d83c634f0bd7d6b5f64be8950dc389dca17a17",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4",
"psr/container": "^1.1|^2.0",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/service-contracts": "^3.6",
- "symfony/var-exporter": "^6.4.20|^7.2.5|^8.0"
+ "symfony/var-exporter": "^7.4|^8.0"
},
"conflict": {
- "ext-psr": "<1.1|>=2",
- "symfony/config": "<6.4",
- "symfony/finder": "<6.4",
- "symfony/yaml": "<6.4"
+ "ext-psr": "<1.1|>=2"
},
"provide": {
"psr/container-implementation": "1.1|2.0",
"symfony/service-implementation": "1.1|2.0|3.0"
},
"require-dev": {
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/yaml": "^6.4|^7.0|^8.0"
+ "symfony/config": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/yaml": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -1920,7 +1902,7 @@
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/dependency-injection/tree/v7.4.7"
+ "source": "https://github.com/symfony/dependency-injection/tree/v8.0.14"
},
"funding": [
{
@@ -1940,20 +1922,20 @@
"type": "tidelift"
}
],
- "time": "2026-03-03T07:48:48+00:00"
+ "time": "2026-06-27T06:17:20+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.7.0",
+ "version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b"
+ "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b",
- "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d",
+ "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d",
"shasum": ""
},
"require": {
@@ -1991,7 +1973,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1"
},
"funding": [
{
@@ -2011,72 +1993,63 @@
"type": "tidelift"
}
],
- "time": "2026-04-13T15:52:40+00:00"
+ "time": "2026-06-05T06:23:12+00:00"
},
{
"name": "symfony/doctrine-bridge",
- "version": "v7.4.7",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/doctrine-bridge.git",
- "reference": "4fc5e2dd41be3c0b6321e0373072782edeff45ed"
+ "reference": "883547207ff3b77c5cec9f4f16dd330ccd7b2849"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/4fc5e2dd41be3c0b6321e0373072782edeff45ed",
- "reference": "4fc5e2dd41be3c0b6321e0373072782edeff45ed",
+ "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/883547207ff3b77c5cec9f4f16dd330ccd7b2849",
+ "reference": "883547207ff3b77c5cec9f4f16dd330ccd7b2849",
"shasum": ""
},
"require": {
"doctrine/event-manager": "^2",
"doctrine/persistence": "^3.1|^4",
- "php": ">=8.2",
+ "php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-mbstring": "^1.0",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
"doctrine/collections": "<1.8",
- "doctrine/dbal": "<3.6",
+ "doctrine/dbal": "<4.3",
"doctrine/lexer": "<1.1",
- "doctrine/orm": "<2.15",
- "symfony/cache": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/form": "<6.4.6|>=7,<7.0.6",
- "symfony/http-foundation": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/lock": "<6.4",
- "symfony/messenger": "<6.4",
- "symfony/property-info": "<6.4",
- "symfony/security-bundle": "<6.4",
- "symfony/security-core": "<6.4",
- "symfony/validator": "<7.4"
+ "doctrine/orm": "<3.4",
+ "symfony/property-info": "<8.0"
},
"require-dev": {
"doctrine/collections": "^1.8|^2.0",
"doctrine/data-fixtures": "^1.1|^2",
- "doctrine/dbal": "^3.6|^4",
- "doctrine/orm": "^2.15|^3",
+ "doctrine/dbal": "^4.3",
+ "doctrine/orm": "^3.4",
"psr/log": "^1|^2|^3",
- "symfony/cache": "^6.4|^7.0|^8.0",
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/doctrine-messenger": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/form": "^7.2|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
- "symfony/lock": "^6.4|^7.0|^8.0",
- "symfony/messenger": "^6.4|^7.0|^8.0",
- "symfony/property-access": "^6.4|^7.0|^8.0",
- "symfony/property-info": "^6.4|^7.0|^8.0",
- "symfony/security-core": "^6.4|^7.0|^8.0",
- "symfony/stopwatch": "^6.4|^7.0|^8.0",
- "symfony/translation": "^6.4|^7.0|^8.0",
- "symfony/type-info": "^7.1.8|^8.0",
- "symfony/uid": "^6.4|^7.0|^8.0",
+ "symfony/cache": "^7.4|^8.0",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/console": "^8.1",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/doctrine-messenger": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/form": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/lock": "^7.4|^8.0",
+ "symfony/messenger": "^7.4|^8.0",
+ "symfony/property-access": "^7.4|^8.0",
+ "symfony/property-info": "^8.0",
+ "symfony/security-core": "^7.4|^8.0",
+ "symfony/stopwatch": "^7.4|^8.0",
+ "symfony/translation": "^7.4|^8.0",
+ "symfony/type-info": "^7.4|^8.0",
+ "symfony/uid": "^7.4|^8.0",
"symfony/validator": "^7.4|^8.0",
- "symfony/var-dumper": "^6.4|^7.0|^8.0"
+ "symfony/var-dumper": "^7.4|^8.0"
},
"type": "symfony-bridge",
"autoload": {
@@ -2104,7 +2077,7 @@
"description": "Provides integration for Doctrine with various Symfony components",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/doctrine-bridge/tree/v7.4.7"
+ "source": "https://github.com/symfony/doctrine-bridge/tree/v8.1.1"
},
"funding": [
{
@@ -2124,37 +2097,36 @@
"type": "tidelift"
}
],
- "time": "2026-03-05T08:16:50+00:00"
+ "time": "2026-06-12T08:43:41+00:00"
},
{
"name": "symfony/error-handler",
- "version": "v7.4.8",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa"
+ "reference": "d8aeb1abd3fef84795567850d3a567bdb5945ee5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa",
- "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/d8aeb1abd3fef84795567850d3a567bdb5945ee5",
+ "reference": "d8aeb1abd3fef84795567850d3a567bdb5945ee5",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4.1",
"psr/log": "^1|^2|^3",
"symfony/polyfill-php85": "^1.32",
- "symfony/var-dumper": "^6.4|^7.0|^8.0"
+ "symfony/var-dumper": "^7.4|^8.0"
},
"conflict": {
- "symfony/deprecation-contracts": "<2.5",
- "symfony/http-kernel": "<6.4"
+ "symfony/deprecation-contracts": "<2.5"
},
"require-dev": {
- "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/console": "^7.4|^8.0",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
- "symfony/serializer": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/serializer": "^7.4|^8.0",
"symfony/webpack-encore-bundle": "^1.0|^2.0"
},
"bin": [
@@ -2186,7 +2158,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/error-handler/tree/v7.4.8"
+ "source": "https://github.com/symfony/error-handler/tree/v8.1.0"
},
"funding": [
{
@@ -2206,28 +2178,29 @@
"type": "tidelift"
}
],
- "time": "2026-03-24T13:12:05+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v7.4.9",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "e4a2e29753c7801f7a8340e066cfa788f3bc8101"
+ "reference": "abd6c11dc468725d1627302ad10f6cd486e9e3d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e4a2e29753c7801f7a8340e066cfa788f3bc8101",
- "reference": "e4a2e29753c7801f7a8340e066cfa788f3bc8101",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/abd6c11dc468725d1627302ad10f6cd486e9e3d0",
+ "reference": "abd6c11dc468725d1627302ad10f6cd486e9e3d0",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/event-dispatcher-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/dependency-injection": "<6.4",
+ "symfony/security-http": "<7.4",
"symfony/service-contracts": "<2.5"
},
"provide": {
@@ -2236,14 +2209,14 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/error-handler": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/framework-bundle": "^6.4|^7.0|^8.0",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/error-handler": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/framework-bundle": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/stopwatch": "^6.4|^7.0|^8.0"
+ "symfony/stopwatch": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -2271,7 +2244,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.9"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v8.1.1"
},
"funding": [
{
@@ -2291,20 +2264,20 @@
"type": "tidelift"
}
],
- "time": "2026-04-18T13:18:21+00:00"
+ "time": "2026-06-09T12:28:30+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
- "version": "v3.7.0",
+ "version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
- "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32"
+ "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/ccba7060602b7fed0b03c85bf025257f76d9ef32",
- "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c7de7a00ffb67842132da02ea92988a39ccd9f4e",
+ "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e",
"shasum": ""
},
"require": {
@@ -2351,7 +2324,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.0"
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.1"
},
"funding": [
{
@@ -2371,29 +2344,30 @@
"type": "tidelift"
}
],
- "time": "2026-01-05T13:30:16+00:00"
+ "time": "2026-06-05T06:23:12+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v7.4.6",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e"
+ "reference": "99aec13b82b4967ec5088222c4a3ecca955949c2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e",
- "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/99aec13b82b4967ec5088222c4a3ecca955949c2",
+ "reference": "99aec13b82b4967ec5088222c4a3ecca955949c2",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
"require-dev": {
- "symfony/process": "^6.4|^7.0|^8.0"
+ "symfony/process": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -2421,7 +2395,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v7.4.6"
+ "source": "https://github.com/symfony/filesystem/tree/v8.1.0"
},
"funding": [
{
@@ -2441,27 +2415,27 @@
"type": "tidelift"
}
],
- "time": "2026-02-25T16:50:00+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/finder",
- "version": "v7.4.6",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf"
+ "reference": "e2989e762c70f9490fa3a00a0ac0fae5aa97a531"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf",
- "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/e2989e762c70f9490fa3a00a0ac0fae5aa97a531",
+ "reference": "e2989e762c70f9490fa3a00a0ac0fae5aa97a531",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "php": ">=8.4.1"
},
"require-dev": {
- "symfony/filesystem": "^6.4|^7.0|^8.0"
+ "symfony/filesystem": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -2489,7 +2463,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v7.4.6"
+ "source": "https://github.com/symfony/finder/tree/v8.1.1"
},
"funding": [
{
@@ -2509,62 +2483,54 @@
"type": "tidelift"
}
],
- "time": "2026-01-29T09:40:50+00:00"
+ "time": "2026-06-27T09:05:56+00:00"
},
{
"name": "symfony/form",
- "version": "v7.4.7",
+ "version": "v8.0.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/form.git",
- "reference": "5f24175103fd0a62b98442207c240688210fd88b"
+ "reference": "36b007caa7fa08be969fee0bf341f6b99dd15000"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/form/zipball/5f24175103fd0a62b98442207c240688210fd88b",
- "reference": "5f24175103fd0a62b98442207c240688210fd88b",
+ "url": "https://api.github.com/repos/symfony/form/zipball/36b007caa7fa08be969fee0bf341f6b99dd15000",
+ "reference": "36b007caa7fa08be969fee0bf341f6b99dd15000",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3",
- "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
- "symfony/options-resolver": "^7.3|^8.0",
- "symfony/polyfill-ctype": "~1.8",
+ "php": ">=8.4",
+ "symfony/event-dispatcher": "^7.4|^8.0",
+ "symfony/options-resolver": "^7.4|^8.0",
+ "symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-intl-icu": "^1.21",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/property-access": "^6.4|^7.0|^8.0",
+ "symfony/polyfill-mbstring": "^1.0",
+ "symfony/property-access": "^7.4|^8.0",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/console": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/doctrine-bridge": "<6.4",
- "symfony/error-handler": "<6.4",
- "symfony/framework-bundle": "<6.4",
- "symfony/http-kernel": "<6.4",
"symfony/intl": "<7.4",
- "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
"symfony/translation-contracts": "<2.5",
- "symfony/twig-bridge": "<6.4"
+ "symfony/validator": "<7.4"
},
"require-dev": {
"doctrine/collections": "^1.0|^2.0",
- "symfony/clock": "^6.4|^7.0|^8.0",
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/console": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/html-sanitizer": "^6.4|^7.0|^8.0",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/clock": "^7.4|^8.0",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/console": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/html-sanitizer": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
"symfony/intl": "^7.4|^8.0",
- "symfony/security-core": "^6.4|^7.0|^8.0",
- "symfony/security-csrf": "^6.4|^7.0|^8.0",
- "symfony/translation": "^6.4.3|^7.0.3|^8.0",
- "symfony/uid": "^6.4|^7.0|^8.0",
- "symfony/validator": "^6.4.12|^7.1.5|^8.0",
- "symfony/var-dumper": "^6.4|^7.0|^8.0"
+ "symfony/security-core": "^7.4|^8.0",
+ "symfony/security-csrf": "^7.4|^8.0",
+ "symfony/translation": "^7.4|^8.0",
+ "symfony/uid": "^7.4|^8.0",
+ "symfony/validator": "^7.4|^8.0",
+ "symfony/var-dumper": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -2592,7 +2558,7 @@
"description": "Allows to easily create, process and reuse HTML forms",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/form/tree/v7.4.7"
+ "source": "https://github.com/symfony/form/tree/v8.0.14"
},
"funding": [
{
@@ -2612,37 +2578,37 @@
"type": "tidelift"
}
],
- "time": "2026-03-05T12:30:09+00:00"
+ "time": "2026-06-16T16:02:37+00:00"
},
{
"name": "symfony/framework-bundle",
- "version": "v7.4.7",
+ "version": "v8.0.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/framework-bundle.git",
- "reference": "c94bc78c85d76af67918404a95d44940f66a7c2f"
+ "reference": "74134f73e391698bf78b3dd05bb25a0bdfccbabb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c94bc78c85d76af67918404a95d44940f66a7c2f",
- "reference": "c94bc78c85d76af67918404a95d44940f66a7c2f",
+ "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/74134f73e391698bf78b3dd05bb25a0bdfccbabb",
+ "reference": "74134f73e391698bf78b3dd05bb25a0bdfccbabb",
"shasum": ""
},
"require": {
"composer-runtime-api": ">=2.1",
"ext-xml": "*",
- "php": ">=8.2",
- "symfony/cache": "^6.4.12|^7.0|^8.0",
+ "php": ">=8.4",
+ "symfony/cache": "^7.4|^8.0",
"symfony/config": "^7.4.4|^8.0.4",
"symfony/dependency-injection": "^7.4.4|^8.0.4",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/error-handler": "^7.3|^8.0",
- "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
- "symfony/filesystem": "^7.1|^8.0",
- "symfony/finder": "^6.4|^7.0|^8.0",
+ "symfony/error-handler": "^7.4|^8.0",
+ "symfony/event-dispatcher": "^7.4|^8.0",
+ "symfony/filesystem": "^7.4|^8.0",
+ "symfony/finder": "^7.4|^8.0",
"symfony/http-foundation": "^7.4|^8.0",
"symfony/http-kernel": "^7.4|^8.0",
- "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php85": "^1.32",
"symfony/routing": "^7.4|^8.0"
},
@@ -2650,79 +2616,62 @@
"doctrine/persistence": "<1.3",
"phpdocumentor/reflection-docblock": "<5.2|>=7",
"phpdocumentor/type-resolver": "<1.5.1",
- "symfony/asset": "<6.4",
- "symfony/asset-mapper": "<6.4",
- "symfony/clock": "<6.4",
- "symfony/console": "<6.4",
- "symfony/dom-crawler": "<6.4",
- "symfony/dotenv": "<6.4",
+ "symfony/console": "<7.4",
"symfony/form": "<7.4",
- "symfony/http-client": "<6.4",
- "symfony/lock": "<6.4",
- "symfony/mailer": "<6.4",
+ "symfony/json-streamer": "<7.4",
"symfony/messenger": "<7.4",
- "symfony/mime": "<6.4",
- "symfony/property-access": "<6.4",
- "symfony/property-info": "<6.4",
- "symfony/runtime": "<6.4.13|>=7.0,<7.1.6",
- "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4",
- "symfony/security-core": "<6.4",
- "symfony/security-csrf": "<7.2",
- "symfony/serializer": "<7.2.5",
- "symfony/stopwatch": "<6.4",
- "symfony/translation": "<7.3",
- "symfony/twig-bridge": "<6.4",
- "symfony/twig-bundle": "<6.4",
- "symfony/validator": "<6.4",
- "symfony/web-profiler-bundle": "<6.4",
- "symfony/webhook": "<7.2",
+ "symfony/mime": "<7.4.9|>=8.0,<8.0.9",
+ "symfony/security-csrf": "<7.4",
+ "symfony/serializer": "<7.4",
+ "symfony/translation": "<7.4",
+ "symfony/webhook": "<7.4",
"symfony/workflow": "<7.4"
},
"require-dev": {
"doctrine/persistence": "^1.3|^2|^3",
"dragonmantank/cron-expression": "^3.1",
"phpdocumentor/reflection-docblock": "^5.2|^6.0",
+ "phpstan/phpdoc-parser": "^1.0|^2.0",
"seld/jsonlint": "^1.10",
- "symfony/asset": "^6.4|^7.0|^8.0",
- "symfony/asset-mapper": "^6.4|^7.0|^8.0",
- "symfony/browser-kit": "^6.4|^7.0|^8.0",
- "symfony/clock": "^6.4|^7.0|^8.0",
- "symfony/console": "^6.4|^7.0|^8.0",
- "symfony/css-selector": "^6.4|^7.0|^8.0",
- "symfony/dom-crawler": "^6.4|^7.0|^8.0",
- "symfony/dotenv": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/asset": "^7.4|^8.0",
+ "symfony/asset-mapper": "^7.4|^8.0",
+ "symfony/browser-kit": "^7.4|^8.0",
+ "symfony/clock": "^7.4|^8.0",
+ "symfony/console": "^7.4|^8.0",
+ "symfony/css-selector": "^7.4|^8.0",
+ "symfony/dom-crawler": "^7.4|^8.0",
+ "symfony/dotenv": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
"symfony/form": "^7.4|^8.0",
- "symfony/html-sanitizer": "^6.4|^7.0|^8.0",
- "symfony/http-client": "^6.4|^7.0|^8.0",
- "symfony/json-streamer": "^7.3|^8.0",
- "symfony/lock": "^6.4|^7.0|^8.0",
- "symfony/mailer": "^6.4|^7.0|^8.0",
+ "symfony/html-sanitizer": "^7.4|^8.0",
+ "symfony/http-client": "^7.4|^8.0",
+ "symfony/json-streamer": "^7.4|^8.0",
+ "symfony/lock": "^7.4|^8.0",
+ "symfony/mailer": "^7.4|^8.0",
"symfony/messenger": "^7.4|^8.0",
- "symfony/mime": "^6.4|^7.0|^8.0",
- "symfony/notifier": "^6.4|^7.0|^8.0",
- "symfony/object-mapper": "^7.3|^8.0",
- "symfony/polyfill-intl-icu": "~1.0",
- "symfony/process": "^6.4|^7.0|^8.0",
- "symfony/property-info": "^6.4|^7.0|^8.0",
- "symfony/rate-limiter": "^6.4|^7.0|^8.0",
- "symfony/runtime": "^6.4.13|^7.1.6|^8.0",
- "symfony/scheduler": "^6.4.4|^7.0.4|^8.0",
- "symfony/security-bundle": "^6.4|^7.0|^8.0",
- "symfony/semaphore": "^6.4|^7.0|^8.0",
- "symfony/serializer": "^7.2.5|^8.0",
- "symfony/stopwatch": "^6.4|^7.0|^8.0",
- "symfony/string": "^6.4|^7.0|^8.0",
- "symfony/translation": "^7.3|^8.0",
- "symfony/twig-bundle": "^6.4|^7.0|^8.0",
- "symfony/type-info": "^7.1.8|^8.0",
- "symfony/uid": "^6.4|^7.0|^8.0",
+ "symfony/mime": "^7.4.9|^8.0.9",
+ "symfony/notifier": "^7.4|^8.0",
+ "symfony/object-mapper": "^7.4.9|^8.0.9",
+ "symfony/polyfill-intl-icu": "^1.0",
+ "symfony/process": "^7.4|^8.0",
+ "symfony/property-info": "^7.4|^8.0",
+ "symfony/rate-limiter": "^7.4|^8.0",
+ "symfony/runtime": "^7.4|^8.0",
+ "symfony/scheduler": "^7.4|^8.0",
+ "symfony/security-bundle": "^7.4|^8.0",
+ "symfony/semaphore": "^7.4|^8.0",
+ "symfony/serializer": "^7.4|^8.0",
+ "symfony/stopwatch": "^7.4|^8.0",
+ "symfony/string": "^7.4|^8.0",
+ "symfony/translation": "^7.4|^8.0",
+ "symfony/twig-bundle": "^7.4|^8.0",
+ "symfony/type-info": "^7.4.1|^8.0.1",
+ "symfony/uid": "^7.4|^8.0",
"symfony/validator": "^7.4|^8.0",
- "symfony/web-link": "^6.4|^7.0|^8.0",
- "symfony/webhook": "^7.2|^8.0",
+ "symfony/web-link": "^7.4|^8.0",
+ "symfony/webhook": "^7.4|^8.0",
"symfony/workflow": "^7.4|^8.0",
- "symfony/yaml": "^7.3|^8.0",
- "twig/twig": "^3.12"
+ "symfony/yaml": "^7.4|^8.0"
},
"type": "symfony-bundle",
"autoload": {
@@ -2750,7 +2699,7 @@
"description": "Provides a tight integration between Symfony components and the Symfony full-stack framework",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/framework-bundle/tree/v7.4.7"
+ "source": "https://github.com/symfony/framework-bundle/tree/v8.0.14"
},
"funding": [
{
@@ -2770,41 +2719,40 @@
"type": "tidelift"
}
],
- "time": "2026-03-06T15:39:55+00:00"
+ "time": "2026-06-27T08:56:37+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v7.4.13",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "bc354f47c62301e990b7874fa662326368508e2c"
+ "reference": "6a168c8fcee806b57ac020244da14293d1f9a883"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/bc354f47c62301e990b7874fa662326368508e2c",
- "reference": "bc354f47c62301e990b7874fa662326368508e2c",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6a168c8fcee806b57ac020244da14293d1f9a883",
+ "reference": "6a168c8fcee806b57ac020244da14293d1f9a883",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "^1.1"
},
"conflict": {
- "doctrine/dbal": "<3.6",
- "symfony/cache": "<6.4.12|>=7.0,<7.1.5"
+ "doctrine/dbal": "<4.3"
},
"require-dev": {
- "doctrine/dbal": "^3.6|^4",
+ "doctrine/dbal": "^4.3",
"predis/predis": "^1.1|^2.0",
- "symfony/cache": "^6.4.12|^7.1.5|^8.0",
- "symfony/clock": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
- "symfony/mime": "^6.4|^7.0|^8.0",
- "symfony/rate-limiter": "^6.4|^7.0|^8.0"
+ "symfony/cache": "^7.4|^8.0",
+ "symfony/clock": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/mime": "^7.4|^8.0",
+ "symfony/rate-limiter": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -2832,7 +2780,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v7.4.13"
+ "source": "https://github.com/symfony/http-foundation/tree/v8.1.1"
},
"funding": [
{
@@ -2852,78 +2800,63 @@
"type": "tidelift"
}
],
- "time": "2026-05-24T11:20:33+00:00"
+ "time": "2026-06-12T08:43:41+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v7.4.13",
+ "version": "v8.0.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "9df847980c436451f4f51d1284491bb4356dd989"
+ "reference": "6685b981881100e5f92a98fb6c5d6739af6a8569"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/9df847980c436451f4f51d1284491bb4356dd989",
- "reference": "9df847980c436451f4f51d1284491bb4356dd989",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6685b981881100e5f92a98fb6c5d6739af6a8569",
+ "reference": "6685b981881100e5f92a98fb6c5d6739af6a8569",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4",
"psr/log": "^1|^2|^3",
- "symfony/deprecation-contracts": "^2.5|^3",
- "symfony/error-handler": "^6.4|^7.0|^8.0",
- "symfony/event-dispatcher": "^7.3|^8.0",
+ "symfony/error-handler": "^7.4|^8.0",
+ "symfony/event-dispatcher": "^7.4|^8.0",
"symfony/http-foundation": "^7.4|^8.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
- "symfony/browser-kit": "<6.4",
- "symfony/cache": "<6.4",
- "symfony/config": "<6.4",
- "symfony/console": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/doctrine-bridge": "<6.4",
"symfony/flex": "<2.10",
- "symfony/form": "<6.4",
- "symfony/http-client": "<6.4",
"symfony/http-client-contracts": "<2.5",
- "symfony/mailer": "<6.4",
- "symfony/messenger": "<6.4",
- "symfony/translation": "<6.4",
"symfony/translation-contracts": "<2.5",
- "symfony/twig-bridge": "<6.4",
- "symfony/validator": "<6.4",
- "symfony/var-dumper": "<6.4",
- "twig/twig": "<3.12"
+ "twig/twig": "<3.21"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/cache": "^1.0|^2.0|^3.0",
- "symfony/browser-kit": "^6.4|^7.0|^8.0",
- "symfony/clock": "^6.4|^7.0|^8.0",
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/console": "^6.4|^7.0|^8.0",
- "symfony/css-selector": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4.1|^7.0.1|^8.0",
- "symfony/dom-crawler": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/finder": "^6.4|^7.0|^8.0",
+ "symfony/browser-kit": "^7.4|^8.0",
+ "symfony/clock": "^7.4|^8.0",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/console": "^7.4|^8.0",
+ "symfony/css-selector": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/dom-crawler": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/finder": "^7.4|^8.0",
"symfony/http-client-contracts": "^2.5|^3",
- "symfony/process": "^6.4|^7.0|^8.0",
- "symfony/property-access": "^7.1|^8.0",
- "symfony/routing": "^6.4|^7.0|^8.0",
- "symfony/serializer": "^7.1|^8.0",
- "symfony/stopwatch": "^6.4|^7.0|^8.0",
- "symfony/translation": "^6.4|^7.0|^8.0",
+ "symfony/process": "^7.4|^8.0",
+ "symfony/property-access": "^7.4|^8.0",
+ "symfony/routing": "^7.4|^8.0",
+ "symfony/serializer": "^7.4|^8.0",
+ "symfony/stopwatch": "^7.4|^8.0",
+ "symfony/translation": "^7.4|^8.0",
"symfony/translation-contracts": "^2.5|^3",
- "symfony/uid": "^6.4|^7.0|^8.0",
- "symfony/validator": "^6.4|^7.0|^8.0",
- "symfony/var-dumper": "^6.4|^7.0|^8.0",
- "symfony/var-exporter": "^6.4|^7.0|^8.0",
- "twig/twig": "^3.12"
+ "symfony/uid": "^7.4|^8.0",
+ "symfony/validator": "^7.4|^8.0",
+ "symfony/var-dumper": "^7.4|^8.0",
+ "symfony/var-exporter": "^7.4|^8.0",
+ "twig/twig": "^3.21"
},
"type": "library",
"autoload": {
@@ -2951,7 +2884,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-kernel/tree/v7.4.13"
+ "source": "https://github.com/symfony/http-kernel/tree/v8.0.14"
},
"funding": [
{
@@ -2971,24 +2904,24 @@
"type": "tidelift"
}
],
- "time": "2026-05-27T08:31:43+00:00"
+ "time": "2026-06-27T09:16:44+00:00"
},
{
"name": "symfony/options-resolver",
- "version": "v7.4.0",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "b38026df55197f9e39a44f3215788edf83187b80"
+ "reference": "88f9c561f678a02d54b897014049fa839e33ff82"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80",
- "reference": "b38026df55197f9e39a44f3215788edf83187b80",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/88f9c561f678a02d54b897014049fa839e33ff82",
+ "reference": "88f9c561f678a02d54b897014049fa839e33ff82",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3"
},
"type": "library",
@@ -3022,7 +2955,7 @@
"options"
],
"support": {
- "source": "https://github.com/symfony/options-resolver/tree/v7.4.0"
+ "source": "https://github.com/symfony/options-resolver/tree/v8.1.0"
},
"funding": [
{
@@ -3042,7 +2975,7 @@
"type": "tidelift"
}
],
- "time": "2025-11-12T15:39:26+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/orm-pack",
@@ -3098,27 +3031,24 @@
},
{
"name": "symfony/password-hasher",
- "version": "v7.4.6",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/password-hasher.git",
- "reference": "376755eb9c9857d78aedb68341ad2f46d1908b29"
+ "reference": "6934d16beaa4677f2c4584229fff1b51099dd7af"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/password-hasher/zipball/376755eb9c9857d78aedb68341ad2f46d1908b29",
- "reference": "376755eb9c9857d78aedb68341ad2f46d1908b29",
+ "url": "https://api.github.com/repos/symfony/password-hasher/zipball/6934d16beaa4677f2c4584229fff1b51099dd7af",
+ "reference": "6934d16beaa4677f2c4584229fff1b51099dd7af",
"shasum": ""
},
"require": {
- "php": ">=8.2"
- },
- "conflict": {
- "symfony/security-core": "<6.4"
+ "php": ">=8.4.1"
},
"require-dev": {
- "symfony/console": "^6.4|^7.0|^8.0",
- "symfony/security-core": "^6.4|^7.0|^8.0"
+ "symfony/console": "^7.4|^8.0",
+ "symfony/security-core": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -3150,7 +3080,7 @@
"password"
],
"support": {
- "source": "https://github.com/symfony/password-hasher/tree/v7.4.6"
+ "source": "https://github.com/symfony/password-hasher/tree/v8.1.0"
},
"funding": [
{
@@ -3170,7 +3100,7 @@
"type": "tidelift"
}
],
- "time": "2026-02-11T16:03:16+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -3257,16 +3187,16 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.33.0",
+ "version": "v1.38.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70"
+ "reference": "e9247d281d694a5120554d9afaf54e070e88a603"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70",
- "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603",
+ "reference": "e9247d281d694a5120554d9afaf54e070e88a603",
"shasum": ""
},
"require": {
@@ -3315,7 +3245,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1"
},
"funding": [
{
@@ -3335,20 +3265,20 @@
"type": "tidelift"
}
],
- "time": "2025-06-27T09:58:17+00:00"
+ "time": "2026-05-26T05:58:03+00:00"
},
{
"name": "symfony/polyfill-intl-icu",
- "version": "v1.33.0",
+ "version": "v1.38.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-icu.git",
- "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c"
+ "reference": "445c90e341fccda10311019cf82ff73bb7343945"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c",
- "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/445c90e341fccda10311019cf82ff73bb7343945",
+ "reference": "445c90e341fccda10311019cf82ff73bb7343945",
"shasum": ""
},
"require": {
@@ -3403,7 +3333,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.38.0"
},
"funding": [
{
@@ -3423,20 +3353,20 @@
"type": "tidelift"
}
],
- "time": "2025-06-20T22:24:30+00:00"
+ "time": "2026-05-25T11:52:53+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.33.0",
+ "version": "v1.38.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
- "reference": "3833d7255cc303546435cb650316bff708a1c75c"
+ "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
- "reference": "3833d7255cc303546435cb650316bff708a1c75c",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b",
+ "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b",
"shasum": ""
},
"require": {
@@ -3488,7 +3418,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0"
},
"funding": [
{
@@ -3508,20 +3438,20 @@
"type": "tidelift"
}
],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2026-05-25T13:48:31+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.38.1",
+ "version": "v1.38.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92"
+ "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/14c5439eec4ccff081ac14eca2dc57feb2a66d92",
- "reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
+ "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
"shasum": ""
},
"require": {
@@ -3573,7 +3503,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.1"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2"
},
"funding": [
{
@@ -3593,100 +3523,20 @@
"type": "tidelift"
}
],
- "time": "2026-05-26T12:51:13+00:00"
- },
- {
- "name": "symfony/polyfill-php83",
- "version": "v1.38.1",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-php83.git",
- "reference": "8339098cae28673c15cce00d80734af0453054e2"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/8339098cae28673c15cce00d80734af0453054e2",
- "reference": "8339098cae28673c15cce00d80734af0453054e2",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "url": "https://github.com/symfony/polyfill",
- "name": "symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Php83\\": ""
- },
- "classmap": [
- "Resources/stubs"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "polyfill",
- "portable",
- "shim"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-php83/tree/v1.38.1"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://github.com/nicolas-grekas",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2026-05-26T12:51:13+00:00"
+ "time": "2026-05-27T06:59:30+00:00"
},
{
"name": "symfony/polyfill-php84",
- "version": "v1.33.0",
+ "version": "v1.38.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php84.git",
- "reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
+ "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
- "reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
+ "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
+ "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
"shasum": ""
},
"require": {
@@ -3733,7 +3583,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1"
},
"funding": [
{
@@ -3753,7 +3603,7 @@
"type": "tidelift"
}
],
- "time": "2025-06-24T13:30:11+00:00"
+ "time": "2026-05-26T12:51:13+00:00"
},
{
"name": "symfony/polyfill-php85",
@@ -3837,25 +3687,25 @@
},
{
"name": "symfony/property-access",
- "version": "v7.4.4",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/property-access.git",
- "reference": "fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1"
+ "reference": "9261ef060f26cc7b728f67f141ba19b98a6209a9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/property-access/zipball/fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1",
- "reference": "fa49bf1ca8fce1ba0e2dba4e4658554cfb9364b1",
+ "url": "https://api.github.com/repos/symfony/property-access/zipball/9261ef060f26cc7b728f67f141ba19b98a6209a9",
+ "reference": "9261ef060f26cc7b728f67f141ba19b98a6209a9",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/property-info": "^6.4.32|~7.3.10|^7.4.4|^8.0.4"
+ "php": ">=8.4.1",
+ "symfony/property-info": "^7.4.4|^8.0.4"
},
"require-dev": {
- "symfony/cache": "^6.4|^7.0|^8.0",
- "symfony/var-exporter": "^6.4.1|^7.0.1|^8.0"
+ "symfony/cache": "^7.4|^8.0",
+ "symfony/var-exporter": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -3894,7 +3744,7 @@
"reflection"
],
"support": {
- "source": "https://github.com/symfony/property-access/tree/v7.4.4"
+ "source": "https://github.com/symfony/property-access/tree/v8.1.0"
},
"funding": [
{
@@ -3914,41 +3764,37 @@
"type": "tidelift"
}
],
- "time": "2026-01-05T08:47:25+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/property-info",
- "version": "v7.4.7",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/property-info.git",
- "reference": "02501d75fd834345da3ecdd8e3200ced39e370f8"
+ "reference": "4721e8c56d0cd2378e0ef9a9899f810008b859f7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/property-info/zipball/02501d75fd834345da3ecdd8e3200ced39e370f8",
- "reference": "02501d75fd834345da3ecdd8e3200ced39e370f8",
+ "url": "https://api.github.com/repos/symfony/property-info/zipball/4721e8c56d0cd2378e0ef9a9899f810008b859f7",
+ "reference": "4721e8c56d0cd2378e0ef9a9899f810008b859f7",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3",
- "symfony/string": "^6.4|^7.0|^8.0",
+ "php": ">=8.4.1",
+ "symfony/string": "^7.4|^8.0",
"symfony/type-info": "^7.4.7|^8.0.7"
},
"conflict": {
"phpdocumentor/reflection-docblock": "<5.2|>=7",
- "phpdocumentor/type-resolver": "<1.5.1",
- "symfony/cache": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/serializer": "<6.4"
+ "phpdocumentor/type-resolver": "<1.5.1"
},
"require-dev": {
"phpdocumentor/reflection-docblock": "^5.2|^6.0",
"phpstan/phpdoc-parser": "^1.0|^2.0",
- "symfony/cache": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/serializer": "^6.4|^7.0|^8.0"
+ "symfony/cache": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/serializer": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -3984,7 +3830,7 @@
"validator"
],
"support": {
- "source": "https://github.com/symfony/property-info/tree/v7.4.7"
+ "source": "https://github.com/symfony/property-info/tree/v8.1.0"
},
"funding": [
{
@@ -4004,38 +3850,33 @@
"type": "tidelift"
}
],
- "time": "2026-03-04T15:53:26+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/routing",
- "version": "v7.4.13",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "3a162171bb008e5e0f15dce6581373a4c0e8390d"
+ "reference": "fe0bfec72c8a806109fb9c3a5f2b898fe0c76eb3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/3a162171bb008e5e0f15dce6581373a4c0e8390d",
- "reference": "3a162171bb008e5e0f15dce6581373a4c0e8390d",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/fe0bfec72c8a806109fb9c3a5f2b898fe0c76eb3",
+ "reference": "fe0bfec72c8a806109fb9c3a5f2b898fe0c76eb3",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3"
},
- "conflict": {
- "symfony/config": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/yaml": "<6.4"
- },
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
- "symfony/yaml": "^6.4|^7.0|^8.0"
+ "symfony/config": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/yaml": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -4069,7 +3910,7 @@
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v7.4.13"
+ "source": "https://github.com/symfony/routing/tree/v8.1.0"
},
"funding": [
{
@@ -4089,50 +3930,42 @@
"type": "tidelift"
}
],
- "time": "2026-05-24T11:20:33+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/security-core",
- "version": "v7.4.4",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/security-core.git",
- "reference": "958a70725a8d669bec6721f4cd318d209712e944"
+ "reference": "2350e2f04858a7d50e758852512f9f5c3091a37b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/security-core/zipball/958a70725a8d669bec6721f4cd318d209712e944",
- "reference": "958a70725a8d669bec6721f4cd318d209712e944",
+ "url": "https://api.github.com/repos/symfony/security-core/zipball/2350e2f04858a7d50e758852512f9f5c3091a37b",
+ "reference": "2350e2f04858a7d50e758852512f9f5c3091a37b",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3",
+ "php": ">=8.4.1",
"symfony/event-dispatcher-contracts": "^2.5|^3",
- "symfony/password-hasher": "^6.4|^7.0|^8.0",
+ "symfony/password-hasher": "^7.4|^8.0",
"symfony/service-contracts": "^2.5|^3"
},
- "conflict": {
- "symfony/dependency-injection": "<6.4",
- "symfony/event-dispatcher": "<6.4",
- "symfony/http-foundation": "<6.4",
- "symfony/ldap": "<6.4",
- "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
- "symfony/validator": "<6.4"
- },
"require-dev": {
"psr/cache": "^1.0|^2.0|^3.0",
"psr/container": "^1.1|^2.0",
"psr/log": "^1|^2|^3",
- "symfony/cache": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
- "symfony/ldap": "^6.4|^7.0|^8.0",
- "symfony/string": "^6.4|^7.0|^8.0",
- "symfony/translation": "^6.4.3|^7.0.3|^8.0",
- "symfony/validator": "^6.4|^7.0|^8.0"
+ "symfony/cache": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/event-dispatcher": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/ldap": "^7.4|^8.0",
+ "symfony/property-access": "^7.4|^8.0",
+ "symfony/string": "^7.4|^8.0",
+ "symfony/translation": "^7.4|^8.0",
+ "symfony/validator": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -4160,7 +3993,7 @@
"description": "Symfony Security Component - Core Library",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/security-core/tree/v7.4.4"
+ "source": "https://github.com/symfony/security-core/tree/v8.1.1"
},
"funding": [
{
@@ -4180,33 +4013,31 @@
"type": "tidelift"
}
],
- "time": "2026-01-14T09:36:49+00:00"
+ "time": "2026-06-09T10:54:51+00:00"
},
{
"name": "symfony/security-csrf",
- "version": "v7.4.6",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/security-csrf.git",
- "reference": "d01adcd3141bec95e4cfd338f6b4482f1dd6a42b"
+ "reference": "c865a8ee0d30b14545d7e5349b8e443f4fa9dc3f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/security-csrf/zipball/d01adcd3141bec95e4cfd338f6b4482f1dd6a42b",
- "reference": "d01adcd3141bec95e4cfd338f6b4482f1dd6a42b",
+ "url": "https://api.github.com/repos/symfony/security-csrf/zipball/c865a8ee0d30b14545d7e5349b8e443f4fa9dc3f",
+ "reference": "c865a8ee0d30b14545d7e5349b8e443f4fa9dc3f",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/security-core": "^6.4|^7.0|^8.0"
- },
- "conflict": {
- "symfony/http-foundation": "<6.4"
+ "php": ">=8.4.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/security-core": "^7.4|^8.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0"
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -4234,7 +4065,7 @@
"description": "Symfony Security Component - CSRF Library",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/security-csrf/tree/v7.4.6"
+ "source": "https://github.com/symfony/security-csrf/tree/v8.1.0"
},
"funding": [
{
@@ -4254,20 +4085,20 @@
"type": "tidelift"
}
],
- "time": "2026-02-11T16:03:16+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v3.7.0",
+ "version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a"
+ "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d25d82433a80eba6aa0e6c24b61d7370d99e444a",
- "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/c0a284bab1ed8aa0417e3d69250ab437739563a0",
+ "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0",
"shasum": ""
},
"require": {
@@ -4321,7 +4152,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.7.0"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.7.1"
},
"funding": [
{
@@ -4341,24 +4172,24 @@
"type": "tidelift"
}
],
- "time": "2026-03-28T09:44:51+00:00"
+ "time": "2026-06-16T09:55:08+00:00"
},
{
"name": "symfony/stopwatch",
- "version": "v7.4.0",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
- "reference": "8a24af0a2e8a872fb745047180649b8418303084"
+ "reference": "21c07b026905d596e8379caeb115d87aa479499d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/stopwatch/zipball/8a24af0a2e8a872fb745047180649b8418303084",
- "reference": "8a24af0a2e8a872fb745047180649b8418303084",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/21c07b026905d596e8379caeb115d87aa479499d",
+ "reference": "21c07b026905d596e8379caeb115d87aa479499d",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4.1",
"symfony/service-contracts": "^2.5|^3"
},
"type": "library",
@@ -4387,7 +4218,7 @@
"description": "Provides a way to profile code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/stopwatch/tree/v7.4.0"
+ "source": "https://github.com/symfony/stopwatch/tree/v8.1.0"
},
"funding": [
{
@@ -4407,39 +4238,38 @@
"type": "tidelift"
}
],
- "time": "2025-08-04T07:05:15+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/string",
- "version": "v7.4.6",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "9f209231affa85aa930a5e46e6eb03381424b30b"
+ "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b",
- "reference": "9f209231affa85aa930a5e46e6eb03381424b30b",
+ "url": "https://api.github.com/repos/symfony/string/zipball/afd5944f4005862d961efb85c8bbd5c523c4e3c9",
+ "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3.0",
- "symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-intl-grapheme": "~1.33",
- "symfony/polyfill-intl-normalizer": "~1.0",
- "symfony/polyfill-mbstring": "~1.0"
+ "php": ">=8.4.1",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-intl-grapheme": "^1.33",
+ "symfony/polyfill-intl-normalizer": "^1.0",
+ "symfony/polyfill-mbstring": "^1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/emoji": "^7.1|^8.0",
- "symfony/http-client": "^6.4|^7.0|^8.0",
- "symfony/intl": "^6.4|^7.0|^8.0",
+ "symfony/emoji": "^7.4|^8.0",
+ "symfony/http-client": "^7.4|^8.0",
+ "symfony/intl": "^7.4|^8.0",
"symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^6.4|^7.0|^8.0"
+ "symfony/var-exporter": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -4478,7 +4308,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.4.6"
+ "source": "https://github.com/symfony/string/tree/v8.1.0"
},
"funding": [
{
@@ -4498,38 +4328,31 @@
"type": "tidelift"
}
],
- "time": "2026-02-09T09:33:46+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/translation",
- "version": "v7.4.6",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "1888cf064399868af3784b9e043240f1d89d25ce"
+ "reference": "342b4218630dc2cf284cedcb2080c80b13404014"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/1888cf064399868af3784b9e043240f1d89d25ce",
- "reference": "1888cf064399868af3784b9e043240f1d89d25ce",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/342b4218630dc2cf284cedcb2080c80b13404014",
+ "reference": "342b4218630dc2cf284cedcb2080c80b13404014",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/translation-contracts": "^2.5.3|^3.3"
+ "php": ">=8.4.1",
+ "symfony/polyfill-mbstring": "^1.0",
+ "symfony/translation-contracts": "^3.6.1"
},
"conflict": {
"nikic/php-parser": "<5.0",
- "symfony/config": "<6.4",
- "symfony/console": "<6.4",
- "symfony/dependency-injection": "<6.4",
"symfony/http-client-contracts": "<2.5",
- "symfony/http-kernel": "<6.4",
- "symfony/service-contracts": "<2.5",
- "symfony/twig-bundle": "<6.4",
- "symfony/yaml": "<6.4"
+ "symfony/service-contracts": "<2.5"
},
"provide": {
"symfony/translation-implementation": "2.3|3.0"
@@ -4537,17 +4360,17 @@
"require-dev": {
"nikic/php-parser": "^5.0",
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/console": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/finder": "^6.4|^7.0|^8.0",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/console": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/finder": "^7.4|^8.0",
"symfony/http-client-contracts": "^2.5|^3.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
- "symfony/intl": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/intl": "^7.4|^8.0",
"symfony/polyfill-intl-icu": "^1.21",
- "symfony/routing": "^6.4|^7.0|^8.0",
+ "symfony/routing": "^7.4|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/yaml": "^6.4|^7.0|^8.0"
+ "symfony/yaml": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -4578,7 +4401,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/translation/tree/v7.4.6"
+ "source": "https://github.com/symfony/translation/tree/v8.1.1"
},
"funding": [
{
@@ -4598,20 +4421,20 @@
"type": "tidelift"
}
],
- "time": "2026-02-17T07:53:42+00:00"
+ "time": "2026-06-06T11:11:44+00:00"
},
{
"name": "symfony/translation-contracts",
- "version": "v3.6.1",
+ "version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation-contracts.git",
- "reference": "65a8bc82080447fae78373aa10f8d13b38338977"
+ "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977",
- "reference": "65a8bc82080447fae78373aa10f8d13b38338977",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/ccb206b98faccc511ebae8e5fad50f2dc0b30621",
+ "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621",
"shasum": ""
},
"require": {
@@ -4624,7 +4447,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
- "dev-main": "3.6-dev"
+ "dev-main": "3.7-dev"
}
},
"autoload": {
@@ -4660,7 +4483,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1"
+ "source": "https://github.com/symfony/translation-contracts/tree/v3.7.1"
},
"funding": [
{
@@ -4680,71 +4503,64 @@
"type": "tidelift"
}
],
- "time": "2025-07-15T13:41:35+00:00"
+ "time": "2026-06-05T06:23:12+00:00"
},
{
"name": "symfony/twig-bridge",
- "version": "v7.4.7",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/twig-bridge.git",
- "reference": "c67219ca6b79a57b64e36bbb2cd8ba741286587e"
+ "reference": "471e3b9537f514664ab8595668cd34c65cfa5d93"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/c67219ca6b79a57b64e36bbb2cd8ba741286587e",
- "reference": "c67219ca6b79a57b64e36bbb2cd8ba741286587e",
+ "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/471e3b9537f514664ab8595668cd34c65cfa5d93",
+ "reference": "471e3b9537f514664ab8595668cd34c65cfa5d93",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3",
+ "php": ">=8.4.1",
"symfony/translation-contracts": "^2.5|^3",
- "twig/twig": "^3.21"
+ "twig/twig": "^3.25"
},
"conflict": {
"phpdocumentor/reflection-docblock": "<5.2|>=7",
"phpdocumentor/type-resolver": "<1.5.1",
- "symfony/console": "<6.4",
- "symfony/form": "<6.4.32|>7,<7.3.10|>7.4,<7.4.4|>8.0,<8.0.4",
- "symfony/http-foundation": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/mime": "<6.4",
- "symfony/serializer": "<6.4",
- "symfony/translation": "<6.4",
- "symfony/workflow": "<6.4"
+ "symfony/form": "<7.4.4|>8.0,<8.0.4",
+ "symfony/mime": "<7.4.9|>8.0,<8.0.9"
},
"require-dev": {
"egulias/email-validator": "^2.1.10|^3|^4",
"league/html-to-markdown": "^5.0",
"phpdocumentor/reflection-docblock": "^5.2|^6.0",
- "symfony/asset": "^6.4|^7.0|^8.0",
- "symfony/asset-mapper": "^6.4|^7.0|^8.0",
- "symfony/console": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/emoji": "^7.1|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/finder": "^6.4|^7.0|^8.0",
- "symfony/form": "^6.4.32|~7.3.10|^7.4.4|^8.0.4",
- "symfony/html-sanitizer": "^6.4|^7.0|^8.0",
- "symfony/http-foundation": "^7.3|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
- "symfony/intl": "^6.4|^7.0|^8.0",
- "symfony/mime": "^6.4|^7.0|^8.0",
- "symfony/polyfill-intl-icu": "~1.0",
- "symfony/property-info": "^6.4|^7.0|^8.0",
- "symfony/routing": "^6.4|^7.0|^8.0",
+ "symfony/asset": "^7.4|^8.0",
+ "symfony/asset-mapper": "^7.4|^8.0",
+ "symfony/console": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/emoji": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/finder": "^7.4|^8.0",
+ "symfony/form": "^7.4.4|^8.0.4",
+ "symfony/html-sanitizer": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/intl": "^7.4|^8.0",
+ "symfony/mime": "^7.4.9|^8.0.9",
+ "symfony/polyfill-intl-icu": "^1.0",
+ "symfony/property-info": "^7.4|^8.0",
+ "symfony/routing": "^7.4|^8.0",
"symfony/security-acl": "^2.8|^3.0",
- "symfony/security-core": "^6.4|^7.0|^8.0",
- "symfony/security-csrf": "^6.4|^7.0|^8.0",
- "symfony/security-http": "^6.4|^7.0|^8.0",
- "symfony/serializer": "^6.4.3|^7.0.3|^8.0",
- "symfony/stopwatch": "^6.4|^7.0|^8.0",
- "symfony/translation": "^6.4|^7.0|^8.0",
- "symfony/validator": "^6.4|^7.0|^8.0",
- "symfony/web-link": "^6.4|^7.0|^8.0",
- "symfony/workflow": "^6.4|^7.0|^8.0",
- "symfony/yaml": "^6.4|^7.0|^8.0",
+ "symfony/security-core": "^7.4|^8.0",
+ "symfony/security-csrf": "^7.4|^8.0",
+ "symfony/security-http": "^7.4|^8.0",
+ "symfony/serializer": "^7.4|^8.0",
+ "symfony/stopwatch": "^7.4|^8.0",
+ "symfony/translation": "^7.4|^8.0",
+ "symfony/validator": "^7.4|^8.0",
+ "symfony/web-link": "^7.4|^8.0",
+ "symfony/workflow": "^7.4|^8.0",
+ "symfony/yaml": "^7.4|^8.0",
"twig/cssinliner-extra": "^3",
"twig/inky-extra": "^3",
"twig/markdown-extra": "^3"
@@ -4775,7 +4591,7 @@
"description": "Provides integration for Twig with various Symfony components",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/twig-bridge/tree/v7.4.7"
+ "source": "https://github.com/symfony/twig-bridge/tree/v8.1.1"
},
"funding": [
{
@@ -4795,49 +4611,43 @@
"type": "tidelift"
}
],
- "time": "2026-03-04T15:37:05+00:00"
+ "time": "2026-06-17T15:04:37+00:00"
},
{
"name": "symfony/twig-bundle",
- "version": "v7.4.4",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/twig-bundle.git",
- "reference": "e8829e02ff96a391ed0703bac9e7ff0537480b6b"
+ "reference": "b7f4a471a07b8b52174d153e4db12f46954192ed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/e8829e02ff96a391ed0703bac9e7ff0537480b6b",
- "reference": "e8829e02ff96a391ed0703bac9e7ff0537480b6b",
+ "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/b7f4a471a07b8b52174d153e4db12f46954192ed",
+ "reference": "b7f4a471a07b8b52174d153e4db12f46954192ed",
"shasum": ""
},
"require": {
"composer-runtime-api": ">=2.1",
- "php": ">=8.2",
+ "php": ">=8.4.1",
"symfony/config": "^7.4|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/deprecation-contracts": "^2.5|^3",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0",
- "symfony/twig-bridge": "^7.3|^8.0",
- "twig/twig": "^3.12"
- },
- "conflict": {
- "symfony/framework-bundle": "<6.4",
- "symfony/translation": "<6.4"
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/twig-bridge": "^7.4|^8.0"
},
"require-dev": {
- "symfony/asset": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/finder": "^6.4|^7.0|^8.0",
- "symfony/form": "^6.4|^7.0|^8.0",
- "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0",
- "symfony/routing": "^6.4|^7.0|^8.0",
- "symfony/runtime": "^6.4.13|^7.1.6",
- "symfony/stopwatch": "^6.4|^7.0|^8.0",
- "symfony/translation": "^6.4|^7.0|^8.0",
- "symfony/web-link": "^6.4|^7.0|^8.0",
- "symfony/yaml": "^6.4|^7.0|^8.0"
+ "symfony/asset": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/finder": "^7.4|^8.0",
+ "symfony/form": "^7.4|^8.0",
+ "symfony/framework-bundle": "^7.4|^8.0",
+ "symfony/routing": "^7.4|^8.0",
+ "symfony/runtime": "^7.4|^8.0",
+ "symfony/stopwatch": "^7.4|^8.0",
+ "symfony/translation": "^7.4|^8.0",
+ "symfony/web-link": "^7.4|^8.0",
+ "symfony/yaml": "^7.4|^8.0"
},
"type": "symfony-bundle",
"autoload": {
@@ -4865,7 +4675,7 @@
"description": "Provides a tight integration of Twig into the Symfony full-stack framework",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/twig-bundle/tree/v7.4.4"
+ "source": "https://github.com/symfony/twig-bundle/tree/v8.1.0"
},
"funding": [
{
@@ -4885,26 +4695,25 @@
"type": "tidelift"
}
],
- "time": "2026-01-06T12:34:24+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/type-info",
- "version": "v7.4.7",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/type-info.git",
- "reference": "31f1e40cbf7851c7354281c90eb1b352c4cb8269"
+ "reference": "9f24df8a79781b9b9f030fea7dfd2f3bd1e7e7e7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/type-info/zipball/31f1e40cbf7851c7354281c90eb1b352c4cb8269",
- "reference": "31f1e40cbf7851c7354281c90eb1b352c4cb8269",
+ "url": "https://api.github.com/repos/symfony/type-info/zipball/9f24df8a79781b9b9f030fea7dfd2f3bd1e7e7e7",
+ "reference": "9f24df8a79781b9b9f030fea7dfd2f3bd1e7e7e7",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "psr/container": "^1.1|^2.0",
- "symfony/deprecation-contracts": "^2.5|^3"
+ "php": ">=8.4.1",
+ "psr/container": "^1.1|^2.0"
},
"conflict": {
"phpstan/phpdoc-parser": "<1.30"
@@ -4948,7 +4757,7 @@
"type"
],
"support": {
- "source": "https://github.com/symfony/type-info/tree/v7.4.7"
+ "source": "https://github.com/symfony/type-info/tree/v8.1.0"
},
"funding": [
{
@@ -4968,62 +4777,55 @@
"type": "tidelift"
}
],
- "time": "2026-03-04T12:49:16+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/validator",
- "version": "v7.4.7",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/validator.git",
- "reference": "3a1a460a9f8c5e5611e15c52c4baa5a62fa3c203"
+ "reference": "d162b73fa884ce2185033c143172dc12b023051a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/validator/zipball/3a1a460a9f8c5e5611e15c52c4baa5a62fa3c203",
- "reference": "3a1a460a9f8c5e5611e15c52c4baa5a62fa3c203",
+ "url": "https://api.github.com/repos/symfony/validator/zipball/d162b73fa884ce2185033c143172dc12b023051a",
+ "reference": "d162b73fa884ce2185033c143172dc12b023051a",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/polyfill-php83": "^1.27",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-mbstring": "^1.0",
"symfony/translation-contracts": "^2.5|^3"
},
"conflict": {
"doctrine/lexer": "<1.1",
- "symfony/dependency-injection": "<6.4",
- "symfony/doctrine-bridge": "<7.0",
- "symfony/expression-language": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/intl": "<6.4",
- "symfony/property-info": "<6.4",
- "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
- "symfony/var-exporter": "<6.4.25|>=7.0,<7.3.3",
- "symfony/yaml": "<6.4"
+ "symfony/doctrine-bridge": "<7.4",
+ "symfony/expression-language": "<7.4"
},
"require-dev": {
"egulias/email-validator": "^2.1.10|^3|^4",
- "symfony/cache": "^6.4|^7.0|^8.0",
- "symfony/config": "^6.4|^7.0|^8.0",
- "symfony/console": "^6.4|^7.0|^8.0",
- "symfony/dependency-injection": "^6.4|^7.0|^8.0",
- "symfony/expression-language": "^6.4|^7.0|^8.0",
- "symfony/finder": "^6.4|^7.0|^8.0",
- "symfony/http-client": "^6.4|^7.0|^8.0",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
- "symfony/intl": "^6.4|^7.0|^8.0",
- "symfony/mime": "^6.4|^7.0|^8.0",
- "symfony/process": "^6.4|^7.0|^8.0",
- "symfony/property-access": "^6.4|^7.0|^8.0",
- "symfony/property-info": "^6.4|^7.0|^8.0",
- "symfony/string": "^6.4|^7.0|^8.0",
- "symfony/translation": "^6.4.3|^7.0.3|^8.0",
- "symfony/type-info": "^7.1.8",
- "symfony/yaml": "^6.4|^7.0|^8.0"
+ "symfony/cache": "^7.4|^8.0",
+ "symfony/clock": "^7.4|^8.0",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/console": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/finder": "^7.4|^8.0",
+ "symfony/http-client": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/intl": "^7.4|^8.0",
+ "symfony/mime": "^7.4|^8.0",
+ "symfony/process": "^7.4|^8.0",
+ "symfony/property-access": "^7.4|^8.0",
+ "symfony/property-info": "^7.4|^8.0",
+ "symfony/string": "^7.4|^8.0",
+ "symfony/translation": "^7.4|^8.0",
+ "symfony/type-info": "^7.4|^8.0",
+ "symfony/yaml": "^7.4|^8.0"
},
"type": "library",
"autoload": {
@@ -5052,7 +4854,7 @@
"description": "Provides tools to validate values",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/validator/tree/v7.4.7"
+ "source": "https://github.com/symfony/validator/tree/v8.1.1"
},
"funding": [
{
@@ -5072,35 +4874,35 @@
"type": "tidelift"
}
],
- "time": "2026-03-06T11:10:17+00:00"
+ "time": "2026-06-27T06:18:14+00:00"
},
{
"name": "symfony/var-dumper",
- "version": "v7.4.8",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd"
+ "reference": "40096a2515a979f3125c5c928603995b8664c62a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9510c3966f749a1d1ff0059e1eabef6cc621e7fd",
- "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/40096a2515a979f3125c5c928603995b8664c62a",
+ "reference": "40096a2515a979f3125c5c928603995b8664c62a",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3",
- "symfony/polyfill-mbstring": "~1.0"
+ "php": ">=8.4.1",
+ "symfony/polyfill-mbstring": "^1.0"
},
"conflict": {
- "symfony/console": "<6.4"
+ "symfony/console": "<7.4",
+ "symfony/error-handler": "<7.4"
},
"require-dev": {
- "symfony/console": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0",
- "symfony/process": "^6.4|^7.0|^8.0",
- "symfony/uid": "^6.4|^7.0|^8.0",
+ "symfony/console": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/process": "^7.4|^8.0",
+ "symfony/uid": "^7.4|^8.0",
"twig/twig": "^3.12"
},
"bin": [
@@ -5139,7 +4941,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v7.4.8"
+ "source": "https://github.com/symfony/var-dumper/tree/v8.1.1"
},
"funding": [
{
@@ -5159,20 +4961,20 @@
"type": "tidelift"
}
],
- "time": "2026-03-30T13:44:50+00:00"
+ "time": "2026-06-09T10:54:51+00:00"
},
{
"name": "symfony/var-exporter",
- "version": "v7.4.9",
+ "version": "v7.4.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
- "reference": "22e03a49c95ef054a43601cd159b222bfab1c701"
+ "reference": "0118811b1d59f323bf131250b3fb919febfece28"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-exporter/zipball/22e03a49c95ef054a43601cd159b222bfab1c701",
- "reference": "22e03a49c95ef054a43601cd159b222bfab1c701",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/0118811b1d59f323bf131250b3fb919febfece28",
+ "reference": "0118811b1d59f323bf131250b3fb919febfece28",
"shasum": ""
},
"require": {
@@ -5220,7 +5022,7 @@
"serialize"
],
"support": {
- "source": "https://github.com/symfony/var-exporter/tree/v7.4.9"
+ "source": "https://github.com/symfony/var-exporter/tree/v7.4.14"
},
"funding": [
{
@@ -5240,32 +5042,32 @@
"type": "tidelift"
}
],
- "time": "2026-04-18T13:18:21+00:00"
+ "time": "2026-06-27T08:41:53+00:00"
},
{
"name": "symfony/yaml",
- "version": "v7.4.12",
+ "version": "v8.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "8b6952b56ca6417f25f7a65758cadd0ce02edc51"
+ "reference": "8e4cdd4311683516be06944f4b85244063cdb886"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/8b6952b56ca6417f25f7a65758cadd0ce02edc51",
- "reference": "8b6952b56ca6417f25f7a65758cadd0ce02edc51",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/8e4cdd4311683516be06944f4b85244063cdb886",
+ "reference": "8e4cdd4311683516be06944f4b85244063cdb886",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3",
+ "php": ">=8.4.1",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
- "symfony/console": "<6.4"
+ "symfony/console": "<7.4"
},
"require-dev": {
- "symfony/console": "^6.4|^7.0|^8.0"
+ "symfony/console": "^7.4|^8.0",
+ "yaml/yaml-test-suite": "*"
},
"bin": [
"Resources/bin/yaml-lint"
@@ -5296,7 +5098,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/yaml/tree/v7.4.12"
+ "source": "https://github.com/symfony/yaml/tree/v8.1.1"
},
"funding": [
{
@@ -5316,7 +5118,7 @@
"type": "tidelift"
}
],
- "time": "2026-05-20T07:20:23+00:00"
+ "time": "2026-06-09T11:06:24+00:00"
},
{
"name": "twig/twig",
@@ -5466,28 +5268,29 @@
},
{
"name": "composer/pcre",
- "version": "3.3.2",
+ "version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
- "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
+ "reference": "d5a341b3fb61f3001970940afb1d332968a183ed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
- "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed",
+ "reference": "d5a341b3fb61f3001970940afb1d332968a183ed",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"conflict": {
- "phpstan/phpstan": "<1.11.10"
+ "phpstan/phpstan": "<2.2.2"
},
"require-dev": {
- "phpstan/phpstan": "^1.12 || ^2",
- "phpstan/phpstan-strict-rules": "^1 || ^2",
- "phpunit/phpunit": "^8 || ^9"
+ "phpstan/phpstan": "^2",
+ "phpstan/phpstan-deprecation-rules": "^2",
+ "phpstan/phpstan-strict-rules": "^2",
+ "phpunit/phpunit": "^9"
},
"type": "library",
"extra": {
@@ -5525,7 +5328,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
- "source": "https://github.com/composer/pcre/tree/3.3.2"
+ "source": "https://github.com/composer/pcre/tree/3.4.0"
},
"funding": [
{
@@ -5535,13 +5338,9 @@
{
"url": "https://github.com/composer",
"type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/composer/composer",
- "type": "tidelift"
}
],
- "time": "2024-11-12T16:29:46+00:00"
+ "time": "2026-06-07T11:47:49+00:00"
},
{
"name": "composer/semver",
@@ -5859,16 +5658,16 @@
},
{
"name": "doctrine/data-fixtures",
- "version": "2.2.0",
+ "version": "2.2.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/data-fixtures.git",
- "reference": "7a615ba135e45d67674bb623d90f34f6c7b6bd97"
+ "reference": "bf7ac3a050b54b261cedfb3d0a44733819062275"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/7a615ba135e45d67674bb623d90f34f6c7b6bd97",
- "reference": "7a615ba135e45d67674bb623d90f34f6c7b6bd97",
+ "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/bf7ac3a050b54b261cedfb3d0a44733819062275",
+ "reference": "bf7ac3a050b54b261cedfb3d0a44733819062275",
"shasum": ""
},
"require": {
@@ -5886,12 +5685,14 @@
"doctrine/dbal": "^3.5 || ^4",
"doctrine/mongodb-odm": "^1.3.0 || ^2.0.0",
"doctrine/orm": "^2.14 || ^3",
+ "doctrine/phpcr-odm": "^1.8 || ^2.0",
"ext-sqlite3": "*",
"fig/log-test": "^1",
- "phpstan/phpstan": "2.1.31",
- "phpunit/phpunit": "10.5.45 || 12.4.0",
- "symfony/cache": "^6.4 || ^7",
- "symfony/var-exporter": "^6.4 || ^7"
+ "jackalope/jackalope-fs": "*",
+ "phpstan/phpstan": "2.1.46",
+ "phpunit/phpunit": "10.5.63 || 12.5.12",
+ "symfony/cache": "^6.4 || ^7 || ^8",
+ "symfony/var-exporter": "^6.4 || ^7 || ^8"
},
"suggest": {
"alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)",
@@ -5922,7 +5723,7 @@
],
"support": {
"issues": "https://github.com/doctrine/data-fixtures/issues",
- "source": "https://github.com/doctrine/data-fixtures/tree/2.2.0"
+ "source": "https://github.com/doctrine/data-fixtures/tree/2.2.1"
},
"funding": [
{
@@ -5938,20 +5739,20 @@
"type": "tidelift"
}
],
- "time": "2025-10-17T20:06:20+00:00"
+ "time": "2026-04-01T13:56:01+00:00"
},
{
"name": "doctrine/mongodb-odm",
- "version": "2.16.1",
+ "version": "2.16.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/mongodb-odm.git",
- "reference": "b34f2dce3ca5b2de8903419a31ad48837d852b74"
+ "reference": "da149ec2596c8e3732c5332b19f1351f3d5b6f70"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/mongodb-odm/zipball/b34f2dce3ca5b2de8903419a31ad48837d852b74",
- "reference": "b34f2dce3ca5b2de8903419a31ad48837d852b74",
+ "url": "https://api.github.com/repos/doctrine/mongodb-odm/zipball/da149ec2596c8e3732c5332b19f1351f3d5b6f70",
+ "reference": "da149ec2596c8e3732c5332b19f1351f3d5b6f70",
"shasum": ""
},
"require": {
@@ -6041,7 +5842,7 @@
],
"support": {
"issues": "https://github.com/doctrine/mongodb-odm/issues",
- "source": "https://github.com/doctrine/mongodb-odm/tree/2.16.1"
+ "source": "https://github.com/doctrine/mongodb-odm/tree/2.16.2"
},
"funding": [
{
@@ -6057,7 +5858,7 @@
"type": "tidelift"
}
],
- "time": "2026-01-29T11:33:08+00:00"
+ "time": "2026-06-19T09:23:48+00:00"
},
{
"name": "doctrine/mongodb-odm-bundle",
@@ -6147,6 +5948,75 @@
},
"time": "2026-01-26T10:21:57+00:00"
},
+ {
+ "name": "ergebnis/agent-detector",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ergebnis/agent-detector.git",
+ "reference": "e211f17928c8b95a51e06040792d57f5462fb271"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ergebnis/agent-detector/zipball/e211f17928c8b95a51e06040792d57f5462fb271",
+ "reference": "e211f17928c8b95a51e06040792d57f5462fb271",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0"
+ },
+ "require-dev": {
+ "ergebnis/composer-normalize": "^2.51.0",
+ "ergebnis/license": "^2.7.0",
+ "ergebnis/php-cs-fixer-config": "^6.60.2",
+ "ergebnis/phpstan-rules": "^2.13.1",
+ "ergebnis/phpunit-slow-test-detector": "^2.24.0",
+ "ergebnis/rector-rules": "^1.18.1",
+ "fakerphp/faker": "^1.24.1",
+ "infection/infection": "^0.26.6",
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^2.1.54",
+ "phpstan/phpstan-deprecation-rules": "^2.0.4",
+ "phpstan/phpstan-phpunit": "^2.0.16",
+ "phpstan/phpstan-strict-rules": "^2.0.10",
+ "phpunit/phpunit": "^9.6.34",
+ "rector/rector": "^2.4.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.2-dev"
+ },
+ "composer-normalize": {
+ "indent-size": 2,
+ "indent-style": "space"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Ergebnis\\AgentDetector\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Andreas Möller",
+ "email": "am@localheinz.com",
+ "homepage": "https://localheinz.com"
+ }
+ ],
+ "description": "Provides a detector for detecting the presence of an agent.",
+ "homepage": "https://github.com/ergebnis/agent-detector",
+ "support": {
+ "issues": "https://github.com/ergebnis/agent-detector/issues",
+ "security": "https://github.com/ergebnis/agent-detector/blob/main/.github/SECURITY.md",
+ "source": "https://github.com/ergebnis/agent-detector"
+ },
+ "time": "2026-05-07T08:19:07+00:00"
+ },
{
"name": "evenement/evenement",
"version": "v3.0.2",
@@ -6257,22 +6127,23 @@
},
{
"name": "friendsofphp/php-cs-fixer",
- "version": "v3.94.2",
+ "version": "v3.95.11",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
- "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63"
+ "reference": "35f98e1293283397824d7f349ce5afb8747c3cd5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7787ceff91365ba7d623ec410b8f429cdebb4f63",
- "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/35f98e1293283397824d7f349ce5afb8747c3cd5",
+ "reference": "35f98e1293283397824d7f349ce5afb8747c3cd5",
"shasum": ""
},
"require": {
"clue/ndjson-react": "^1.3",
"composer/semver": "^3.4",
"composer/xdebug-handler": "^3.0.5",
+ "ergebnis/agent-detector": "^1.2",
"ext-filter": "*",
"ext-hash": "*",
"ext-json": "*",
@@ -6283,32 +6154,32 @@
"react/event-loop": "^1.5",
"react/socket": "^1.16",
"react/stream": "^1.4",
- "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0",
+ "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0 || ^9.0",
"symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
- "symfony/polyfill-mbstring": "^1.33",
- "symfony/polyfill-php80": "^1.33",
- "symfony/polyfill-php81": "^1.33",
- "symfony/polyfill-php84": "^1.33",
+ "symfony/polyfill-mbstring": "^1.37",
+ "symfony/polyfill-php80": "^1.37",
+ "symfony/polyfill-php81": "^1.37",
+ "symfony/polyfill-php84": "^1.37",
"symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0",
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0"
},
"require-dev": {
- "facile-it/paraunit": "^1.3.1 || ^2.7.1",
- "infection/infection": "^0.32.3",
- "justinrainbow/json-schema": "^6.6.4",
+ "facile-it/paraunit": "^1.3.1 || ^2.11.0",
+ "infection/infection": "^0.32.7",
+ "justinrainbow/json-schema": "^6.10.0",
"keradus/cli-executor": "^2.3",
"mikey179/vfsstream": "^1.6.12",
"php-coveralls/php-coveralls": "^2.9.1",
- "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7",
- "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7",
- "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51",
- "symfony/polyfill-php85": "^1.33",
- "symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4",
- "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1"
+ "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.8",
+ "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.8",
+ "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.55",
+ "symfony/polyfill-php85": "^1.38",
+ "symfony/var-dumper": "^5.4.48 || ^6.4.36 || ^7.4.8 || ^8.1.0",
+ "symfony/yaml": "^5.4.53 || ^6.4.41 || ^7.4.13 || ^8.1.0"
},
"suggest": {
"ext-dom": "For handling output formats in XML",
@@ -6349,7 +6220,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
- "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.2"
+ "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.11"
},
"funding": [
{
@@ -6357,7 +6228,7 @@
"type": "github"
}
],
- "time": "2026-02-20T16:13:53+00:00"
+ "time": "2026-06-25T14:17:04+00:00"
},
{
"name": "friendsofphp/proxy-manager-lts",
@@ -6931,11 +6802,11 @@
},
{
"name": "phpstan/phpstan",
- "version": "2.1.40",
+ "version": "2.2.4",
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
- "reference": "9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f0fe3fb03bb53ce68cc2416785b260e62226ec27",
+ "reference": "f0fe3fb03bb53ce68cc2416785b260e62226ec27",
"shasum": ""
},
"require": {
@@ -6958,6 +6829,17 @@
"license": [
"MIT"
],
+ "authors": [
+ {
+ "name": "Ondřej Mirtes"
+ },
+ {
+ "name": "Markus Staab"
+ },
+ {
+ "name": "Vincent Langlet"
+ }
+ ],
"description": "PHPStan - PHP Static Analysis Tool",
"keywords": [
"dev",
@@ -6980,7 +6862,7 @@
"type": "github"
}
],
- "time": "2026-02-23T15:04:35+00:00"
+ "time": "2026-07-03T07:00:23+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -7940,21 +7822,21 @@
},
{
"name": "rector/rector",
- "version": "2.3.8",
+ "version": "2.5.2",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
- "reference": "bbd37aedd8df749916cffa2a947cfc4714d1ba2c"
+ "reference": "49ff6339174bdbdf50b0b35ecbcff14a05ac9e24"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/rectorphp/rector/zipball/bbd37aedd8df749916cffa2a947cfc4714d1ba2c",
- "reference": "bbd37aedd8df749916cffa2a947cfc4714d1ba2c",
+ "url": "https://api.github.com/repos/rectorphp/rector/zipball/49ff6339174bdbdf50b0b35ecbcff14a05ac9e24",
+ "reference": "49ff6339174bdbdf50b0b35ecbcff14a05ac9e24",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0",
- "phpstan/phpstan": "^2.1.38"
+ "phpstan/phpstan": "^2.2.2"
},
"conflict": {
"rector/rector-doctrine": "*",
@@ -7988,7 +7870,7 @@
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
- "source": "https://github.com/rectorphp/rector/tree/2.3.8"
+ "source": "https://github.com/rectorphp/rector/tree/2.5.2"
},
"funding": [
{
@@ -7996,7 +7878,7 @@
"type": "github"
}
],
- "time": "2026-02-22T09:45:50+00:00"
+ "time": "2026-06-22T11:39:33+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -9117,20 +8999,20 @@
},
{
"name": "symfony/process",
- "version": "v7.4.5",
+ "version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "608476f4604102976d687c483ac63a79ba18cc97"
+ "reference": "c4a9e58f235a6bf7f97ffbfedae2687353ac79e5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97",
- "reference": "608476f4604102976d687c483ac63a79ba18cc97",
+ "url": "https://api.github.com/repos/symfony/process/zipball/c4a9e58f235a6bf7f97ffbfedae2687353ac79e5",
+ "reference": "c4a9e58f235a6bf7f97ffbfedae2687353ac79e5",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "php": ">=8.4.1"
},
"type": "library",
"autoload": {
@@ -9158,7 +9040,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.4.5"
+ "source": "https://github.com/symfony/process/tree/v8.1.0"
},
"funding": [
{
@@ -9178,7 +9060,7 @@
"type": "tidelift"
}
],
- "time": "2026-01-26T15:07:59+00:00"
+ "time": "2026-05-29T05:06:50+00:00"
},
{
"name": "theseer/tokenizer",
@@ -9237,14 +9119,13 @@
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
- "php": "^8.1|^8.2|^8.3|^8.4"
+ "php": "^8.2|^8.3|^8.4"
},
"platform-dev": {
"ext-mongodb": "^1.21.0 || ^2.0.0",
"ext-pdo": "*"
},
"platform-overrides": {
- "php": "8.2.0",
"ext-mongodb": "2.1.4"
},
"plugin-api-version": "2.9.0"
diff --git a/docker-compose.yml b/docker-compose.yml
index 0cd30454..3ea03ee9 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -31,7 +31,7 @@ services:
retries: 3
mongo:
- image: mongo:4.0
+ image: mongo:4.4
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: secret