| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 | <?php declare(strict_types=1);namespace Grav\Plugin\Form;use Grav\Framework\Form\Interfaces\FormInterface;use Twig\Extension\AbstractExtension;use Twig\TwigFilter;use Twig\TwigFunction;use function is_string;/** * Class GravExtension * @package Grav\Common\Twig\Extension */class TwigExtension extends AbstractExtension{    public function getFilters()    {       return [            new TwigFilter('value_and_label', [$this, 'valueAndLabel'])       ];    }    /**     * Return a list of all functions.     *     * @return array     */    public function getFunctions(): array    {        return [            new TwigFunction('prepare_form_fields', [$this, 'prepareFormFields'], ['needs_context' => true]),            new TwigFunction('prepare_form_field', [$this, 'prepareFormField'], ['needs_context' => true]),            new TwigFunction('include_form_field', [$this, 'includeFormField']),        ];    }    public function valueAndLabel($value): array    {        if (!is_array($value)) {            return [];        }        $list = [];        foreach ($value as $key => $label) {            $list[] = ['value' => $key, 'label' => $label];        }        return $list;    }    /**     * Filters form fields for the current parent.     *     * @param array $context     * @param array $fields Form fields     * @param string|null $parent Parent field name if available     * @return array     */    public function prepareFormFields(array $context, $fields, $parent = null): array    {        $list = [];        if (is_iterable($fields)) {            foreach ($fields as $name => $field) {                $field = $this->prepareFormField($context, $field, $name, $parent);                if ($field) {                    $list[$field['name']] = $field;                }            }        }        return $list;    }    /**     * Filters field name by changing dot notation into array notation.     *     * @param array $context     * @param array $field Form field     * @param string|int|null $name Field name (defaults to field.name)     * @param string|null $parent Parent field name if available     * @param array|null $options List of options to override     * @return array|null     */    public function prepareFormField(array $context, $field, $name = null, $parent = null, array $options = []): ?array    {        // Make sure that the field is a valid form field type and is not being ignored.        if (empty($field['type']) || ($field['validate']['ignore'] ?? false)) {            return null;        }        // Check if we have just a list of fields (no name given).        if (is_int($name)) {            // Look at the field.name and if not set, fall back to the key.            $name = (string)($field['name'] ?? $name);        }        // Make sure that the field has a name.        $name = $name ?? $field['name'] ?? null;        if (!is_string($name) || $name === '') {            return null;        }        // Prefix name with the parent name if needed.        if (str_starts_with($name, '.')) {            $name = $parent ? $parent . $name : (string)substr($name, 1);        } elseif (isset($options['key'])) {            $name = str_replace('*', $options['key'], $name);        }        unset($options['key']);        // Set fields as readonly if form is in readonly mode.        /** @var FormInterface $form */        $form = $context['form'] ?? null;        if ($form && method_exists($form, 'isEnabled') && !$form->isEnabled()) {            $options['disabled'] = true;        }        // Loop through options        foreach ($options as $key => $option) {            $field[$key] = $option;        }        // Always set field name.        $field['name'] = $name;        return $field;    }    /**     * @param string $type     * @param string|string[]|null $layouts     * @param string|null $default     * @return string[]     */    public function includeFormField(string $type, $layouts = null, string $default = null): array    {        $list = [];        foreach ((array)$layouts as $layout) {            $list[] = "forms/fields/{$type}/{$layout}-{$type}.html.twig";        }        $list[] = "forms/fields/{$type}/{$type}.html.twig";        if ($default) {            foreach ((array)$layouts as $layout) {                $list[] = "forms/fields/{$default}/{$layout}-{$default}.html.twig";            }            $list[] = "forms/fields/{$default}/{$default}.html.twig";        }        return $list;    }}
 |