Skip to content

Commit

Permalink
add options factory and formatter options
Browse files Browse the repository at this point in the history
  • Loading branch information
ericges committed Mar 25, 2024
1 parent fa7c812 commit a3e2ecb
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 29 deletions.
79 changes: 79 additions & 0 deletions src/Options/OptionsFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

namespace HeimrichHannot\UtilsBundle\Options;

use BadMethodCallException;

class OptionsFactory
{
protected array $options = [];

public function get(string $key, mixed $default = null): mixed
{
return $this->$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();
}
}
52 changes: 23 additions & 29 deletions src/Util/FormatterUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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.
*
Expand All @@ -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);
}
Expand All @@ -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);
Expand Down Expand Up @@ -138,7 +127,7 @@ public function formatDcaFieldValue(
$dc,
$field,
$v,
$settings | self::OPTION_CALL_IS_RECURSIVE,
$settings,
$dcaOverride,
$arrayJoiner,
$cachedOptions
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down
21 changes: 21 additions & 0 deletions src/Util/FormatterUtil/FormatDcaFieldValueOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace HeimrichHannot\UtilsBundle\Util\FormatterUtil;

use HeimrichHannot\UtilsBundle\Options\OptionsFactory;

/**
* @method $this setPreserveEmptyArrayValues(bool $value)
* @method $this setLocalize(bool $value)
* @method $this setLoadDca(bool $value)
* @method $this setCacheOptions(bool $value)
* @method $this setReplaceInsertTags(bool $value)
*/
class FormatDcaFieldValueOptions extends OptionsFactory
{
public bool $preserveEmptyArrayValues = false;
public bool $localize = true;
public bool $loadDca = true;
public bool $cacheOptions = true;
public bool $replaceInsertTags = true;
}

0 comments on commit a3e2ecb

Please sign in to comment.