1<?php
2
3namespace dokuwiki\Form;
4
5/**
6 * Class Element
7 *
8 * The basic building block of a form
9 *
10 * @package dokuwiki\Form
11 */
12abstract class Element
13{
14    /**
15     * @var array the attributes of this element
16     */
17    protected $attributes = [];
18
19    /**
20     * @var string The type of this element
21     */
22    protected $type;
23
24    /**
25     * @param string $type The type of this element
26     * @param array $attributes
27     */
28    public function __construct($type, $attributes = [])
29    {
30        $this->type = $type;
31        $this->attributes = $attributes;
32    }
33
34    /**
35     * Type of this element
36     *
37     * @return string
38     */
39    public function getType()
40    {
41        return $this->type;
42    }
43
44    /**
45     * Gets or sets an attribute
46     *
47     * When no $value is given, the current content of the attribute is returned.
48     * An empty string is returned for unset attributes.
49     *
50     * When a $value is given, the content is set to that value and the Element
51     * itself is returned for easy chaining
52     *
53     * @param string $name Name of the attribute to access
54     * @param null|string $value New value to set
55     * @return string|$this
56     */
57    public function attr($name, $value = null)
58    {
59        // set
60        if ($value !== null) {
61            $this->attributes[$name] = $value;
62            return $this;
63        }
64
65        // get
66        if (isset($this->attributes[$name])) {
67            return $this->attributes[$name];
68        } else {
69            return '';
70        }
71    }
72
73    /**
74     * Removes the given attribute if it exists
75     *
76     * @param string $name
77     * @return $this
78     */
79    public function rmattr($name)
80    {
81        if (isset($this->attributes[$name])) {
82            unset($this->attributes[$name]);
83        }
84        return $this;
85    }
86
87    /**
88     * Gets or adds a all given attributes at once
89     *
90     * @param array|null $attributes
91     * @return array|$this
92     */
93    public function attrs($attributes = null)
94    {
95        // set
96        if ($attributes) {
97            foreach ((array) $attributes as $key => $val) {
98                $this->attr($key, $val);
99            }
100            return $this;
101        }
102        // get
103        return $this->attributes;
104    }
105
106    /**
107     * Adds a class to the class attribute
108     *
109     * This is the preferred method of setting the element's class
110     *
111     * @param string $class the new class to add
112     * @return $this
113     */
114    public function addClass($class)
115    {
116        $classes = explode(' ', $this->attr('class'));
117        $classes[] = $class;
118        $classes = array_unique($classes);
119        $classes = array_filter($classes);
120        $this->attr('class', implode(' ', $classes));
121        return $this;
122    }
123
124    /**
125     * Get or set the element's ID
126     *
127     * This is the preferred way of setting the element's ID
128     *
129     * @param null|string $id
130     * @return string|$this
131     */
132    public function id($id = null)
133    {
134        if (strpos($id, '__') === false) {
135            throw new \InvalidArgumentException('IDs in DokuWiki have to contain two subsequent underscores');
136        }
137
138        return $this->attr('id', $id);
139    }
140
141    /**
142     * Get or set the element's value
143     *
144     * This is the preferred way of setting the element's value
145     *
146     * @param null|string $value
147     * @return string|$this
148     */
149    public function val($value = null)
150    {
151        return $this->attr('value', $value);
152    }
153
154    /**
155     * The HTML representation of this element
156     *
157     * @return string
158     */
159    abstract public function toHTML();
160}
161