Skip to content

Commit bf3b54b

Browse files
committed
feature symfony#53096 [Intl] [Emoji] Move emoji data in a new component (smnandre)
This PR was merged into the 7.1 branch. Discussion ---------- [Intl] [Emoji] Move emoji data in a new component | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? | no | New feature? | yes | Deprecations? | yes | Issues | | License | MIT This PR move all the emoji data & code from the Intl component into its own new Emoji component. Objectives/reasons: * reduce the size of a standard "--webapp" install * allow usage of intl (required if your app uses those validators/form types: BIC, country, currency, language, locale, timezone) without downloading all the emoji data * allow usage of Emoji without downloading all the Intl data Thanks to all the reviewers for the feedbacks, opinions, advices ❤️ --- --- Original (obselete) post below --- This PR move all the emoji data & code from the Intl component into its own new IntlEmoji component. ... and hopefully open a debate aboute the future of the Intl component, its role, and the way we handle "data" in the framework and the repositories > [!IMPORTANT] > 🎙️ DISCLAIMER: This PR contains both metrics and opinions. The metrics were collected this morning in a neutral and transparent manner, ensuring they can be [reproduced by anyone](https://gist.github.com/smnandre/38b081253fc8813a5e638661650b01f6). However, the opinions I present here are just that – opinions, and should not be interpreted as objective truths or claims of fact. Update: details/summary added to improve the readability <details> <summary> ## What is symfony/intl ? </summary> Repository: https://github.com/symfony/intl Documentation: https://symfony.com/doc/current/components/intl.html Unicode: https://home.unicode.org/technical-quick-start-guide/ ### Responsabilities Currently, it seems to me this component: * provides a polifill-ish layer for the intl PHP extension * provides exhaustive formatting + locale data for countries, currencies, date, ... * provides methods to check ISO codes or identifiers * provides a dictionnary emoji -> description for every possible combinaison ### Opiniated remarks Two comments highlight the "blurred lines" I believe this component navigates: #### 1) Access or data ? > This component provides **access** to the localization **data** of the ICU library. Maybe my english is in fault, but it seems to me it does not provides access to the data... it provides the data. #### 2) Unicode = CLDR + ICU + UTC > This component provides access to the localization data of the **ICU library**. CLDR (where the emoji data comes from) is not in the ICU library. I'm quibbling over details here, i know. But i think that illustrates the volatile "scope" and "responsabilities" of this component. So we come close to the problem... </details> <details> <summary> ## Symfony/Intl is massive </summary> The data included in the Intl component is massive (especially the emoji descriptions), and will grow more every semester. I looked at the following cases * source code * symfony/symfony : https://github.com/symfony/symfony/archive/refs/heads/7.0.zip * symfony/intl : https://github.com/symfony/intl/archive/refs/heads/7.0.zip * installed * standalone: new folder + composer require symfony/intl * webapp: new folder + symfony create --webapp Versions: * 6.0 6.1 6.2 6.3 6.4 7.0 * Emoji data were added in 6.2 ### Some metrics... | | Size (zip) | Size (unzipped) | Files | PHP Files | | - | - | - | - | - | | symfony/symfony | 12.91 | 58.6 | 6006 | 4729 | | symfony/intl | 7.5 | 43.2 | 1517 | 1487 | | % | 58.1% | 73.8% | 25.3% | 31.5% | So symfony/intl accounts for 30% of the files in the monorepo ... and nearly **75% of its total disk size**. ### ...over time **Size (in MB) of the sources** | | 6.0 | 6.1 | 6.2 | 6.3 | 6.4 | 7.0 | |--------|-----|-----|-----|-----|-----|-----| | intl |15.1 |15.1 |41.8 |41.9 |43.2 |43.2 | | symfony|28.8 |29.1 |56.5 |58.1 |59.8 |58.6 | It was already big in previous versions, but since the emoji data integration, it's off charts. The symfony/intl alone is twice as big as: all the other components, all the bridges and all the bundles. Combined. And it's not over. At all. ### Why it'll grow more The ICU components used in the component are well-defined and constrained by 'real-world' factors, so we can expect minor changes regarding countries, formatting data, etc. It's unlikely, for instance, that 200 new countries will suddenly emerge in 2024. However, emojis may present a major challenge in the near future. New ones are added with every CLDR release. Except for a significant drop (like the upcoming 2000 hieroglyphs), this should be a gradual increase. What bothers me more is the 'combinatorial nature' of these descriptions. We generate a line of text for every combination. And that's why this component is so large. But it's just the beginning of what could be exponential growth. As of today, the 'hand emoji' has variations for skin color (I'm not certain, but let's say there are 6 possible colors), and emojis with multiple people often vary by gender ('boy and two girls'). In the upcoming release, a new variable is the concept of 'left-handed' versus 'right-handed'. So, we'll create a new line for every existing emoji with a visible hand. But we'll need way more than just a new line, because of every emoji where two hands are visible. I don't remember if it's already implemented, but there was discussion about including the same thing for the age of a person, or some hairstyles. So, the symfony/intl component could very soon be 50GB, and a short while later 10^80TB. But there's no way it reduces in size... or even slows its growth. </details> <details> <summary> ## And.... where is the problem ? </summary> I see negative effect on three very different layers. ### Developper Experience Whether these values are low or not in absolute terms (and I have no doubt that everyone will have their own opinion on this)... the reality is that users are downloading a component that is twice as heavy as all the others combined... and this inevitably affects installation times, bandwidth, update times, static analysis, IDE indexing, etc. A prime example is Docker on macOS, which was a real pain until recently with Orbstack, and the performance nightmare was directly related to the number of files mounted in a volume. ### Contributor experience I've lost count of how many times I've seen a contributor propose a feature only to be told: it's userland. (Full disclosure, I understand and share this point of view). But it can be frustrating to see closed doors for a few classes, while at the same time Symfony contains hundreds of lines like 'young woman with dark hair and kid' ### Real world consequences: Ecological & financial costs I have no desire to open a debate (on either of those topics). But again, these small things have real-world consequences. We are talking about Symfony, so the impact is enormous, even on small matters ### What is the real impact ? Downloads data, as provided by packagist (collected today) | Package | install total | install (last 30 days) | |---------|---------------|------------------------| | symfony/intl | 111,000,000 | 2,800,000 | | [symfony/http-foundation](https://packagist.org/packages/symfony/http-foundation) | 528,000,000 | 11,250,000 | | symfony/console | 678,000,000 | 12,900,000 | | symfony/console | 678,000,000 | 12,900,000 | | symfony/translation | 508,000,000 | 10,400,000 | Let's agree on: "it's not without an impact". </details> <details> <summary> ## Why is it used ? </summary> ### For its quality Please don't misinterpret my message. I'm not criticizing the value of the component or questioning its qualities. Besides, my opinion wouldn't have any value for that matter anyway. And i'm absolutely convinced a lot of people decide to install this component knowing what they do. ### For another reason But there are also people who install... Symfony. The recommended installation procedure, as outlined in the documentation on the website, is to install the web application skeleton, which requires symfony/intl. To revisit the argument from earlier, I'm really not sure if anyone realizes after installation why its vendors directory is 80MB and what it's used for (young woman with...). I'm unsure why symfony/intl is included by default in a new project, while other components are not. As a developer, I would appreciate the ability to install a small, lightweight application or to have more packages for the same amount of overhead :) ### For another reason (bis) "There is a third reason, and once again, I'm not fully understanding the situation (and may not have all the backstory required for it). The Country validator requires symfony/intl to validate a given string as a valid ISO alpha country code. To do this, it tries to retrieve the list of country names (indexed by code) from the locale data. Consequently, it's not possible to use BIC, Country, Currency, and probably others without symfony/intl. So, if a developer installs symfony/validator and then wants to validate a BIC, they cannot do so without downloading 80MB of locale-specific data. Wouldn't it be simpler to have a couple of ISO classes/methods in the Validator component? Or perhaps create a small component just for that purpose? Because having to parse giant files just to check if "FR" is a valid ISO country code seems quite inefficient to me. </details> ## Well: Suggestions So, personal conclusion and some suggestions.. ### TODO list Sooner * move "emoji" out of Symfony\Intl * remove "intl" from symfony/webapp * fix the validator requirements Later * move "intl" out of the monorepo * create a distinct class/component to handle iso lists ### Discussions - [x] Handle the BC layer (require symfony/intl-emoji in symfony/intl ?) - [x] Find a way to handle the exponential growth of those files -- Open to any feedback :) Commits ------- f5ba7e3 Move & adapt "emoji code" from Intl into its own component
2 parents e5d1e1e + f5ba7e3 commit bf3b54b

File tree

185 files changed

+445
-146
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

185 files changed

+445
-146
lines changed

.github/workflows/intl-data-tests.yml

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1-
name: Intl data
1+
name: Intl/Emoji data
22

33
on:
44
push:
55
paths:
6+
- 'src/Symfony/Component/Emoji/*.php'
7+
- 'src/Symfony/Component/Emoji/Resources/data/**'
8+
- 'src/Symfony/Component/Emoji/Tests/*Test.php'
69
- 'src/Symfony/Component/Intl/*.php'
710
- 'src/Symfony/Component/Intl/Util/GitRepository.php'
811
- 'src/Symfony/Component/Intl/Resources/data/**'
912
- 'src/Symfony/Component/Intl/Tests/*Test.php'
1013
- 'src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php'
1114
pull_request:
1215
paths:
16+
- 'src/Symfony/Component/Emoji/*.php'
17+
- 'src/Symfony/Component/Emoji/Resources/data/**'
18+
- 'src/Symfony/Component/Emoji/Tests/*Test.php'
1319
- 'src/Symfony/Component/Intl/*.php'
1420
- 'src/Symfony/Component/Intl/Util/GitRepository.php'
1521
- 'src/Symfony/Component/Intl/Resources/data/**'
@@ -29,7 +35,7 @@ permissions:
2935

3036
jobs:
3137
tests:
32-
name: Intl data
38+
name: Intl/Emoji data
3339
runs-on: Ubuntu-20.04
3440

3541
steps:
@@ -80,15 +86,23 @@ jobs:
8086
- name: Run intl-data tests
8187
run: ./phpunit --group intl-data -v
8288

83-
- name: Test with compressed data
89+
- name: Test intl-data with compressed data
8490
run: |
8591
[ -f src/Symfony/Component/Intl/Resources/data/locales/en.php ]
8692
[ ! -f src/Symfony/Component/Intl/Resources/data/locales/en.php.gz ]
87-
[ -f src/Symfony/Component/Intl/Resources/data/transliterator/emoji/emoji-en.php ]
88-
[ ! -f src/Symfony/Component/Intl/Resources/data/transliterator/emoji/emoji-en.php.gz ]
8993
src/Symfony/Component/Intl/Resources/bin/compress
9094
[ ! -f src/Symfony/Component/Intl/Resources/data/locales/en.php ]
9195
[ -f src/Symfony/Component/Intl/Resources/data/locales/en.php.gz ]
92-
[ ! -f src/Symfony/Component/Intl/Resources/data/transliterator/emoji/emoji-en.php ]
93-
[ -f src/Symfony/Component/Intl/Resources/data/transliterator/emoji/emoji-en.php.gz ]
9496
./phpunit src/Symfony/Component/Intl
97+
98+
- name: Run Emoji tests
99+
run: ./phpunit src/Symfony/Component/Emoji -v
100+
101+
- name: Test Emoji with compressed data
102+
run: |
103+
[ -f src/Symfony/Component/Emoji/Resources/data/emoji-en.php ]
104+
[ ! -f src/Symfony/Component/Emoji/Resources/data/emoji-en.php.gz ]
105+
src/Symfony/Component/Emoji/Resources/bin/compress
106+
[ ! -f src/Symfony/Component/Emoji/Resources/data/emoji-en.php ]
107+
[ -f src/Symfony/Component/Emoji/Resources/data/emoji-en.php.gz ]
108+
./phpunit src/Symfony/Component/Emoji

.github/workflows/package-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121

2222
- name: Find packages
2323
id: find-packages
24-
run: echo "packages=$(php .github/get-modified-packages.php $(find src/Symfony -mindepth 2 -type f -name composer.json -printf '%h\n' | grep -v src/Symfony/Component/Intl/Resources/emoji |jq -R -s -c 'split("\n")[:-1]') $(git diff --name-only origin/${{ github.base_ref }} HEAD | grep src/ | jq -R -s -c 'split("\n")[:-1]'))" >> $GITHUB_OUTPUT
24+
run: echo "packages=$(php .github/get-modified-packages.php $(find src/Symfony -mindepth 2 -type f -name composer.json -printf '%h\n' | grep -v src/Symfony/Component/Emoji/Resources/bin |jq -R -s -c 'split("\n")[:-1]') $(git diff --name-only origin/${{ github.base_ref }} HEAD | grep src/ | jq -R -s -c 'split("\n")[:-1]'))" >> $GITHUB_OUTPUT
2525

2626
- name: Verify meta files are correct
2727
run: |

.github/workflows/unit-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ jobs:
9595
echo SYMFONY_DEPRECATIONS_HELPER=weak >> $GITHUB_ENV
9696
cp composer.json composer.json.orig
9797
echo -e '{\n"require":{'"$(grep phpunit-bridge composer.json)"'"php":"*"},"minimum-stability":"dev"}' > composer.json
98-
php .github/build-packages.php HEAD^ $SYMFONY_VERSION $(find src/Symfony -mindepth 2 -type f -name composer.json -printf '%h\n' | grep -v src/Symfony/Component/Intl/Resources/emoji)
98+
php .github/build-packages.php HEAD^ $SYMFONY_VERSION $(find src/Symfony -mindepth 2 -type f -name composer.json -printf '%h\n' | grep -v src/Symfony/Component/Emoji/Resources/bin)
9999
mv composer.json composer.json.phpunit
100100
mv composer.json.orig composer.json
101101
fi

.php-cs-fixer.dist.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
'Symfony/Bundle/FrameworkBundle/Resources/views/Form',
5757
// explicit trigger_error tests
5858
'Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/',
59+
'Symfony/Component/Emoji/Resources/',
5960
'Symfony/Component/Intl/Resources/data/',
6061
])
6162
// explicit tests for ommited @param type, against `no_superfluous_phpdoc_tags`

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"symfony/doctrine-bridge": "self.version",
7272
"symfony/dom-crawler": "self.version",
7373
"symfony/dotenv": "self.version",
74+
"symfony/emoji": "self.version",
7475
"symfony/error-handler": "self.version",
7576
"symfony/event-dispatcher": "self.version",
7677
"symfony/expression-language": "self.version",

psalm.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
<directory name="src/Symfony/*/*/Tests" />
1818
<directory name="src/Symfony/*/*/*/Tests" />
1919
<directory name="src/Symfony/*/*/*/*/Tests" />
20-
<directory name="src/Symfony/Component/Intl/Resources/emoji/" />
20+
<directory name="src/Symfony/Component/Intl/Resources/data/" />
21+
<directory name="src/Symfony/Component/Emoji/Resources/data/" />
2122
<directory name="vendor" />
2223
</ignoreFiles>
2324
</projectFiles>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/Resources/bin/build.php export-ignore
2+
/Resources/bin/composer.json export-ignore
3+
/Resources/bin/Makefile export-ignore
4+
/Resources/bin/README.md export-ignore
5+
/Tests export-ignore
6+
/phpunit.xml.dist export-ignore
7+
/.gitattributes export-ignore
8+
/.gitignore export-ignore
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
composer.lock
3+
phpunit.xml
Lines changed: 7 additions & 0 deletions
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[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 Symfony\Component\Emoji;
13+
14+
use Symfony\Component\Emoji\Util\GzipStreamWrapper;
15+
16+
if (!class_exists(\Transliterator::class)) {
17+
throw new \LogicException(sprintf('You cannot use the "%s\EmojiTransliterator" class as the "intl" extension is not installed. See https://php.net/intl.', __NAMESPACE__));
18+
}
19+
20+
final class EmojiTransliterator extends \Transliterator
21+
{
22+
private const QUICK_CHECK = "\xA9\xAE\xE2\xE3\xF0";
23+
private const REVERSEABLE_IDS = [
24+
'emoji-github' => 'github-emoji',
25+
'emoji-slack' => 'slack-emoji',
26+
'github-emoji' => 'emoji-github',
27+
'slack-emoji' => 'emoji-slack',
28+
];
29+
30+
public readonly string $id;
31+
32+
private array $map;
33+
34+
private string $quickCheck;
35+
36+
private \Transliterator $transliterator;
37+
38+
public static function create(string $id, int $direction = self::FORWARD): self
39+
{
40+
$id = strtolower($id);
41+
42+
if (!isset(self::REVERSEABLE_IDS[$id]) && !str_starts_with($id, 'emoji-')) {
43+
$id = 'emoji-'.$id;
44+
}
45+
46+
if (self::REVERSE === $direction) {
47+
if (!isset(self::REVERSEABLE_IDS[$id])) {
48+
// Create a failing reverse-transliterator to populate intl_get_error_*()
49+
\Transliterator::createFromRules('A > B')->createInverse();
50+
51+
throw new \IntlException(intl_get_error_message(), intl_get_error_code());
52+
}
53+
$id = self::REVERSEABLE_IDS[$id];
54+
}
55+
56+
$file = __DIR__."/Resources/data/{$id}.php";
57+
if (!preg_match('/^[a-z0-9@_\\.\\-]*$/', $id) || !is_file($file) && !is_file($file .= '.gz')) {
58+
\Transliterator::create($id); // Populate intl_get_error_*()
59+
60+
throw new \IntlException(intl_get_error_message(), intl_get_error_code());
61+
}
62+
63+
/**
64+
* @var array<string, array> $maps
65+
*/
66+
static $maps;
67+
68+
// Create an instance of \Transliterator with a custom id; that's the only way
69+
static $newInstance;
70+
$instance = ($newInstance ??= (new \ReflectionClass(self::class))->newInstanceWithoutConstructor(...))();
71+
$instance->id = $id;
72+
$instance->map = $maps[$id] ??= str_ends_with($file, '.gz') ? GzipStreamWrapper::require($file) : require $file;
73+
74+
return $instance;
75+
}
76+
77+
public function createInverse(): self
78+
{
79+
return self::create($this->id, \Transliterator::REVERSE);
80+
}
81+
82+
public function getErrorCode(): int|false
83+
{
84+
return $this->transliterator?->getErrorCode() ?? 0;
85+
}
86+
87+
public function getErrorMessage(): string|false
88+
{
89+
return $this->transliterator?->getErrorMessage() ?? false;
90+
}
91+
92+
public static function listIDs(): array
93+
{
94+
static $ids = [];
95+
96+
if ($ids) {
97+
return $ids;
98+
}
99+
100+
foreach (scandir(__DIR__.'/Resources/data/') as $file) {
101+
if (str_ends_with($file, '.php.gz')) {
102+
$ids[] = substr($file, 0, -7);
103+
} elseif (str_ends_with($file, '.php')) {
104+
$ids[] = substr($file, 0, -4);
105+
}
106+
}
107+
108+
return $ids;
109+
}
110+
111+
public function transliterate(string $string, int $start = 0, int $end = -1): string|false
112+
{
113+
$this->quickCheck ??= str_starts_with(array_key_first($this->map), ':') ? ':' : self::QUICK_CHECK;
114+
115+
if (0 === $start && -1 === $end && preg_match('//u', $string)) {
116+
return \strlen($string) === strcspn($string, $this->quickCheck) ? $string : strtr($string, $this->map);
117+
}
118+
119+
// Here we rely on intl to validate the $string, $start and $end arguments
120+
// and to slice the string. Slicing is done by replacing the part if $string
121+
// between $start and $end by a unique cookie that can be reliably used to
122+
// identify which part of $string should be transliterated.
123+
124+
static $cookie;
125+
static $transliterator;
126+
127+
$cookie ??= hash('xxh128', random_bytes(8));
128+
$this->transliterator ??= clone $transliterator ??= \Transliterator::createFromRules('[:any:]* > '.$cookie);
129+
130+
if (false === $result = $this->transliterator->transliterate($string, $start, $end)) {
131+
return false;
132+
}
133+
134+
$parts = explode($cookie, $result);
135+
$start = \strlen($parts[0]);
136+
$length = -\strlen($parts[1]) ?: null;
137+
$string = substr($string, $start, $length);
138+
139+
return $parts[0].(\strlen($string) === strcspn($string, $this->quickCheck) ? $string : strtr($string, $this->map)).$parts[1];
140+
}
141+
}

src/Symfony/Component/Emoji/LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2024-present Fabien Potencier
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is furnished
8+
to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

src/Symfony/Component/Emoji/README.md

Lines changed: 18 additions & 0 deletions

src/Symfony/Component/Intl/Resources/emoji/build.php renamed to src/Symfony/Component/Emoji/Resources/bin/build.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
final class Builder
2727
{
28-
private const TARGET_DIR = __DIR__.'/../data/transliterator/emoji/';
28+
private const TARGET_DIR = __DIR__.'/../data/';
2929

3030
public static function getEmojisCodePoints(): array
3131
{
@@ -233,7 +233,7 @@ public static function saveRules(iterable $rulesByLocale): void
233233
sort($firstChars);
234234

235235
$quickCheck = '"'.str_replace('%', '\\x', rawurlencode(implode('', $firstChars))).'"';
236-
$file = dirname(__DIR__, 2).'/Transliterator/EmojiTransliterator.php';
236+
$file = dirname(__DIR__, 2).'/EmojiTransliterator.php';
237237
file_put_contents($file, preg_replace('/QUICK_CHECK = .*;/m', "QUICK_CHECK = {$quickCheck};", file_get_contents($file)));
238238
}
239239

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
/*
5+
* This file is part of the Symfony package.
6+
*
7+
* (c) Fabien Potencier <[email protected]>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
if ('cli' !== PHP_SAPI) {
14+
throw new Exception('This script must be run from the command line.');
15+
}
16+
if (!extension_loaded('zlib')) {
17+
throw new Exception('This script requires the zlib extension.');
18+
}
19+
20+
$iterator = new RecursiveIteratorIterator(
21+
new RecursiveDirectoryIterator(
22+
dirname(__DIR__).'/data',
23+
FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS
24+
)
25+
);
26+
27+
foreach ($iterator as $file) {
28+
if ('php' !== $file->getExtension()) {
29+
continue;
30+
}
31+
32+
$data = file_get_contents($file);
33+
file_put_contents('compress.zlib://'.$file.'.gz', $data);
34+
35+
unlink($file.(filesize($file.'.gz') >= strlen($data) ? '.gz' : ''));
36+
}

src/Symfony/Component/Intl/Tests/Transliterator/EmojiTransliteratorTest.php renamed to src/Symfony/Component/Emoji/Tests/EmojiTransliteratorTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\Component\Intl\Tests\Transliterator;
12+
namespace Symfony\Component\Emoji\Tests;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Emoji\EmojiTransliterator;
1516
use Symfony\Component\Finder\Finder;
16-
use Symfony\Component\Intl\Transliterator\EmojiTransliterator;
1717

1818
/**
1919
* @requires extension intl
@@ -95,7 +95,7 @@ public function testAllTransliterator(string $locale)
9595
public static function provideLocaleTest(): iterable
9696
{
9797
$file = (new Finder())
98-
->in(__DIR__.'/../../Resources/data/transliterator/emoji')
98+
->in(__DIR__.'/../Resources/data')
9999
->name('*.php')
100100
->notName('emoji-strip.php')
101101
->files()

0 commit comments

Comments
 (0)