Skip to content
Snippets Groups Projects
class-settings.php 5.87 KiB
Newer Older
Lucas García's avatar
Lucas García committed
<?php

namespace WPCT_ABSTRACT;
Lucas García's avatar
Lucas García committed

class Undefined
{
};

abstract class Settings extends Singleton
{
    protected $group_name;
    protected $_default = [];
Lucas García's avatar
Lucas García committed

    abstract public function register();

    public function __construct($textdomain)
    {
        $this->group_name = $textdomain;
    }

    public function get_name()
    {
        return $this->group_name;
    }

    public function register_setting($name)
    {
        $default = $this->get_default($name);
        $default = $this->get_default($name, $default);
Lucas García's avatar
Lucas García committed
        register_setting(
            $this->group_name,
            $name,
            [
                'type' => 'array',
                'show_in_rest' => false,
                'default' => $default,
Lucas García's avatar
Lucas García committed
            ],
        );

        add_settings_section(
            $name . '_section',
            __($name . '--title', 'wpct'),
Lucas García's avatar
Lucas García committed
            function () use ($name) {
                $title = __($name . '--description', 'wpct');
Lucas García's avatar
Lucas García committed
                echo "<p>{$title}</p>";
            },
            $this->group_name,
        );

        $this->_default[$name] = $default;
Lucas García's avatar
Lucas García committed

        foreach (array_keys($default) as $field) {
Lucas García's avatar
Lucas García committed
            $this->register_field($field, $name);
        }
    }

    public function register_field($field_name, $setting_name)
    {
        $field_id = $setting_name . '__' . $field_name;
        add_settings_field(
            $field_name,
            __($field_id . '--label', 'wpct'),
Lucas García's avatar
Lucas García committed
            function () use ($setting_name, $field_name) {
                echo $this->field_render($setting_name, $field_name);
            },
            $this->group_name,
            $setting_name . '_section',
            [
                'class' => $field_id,
            ]
        );
    }

    public function field_render()
    {
        $args = func_get_args();
        $setting = $args[0];
        $field = $args[1];
        if (count($args) >= 3) {
            $value = $args[2];
        } else {
            $value = new Undefined();
        }

        return $this->_field_render($setting, $field, $value);
    }

    private function _field_render($setting, $field, $value)
    {
        $is_root = false;
        if ($value instanceof Undefined) {
            $value = $this->option_getter($setting, $field);
            $is_root = true;
        }

        if (!is_array($value)) {
            return $this->input_render($setting, $field, $value);
        } else {
            $fieldset = $this->fieldset_render($setting, $field, $value);
            if ($is_root) {
                $fieldset = $this->control_style($setting, $field)
                    . $fieldset . $this->control_render($setting, $field);
            }

            return $fieldset;
        }
    }

    public function input_render($setting, $field, $value)
    {
        $default_value = $this->get_default($setting);
Lucas García's avatar
Lucas García committed
        $keys = explode('][', $field);
        $is_list = is_list($default_value);
        for ($i = 0; $i < count($keys); $i++) {
            $key = $keys[$i];
            if ($is_list) {
                $key = (int) $key;
            }
            $default_value = isset($default_value[$key]) ? $default_value[$key] : $default_value[0];
            $is_list = is_list($default_value);
        }
        $is_bool = is_bool($default_value);
        if ($is_bool) {
            $is_bool = true;
            $value = 'on' === $value;
        }

        if ($is_bool) {
            return "<input type='checkbox' name='{$setting}[$field]' " . ($value ? 'checked' : '') . " />";
        } else {
            return "<input type='text' name='{$setting}[{$field}]' value='{$value}' />";
        }
    }

    public function fieldset_render($setting, $field, $data)
    {
        $table_id = $setting . '__' . str_replace('][', '_', $field);
        $fieldset = "<table id='{$table_id}'>";
        $is_list = is_list($data);
        foreach (array_keys($data) as $key) {
            $fieldset .= '<tr>';
            if (!$is_list) {
                $fieldset .= "<th>{$key}</th>";
            }
            $_field = $field . '][' . $key;
            $fieldset .= "<td>{$this->field_render($setting, $_field, $data[$key])}</td>";
            $fieldset .= '</tr>';
        }
        $fieldset .= '</table>';

        return $fieldset;
    }

    public function control_render($setting, $field)
    {
        $default = $this->get_default($setting);
Lucas García's avatar
Lucas García committed
        ob_start();
        ?>
        <div class="<?= $setting; ?>__<?= $field ?>--controls">
            <button class="button button-primary" data-action="add">Add</button>
            <button class="button button-secondary" data-action="remove">Remove</button>
        </div>
        <?php include 'fieldset-control-js.php' ?>
<?php
Lucas García's avatar
Lucas García committed
        return ob_get_clean();
    }

    public function control_style($setting, $field)
    {
        return "<style>#{$setting}__{$field} td td,#{$setting}__{$field} td th{padding:0}#{$setting}__{$field} table table{margin-bottom:1rem}</style>";
    }

    public function option_getter($setting, $option)
    {
        $default = $this->get_default($setting, $option);
        $setting = get_option($setting) ?: [];
Lucas García's avatar
Lucas García committed
        if (!key_exists($option, $setting)) {
            return null;
        }

        if (empty($setting[$option])) {
            return $default;
Lucas García's avatar
Lucas García committed
        } elseif (is_list($setting[$option])) {
            // $setting[$option] = array_map($setting[$option]);
Lucas García's avatar
Lucas García committed
        }

        return $setting[$option];
    }

    public function get_default($setting_name, $field = null)
Lucas García's avatar
Lucas García committed
    {
        $default = usset($this->_default[$setting_name]) ?: [];
        $default = apply_filters($setting_name . '_default', $default);
Lucas García's avatar
Lucas García committed

        if ($field && isset($default[$field])) {
            return $default[$field];
Lucas García's avatar
Lucas García committed
        }

        return $default;
Lucas García's avatar
Lucas García committed
    }
}

function is_list($arr)
{
    if (!is_array($arr)) {
        return false;
    }
    if (sizeof($arr) === 0) {
        return true;
    }
    return array_keys($arr) === range(0, count($arr) - 1);
}