diff --git a/src/Options/OptionsFactory.php b/src/Options/OptionsFactory.php new file mode 100644 index 00000000..8ad9c04d --- /dev/null +++ b/src/Options/OptionsFactory.php @@ -0,0 +1,79 @@ +$key ?? $this->options[$key] ?? $default; + } + + public function set(string $key, mixed $value): static + { + if (property_exists($this, $key)) { + $this->$key = $value; + } + $this->options[$key] = $value; + return $this; + } + + public function has(string $key): bool + { + return isset($this->$key) || isset($this->options[$key]); + } + + public function del(string $key): static + { + unset($this->options[$key]); + return $this; + } + + protected function methodNameToOptionKey(string $name): string + { + return lcfirst(substr($name, 3)); + } + + public function __call(string $name, array $arguments): mixed + { + if (strlen($name) < 4) { + throw new BadMethodCallException(sprintf('Method %s does not exist', $name)); + } + + $numArgs = count($arguments); + if ($numArgs < 1 || $numArgs > 1) { + throw new BadMethodCallException(sprintf('Method %s expects exactly one argument', $name)); + } + + $key = static::methodNameToOptionKey($name); + $prefix = substr($name, 0, 3); + + return match ($prefix) + { + 'set' => $this->set($key, $arguments[0]), + 'get' => $this->get($key, $arguments[0] ?? null), + 'has' => $this->has($key), + 'del' => $this->del($key), + default => throw new BadMethodCallException(sprintf('Method %s does not exist', $name)), + }; + } + + public function __get(string $name) + { + return $this->get($name); + } + + public function __set(string $name, mixed $value) + { + $this->set($name, $value); + } + + public static function create(): static + { + return new static(); + } +} \ No newline at end of file diff --git a/src/Util/FormatterUtil.php b/src/Util/FormatterUtil.php index 6d2cac2d..ddf884ae 100644 --- a/src/Util/FormatterUtil.php +++ b/src/Util/FormatterUtil.php @@ -14,6 +14,10 @@ use Contao\StringUtil as Str; use Contao\System; use Contao\Validator; +use HeimrichHannot\UtilsBundle\Options\OptionsFactory; +use HeimrichHannot\UtilsBundle\Util\FormatterUtil\FormatDcaFieldValueOptions; + +$cfgt = (new FormatDcaFieldValueOptions())->setPreserveEmptyArrayValues(true); class FormatterUtil { @@ -24,17 +28,6 @@ public function __construct( protected array $kernelBundles ) {} - const OPTION_PRESERVE_EMPTY_ARRAY_VALUES = 2^0; - const OPTION_SKIP_LOCALIZATION = 2^1; - const OPTION_SKIP_DCA_LOADING = 2^2; - const OPTION_SKIP_OPTION_CACHING = 2^3; - const OPTION_SKIP_REPLACE_INSERT_TAGS = 2^4; - /** - * @var FormatterUtil::OPTION_CALL_IS_RECURSIVE Whether the current call is recursive. - * @internal You should not set this option manually. - */ - const OPTION_CALL_IS_RECURSIVE = 2^5; - /** * Makes a DCA field value human-readable. * @@ -44,33 +37,29 @@ public function __construct( * @param string $field The DCA field name. * @param array|string|null $value The value to format. If an array is passed, the values will be evaluated * recursively. - * @param int $settings Additional settings flags. + * @param ?FormatDcaFieldValueOptions $settings Additional settings flags. * @param string $arrayJoiner The string that joins array values. Default: ', '. * @param array|null $dcaOverride Override the DCA field settings. If not set, the DCA field settings will be used. * @param array|null $cachedOptions The cached options to use. If not set, the options-callback will be evaluated. * @return mixed The formatted value. - * - * @see FormatterUtil::OPTION_PRESERVE_EMPTY_ARRAY_VALUES Preserve empty array values. - * @see FormatterUtil::OPTION_SKIP_LOCALIZATION Skip localization. - * @see FormatterUtil::OPTION_SKIP_DCA_LOADING Skip DCA loading. - * @see FormatterUtil::OPTION_SKIP_OPTION_CACHING Skip option caching. - * @see FormatterUtil::OPTION_SKIP_REPLACE_INSERT_TAGS Skip replace insert tags. */ public function formatDcaFieldValue( DataContainer $dc, string $field, array|string|null $value, - int $settings = 0, + OptionsFactory $settings = null, array $dcaOverride = null, string $arrayJoiner = ', ', ?array $cachedOptions = null ): mixed { + $settings ??= new FormatDcaFieldValueOptions(); + $value = Str::deserialize($value); $table = $dc->table; [$system, $controller] = $this->prepareServices(); - if (~$settings & self::OPTION_SKIP_DCA_LOADING) { + if ($settings->loadDca) { $controller->loadDataContainer($table); $system->loadLanguageFile($table); } @@ -91,7 +80,7 @@ public function formatDcaFieldValue( return $this->formatInputUnitField($value, $arrayJoiner); } - if ($cachedOptions === null || $settings & self::OPTION_SKIP_OPTION_CACHING) + if ($cachedOptions === null || !$settings->cacheOptions) { $cachedOptions = $data['options'] ?? $this->utils->dca() ->executeCallback($data['options_callback'] ?? null, $dc); @@ -138,7 +127,7 @@ public function formatDcaFieldValue( $dc, $field, $v, - $settings | self::OPTION_CALL_IS_RECURSIVE, + $settings, $dcaOverride, $arrayJoiner, $cachedOptions @@ -202,8 +191,7 @@ public function formatDcaFieldValue( $value = $cachedOptions[$value] ?? $value; } - if (~$settings & self::OPTION_SKIP_LOCALIZATION - && ($reference = $data['reference'][$value] ?? null)) + if ($settings->localize && ($reference = $data['reference'][$value] ?? null)) { $value = is_array($reference) ? $reference[0] ?? $reference[array_key_first($reference)] ?? $value @@ -217,7 +205,7 @@ public function formatDcaFieldValue( $value = openssl_decrypt($encrypted, 'aes-256-ctr', $key, 0, base64_decode($iv, true)); } - if (~$settings & self::OPTION_SKIP_REPLACE_INSERT_TAGS) + if ($settings->replaceInsertTags) { $value = $this->insertTagParser->replace($value); } @@ -258,18 +246,24 @@ private function isMultiColumnsActive(): bool /** * @param array $values - * @param int $settings + * @param FormatDcaFieldValueOptions $settings * @param string $arraySeparator - * @param callable(array|string|null $value): string $callback The callback to format each value, possibly recursively. + * @param callable(array|string|null $value): string $callback The callback to format each value, possibly + * recursively. * @return string */ - private function formatArray(array $values, int $settings, string $arraySeparator, callable $callback): string + private function formatArray( + array $values, + OptionsFactory $settings, + string $arraySeparator, + callable $callback + ): string { foreach ($values as $k => $v) { $result = $callback($v); - if ($settings & self::OPTION_PRESERVE_EMPTY_ARRAY_VALUES) + if ($settings->preserveEmptyArrayValues) { $values[$k] = $result; continue; diff --git a/src/Util/FormatterUtil/FormatDcaFieldValueOptions.php b/src/Util/FormatterUtil/FormatDcaFieldValueOptions.php new file mode 100644 index 00000000..8edc5fe9 --- /dev/null +++ b/src/Util/FormatterUtil/FormatDcaFieldValueOptions.php @@ -0,0 +1,21 @@ +