Skip to content

Commit fa230b6

Browse files
damienalexandreNyholm
authored andcommitted
Add a --cache option on translation:download to clear the cache (#139)
* Add a --cache option on translation:download to clear the cache * Refactor the cache clearer as a service and better hash generation * Fix CS and missing stuff * Order files and avoid ~ suffix
1 parent aae5865 commit fa230b6

File tree

5 files changed

+132
-45
lines changed

5 files changed

+132
-45
lines changed

Changelog.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,33 @@
22

33
The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.
44

5+
## Unreleased
6+
7+
## Added
8+
9+
- New `--cache` option on the `translation:download` allowing to clear the cache automatically if the downloaded translations have changed.
10+
511
## 0.4.0
612

713
Major improvements on this version. Be aware that the default format to store translation has changed to XLIFF 2.0. If you
8-
run the extract command you will automatically get updated files.
14+
run the extract command you will automatically get updated files.
915

1016
### Added
1117

1218
- More extractors from `php-translation/extractor`
13-
- Show status after extract command
19+
- Show status after extract command
1420
- Added status command
1521
- Support for PHPUnit6
1622
- Support for `php-translation/symfony-storage` 0.3.0
1723
- Using dumper and loader from `php-translation/extractor`
18-
- `CatalogeCounter` to show statistics about a catalogue.
19-
- Lots of more tests. Test coverage increased from 27% to 69%.
24+
- `CatalogueCounter` to show statistics about a catalogue
25+
- Lots of more tests. Test coverage increased from 27% to 69%
2026

2127
### Changed
2228

2329
- `Importer` returns an `ImportResult` value object
2430
- Improved internal management of metadata. Introduced a new `Metadata` model
25-
- Renamed `MetadataAwareMerged` to `ReplaceOperation`, read the class doc for the updated syntax.
31+
- Renamed `MetadataAwareMerged` to `ReplaceOperation`, read the class doc for the updated syntax
2632

2733
### Fixed
2834

@@ -31,7 +37,7 @@ run the extract command you will automatically get updated files.
3137
### Removed
3238

3339
- Removed `WebUIMessage` and `EditInPlaceMessage`. Use `Message` from `php-translation/common` instead
34-
- Removed metadata related functions from `CatalogueManager`
40+
- Removed metadata related functions from `CatalogueManager`
3541

3642
### Changed
3743

@@ -55,7 +61,7 @@ run the extract command you will automatically get updated files.
5561

5662
### Fixed
5763

58-
- When using EditInPlace, we only mark twig filters (`trans` & `transchoice`) as "safe" when EditInPlace in active.
64+
- When using EditInPlace, we only mark twig filters (`trans` & `transchoice`) as "safe" when EditInPlace in active.
5965

6066
## 0.3.3
6167

Command/DownloadCommand.php

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313

1414
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
1515
use Symfony\Component\Console\Input\InputArgument;
16+
use Symfony\Component\Console\Input\InputOption;
1617
use Symfony\Component\Console\Input\InputInterface;
1718
use Symfony\Component\Console\Output\OutputInterface;
19+
use Symfony\Component\Finder\Finder;
1820
use Translation\Bundle\Service\StorageService;
21+
use Translation\Bundle\Model\Configuration;
1922

2023
/**
2124
* @author Tobias Nyholm <[email protected]>
@@ -27,15 +30,50 @@ protected function configure()
2730
$this
2831
->setName('translation:download')
2932
->setDescription('Replace local messages with messages from remote')
30-
->addArgument('configuration', InputArgument::OPTIONAL, 'The configuration to use', 'default');
33+
->addArgument('configuration', InputArgument::OPTIONAL, 'The configuration to use', 'default')
34+
->addOption('cache', null, InputOption::VALUE_NONE, 'Clear the cache if the translations have changed')
35+
;
3136
}
3237

3338
protected function execute(InputInterface $input, OutputInterface $output)
3439
{
3540
$container = $this->getContainer();
3641
$configName = $input->getArgument('configuration');
42+
3743
/** @var StorageService $storage */
3844
$storage = $container->get('php_translation.storage.'.$configName);
39-
$storage->download();
45+
/** @var Configuration $configuration */
46+
$configuration = $this->getContainer()->get('php_translation.configuration.'.$configName);
47+
48+
if ($input->getOption('cache')) {
49+
$translationsDirectory = $configuration->getOutputDir();
50+
$md5BeforeDownload = $this->hashDirectory($translationsDirectory);
51+
$storage->download();
52+
$md5AfterDownload = $this->hashDirectory($translationsDirectory);
53+
54+
if ($md5BeforeDownload !== $md5AfterDownload) {
55+
$cacheClearer = $this->getContainer()->get('php_translation.cache_clearer');
56+
$cacheClearer->clearAndWarmUp();
57+
}
58+
} else {
59+
$storage->download();
60+
}
61+
}
62+
63+
private function hashDirectory($directory)
64+
{
65+
if (!is_dir($directory)) {
66+
return false;
67+
}
68+
69+
$finder = new Finder();
70+
$finder->files()->in($directory)->notName('/~$/')->sortByName();
71+
72+
$hash = hash_init('md5');
73+
foreach ($finder as $file) {
74+
hash_update_file($hash, $file->getRealPath());
75+
}
76+
77+
return hash_final($hash);
4078
}
4179
}

Controller/EditInPlaceController.php

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
namespace Translation\Bundle\Controller;
1313

1414
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
15-
use Symfony\Component\Finder\Finder;
1615
use Symfony\Component\HttpFoundation\Request;
1716
use Symfony\Component\HttpFoundation\Response;
1817
use Translation\Bundle\Exception\MessageValidationException;
@@ -45,45 +44,12 @@ public function editAction(Request $request, $configName, $locale)
4544
$storage->update($message);
4645
}
4746

48-
$this->rebuildTranslations($locale);
47+
$cacheClearer = $this->get('php_translation.cache_clearer');
48+
$cacheClearer->clearAndWarmUp($locale);
4949

5050
return new Response();
5151
}
5252

53-
/**
54-
* Remove the Symfony translation cache and warm it up again.
55-
*
56-
* @param $locale
57-
*/
58-
private function rebuildTranslations($locale)
59-
{
60-
$cacheDir = $this->getParameter('kernel.cache_dir');
61-
$translationDir = sprintf('%s/translations', $cacheDir);
62-
63-
$filesystem = $this->get('filesystem');
64-
$finder = new Finder();
65-
66-
if (!is_dir($translationDir)) {
67-
mkdir($translationDir);
68-
}
69-
70-
if (!is_writable($translationDir)) {
71-
throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $translationDir));
72-
}
73-
74-
// Remove the translations for this locale
75-
$files = $finder->files()->name('*.'.$locale.'.*')->in($translationDir);
76-
foreach ($files as $file) {
77-
$filesystem->remove($file);
78-
}
79-
80-
// Build them again
81-
$translator = $this->get('translator');
82-
if (method_exists($translator, 'warmUp')) {
83-
$translator->warmUp($translationDir);
84-
}
85-
}
86-
8753
/**
8854
* Get and validate messages from the request.
8955
*

Resources/config/services.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ services:
2525
class: Translation\Bundle\Service\Importer
2626
arguments: ["@php_translation.extractor"]
2727

28+
php_translation.cache_clearer:
29+
class: Translation\Bundle\Service\CacheClearer
30+
arguments: ["%kernel.cache_dir%", "@translator", "@filesystem"]
31+
2832
php_translation.local_file_storage.abstract:
2933
class: Translation\SymfonyStorage\FileStorage
3034
abstract: true

Service/CacheClearer.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the PHP Translation package.
5+
*
6+
* (c) PHP Translation team <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Translation\Bundle\Service;
13+
14+
use Symfony\Component\Filesystem\Filesystem;
15+
use Symfony\Component\Finder\Finder;
16+
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
17+
use Symfony\Component\Translation\TranslatorInterface;
18+
19+
/**
20+
* A service able to read and clear the Symfony Translation cache.
21+
*
22+
* @author Damien A. <[email protected]>
23+
*/
24+
final class CacheClearer
25+
{
26+
/**
27+
* @var string
28+
*/
29+
private $kernelCacheDir;
30+
31+
/**
32+
* @var TranslatorInterface
33+
*/
34+
private $translator;
35+
36+
/**
37+
* @var Filesystem
38+
*/
39+
private $filesystem;
40+
41+
public function __construct($kernelCacheDir, TranslatorInterface $translator, Filesystem $filesystem)
42+
{
43+
$this->kernelCacheDir = $kernelCacheDir;
44+
$this->translator = $translator;
45+
$this->filesystem = $filesystem;
46+
}
47+
48+
/**
49+
* Remove the Symfony translation cache and warm it up again.
50+
*
51+
* @param string|null $locale Optional filter to clear only one locale.
52+
*/
53+
public function clearAndWarmUp($locale = null)
54+
{
55+
$translationDir = sprintf('%s/translations', $this->kernelCacheDir);
56+
57+
$finder = new Finder();
58+
59+
// Make sure the directory exists
60+
$this->filesystem->mkdir($translationDir);
61+
62+
// Remove the translations for this locale
63+
$files = $finder->files()->name($locale ? '*.'.$locale.'.*' : '*')->in($translationDir);
64+
foreach ($files as $file) {
65+
$this->filesystem->remove($file);
66+
}
67+
68+
// Build them again
69+
if ($this->translator instanceof WarmableInterface) {
70+
$this->translator->warmUp($translationDir);
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)