Skip to content

Instantly share code, notes, and snippets.

@ker0x
Created May 5, 2023 07:58
Show Gist options
  • Save ker0x/e050e7d1c5b7c1d1f88e3dd825f75f52 to your computer and use it in GitHub Desktop.
Save ker0x/e050e7d1c5b7c1d1f88e3dd825f75f52 to your computer and use it in GitHub Desktop.
A Symfony Form extension to display emoji country flag for CountryType
<?php
declare(strict_types=1);
namespace App\Form\Extension;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\ChoiceList\ChoiceList;
use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader;
use Symfony\Component\Form\Exception\LogicException;
use Symfony\Component\Form\Extension\Core\Type\CountryType;
use Symfony\Component\Intl\Countries;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
final class CountryTypeExtension extends AbstractTypeExtension
{
public const FORMAT_WITH_NAME = '{name}';
public const FORMAT_WITH_FLAG = '{flag}';
public const FORMAT_WITH_FLAG_AND_NAME = '{flag} {name}';
public const FLAG_POSITION_BEFORE = 'before';
public const FLAG_POSITION_AFTER = 'after';
public static function getExtendedTypes(): iterable
{
return [CountryType::class];
}
public static function getFlag(string $countryCode): string
{
$offset = 0x1F1A5;
return
mb_chr($offset + mb_ord($countryCode[0], 'UTF-8'), 'UTF-8').
mb_chr($offset + mb_ord($countryCode[1], 'UTF-8'), 'UTF-8');
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'choice_loader' => function (Options $options) {
if (!class_exists(Intl::class)) {
throw new LogicException(sprintf('The "symfony/intl" component is required to use "%s". Try running "composer require symfony/intl".', CountryType::class));
}
$choiceTranslationLocale = $options['choice_translation_locale'];
$alpha3 = $options['alpha3'];
$format = $options['format'];
$flagPosition = $options['flag_position'];
return ChoiceList::loader($this, new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale, $alpha3, $format, $flagPosition) {
$countries = $alpha3 ? Countries::getAlpha3Names($choiceTranslationLocale) : Countries::getNames($choiceTranslationLocale);
$choices = $countries;
if (self::FORMAT_WITH_FLAG === $format) {
foreach ($countries as $countryCode => $countryName) {
$choices[$countryCode] = self::getFlag($countryCode);
}
} elseif (self::FORMAT_WITH_FLAG_AND_NAME === $format) {
$choices = [];
foreach ($countries as $countryCode => $countryName) {
$values = [self::getFlag($countryCode), $countryName];
if (self::FLAG_POSITION_AFTER === $flagPosition) {
$values = array_reverse($values);
}
$choices[$countryCode] = sprintf('%s %s', ...$values);
}
}
return array_flip($choices);
}), [$choiceTranslationLocale, $alpha3]);
},
'format' => self::FORMAT_WITH_NAME,
'flag_position' => self::FLAG_POSITION_BEFORE,
]);
$resolver->setAllowedTypes('format', ['string']);
$resolver->setAllowedTypes('flag_position', ['string']);
$resolver->setAllowedValues('format', [self::FORMAT_WITH_NAME, self::FORMAT_WITH_FLAG, self::FORMAT_WITH_FLAG_AND_NAME]);
$resolver->setAllowedValues('flag_position', [self::FLAG_POSITION_BEFORE, self::FLAG_POSITION_AFTER]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment