1<?php
2
3namespace dokuwiki\plugin\struct\meta;
4
5/**
6 * Class Value
7 *
8 * Holds the value for a single "cell". That value may be an array for multi value columns
9 *
10 * @package dokuwiki\plugin\struct\meta
11 */
12class Value
13{
14    /** @var Column */
15    protected $column;
16
17    /** @var  array|int|string */
18    protected $value;
19
20    /** @var  array|int|string */
21    protected $rawvalue = null;
22
23    /** @var array|int|string */
24    protected $display = null;
25
26    /** @var array|int|string */
27    protected $compare = null;
28
29    /** @var bool is this a raw value only? */
30    protected $rawonly = false;
31
32    /**
33     * Value constructor.
34     *
35     * @param Column $column
36     * @param array|int|string $value
37     */
38    public function __construct(Column $column, $value)
39    {
40        $this->column = $column;
41        $this->setValue($value);
42    }
43
44    /**
45     * @return Column
46     */
47    public function getColumn()
48    {
49        return $this->column;
50    }
51
52    /**
53     * @return array|int|string
54     */
55    public function getValue()
56    {
57        if ($this->rawonly) {
58            throw new StructException('Accessing value of rawonly value forbidden');
59        }
60        return $this->value;
61    }
62
63    /**
64     * Access the raw value
65     *
66     * @return array|string (array on multi)
67     */
68    public function getRawValue()
69    {
70        return $this->rawvalue;
71    }
72
73    /**
74     * Access the display value
75     *
76     * @return array|string (array on multi)
77     */
78    public function getDisplayValue()
79    {
80        if ($this->rawonly) {
81            throw new StructException('Accessing displayvalue of rawonly value forbidden');
82        }
83        return $this->display;
84    }
85
86    /**
87     * Access the compare value
88     *
89     * @return array|string (array on multi)
90     */
91    public function getCompareValue()
92    {
93        if ($this->rawonly) {
94            throw new StructException('Accessing comparevalue of rawonly value forbidden');
95        }
96        return $this->compare;
97    }
98
99    /**
100     * Allows overwriting the current value
101     *
102     * Cleans the value(s) of empties
103     *
104     * @param array|int|string $value
105     * @param bool $israw is the passed value a raw value? turns Value into rawonly
106     */
107    public function setValue($value, $israw = false)
108    {
109        $this->rawonly = $israw;
110
111        // treat all givens the same
112        if (!is_array($value)) {
113            $value = array($value);
114        }
115
116        // reset/init
117        $this->value = array();
118        $this->rawvalue = array();
119        $this->display = array();
120        $this->compare = array();
121
122        // remove all blanks
123        foreach ($value as $val) {
124            if ($israw) {
125                $raw = $val;
126            } else {
127                $raw = $this->column->getType()->rawValue($val);
128            }
129            if ('' === trim((string) $raw)) continue;
130            $this->value[] = $val;
131            $this->rawvalue[] = $raw;
132            if ($israw) {
133                $this->display[] = $val;
134                $this->compare[] = $val;
135            } else {
136                $this->display[] = $this->column->getType()->displayValue($val);
137                $this->compare[] = $this->column->getType()->compareValue($val);
138            }
139        }
140
141        // make single value again
142        if (!$this->column->isMulti()) {
143            $this->value = (string)array_shift($this->value);
144            $this->rawvalue = (string)array_shift($this->rawvalue);
145            $this->display = (string)array_shift($this->display);
146            $this->compare = (string)array_shift($this->compare);
147        }
148    }
149
150    /**
151     * Is this empty?
152     *
153     * @return bool
154     */
155    public function isEmpty()
156    {
157        return ($this->rawvalue === '' || $this->rawvalue === array());
158    }
159
160    /**
161     * Render the value using the given renderer and mode
162     *
163     * automativally picks the right mechanism depending on multi or single value
164     *
165     * values are only rendered when there is a value
166     *
167     * @param \Doku_Renderer $R
168     * @param string $mode
169     * @return bool
170     */
171    public function render(\Doku_Renderer $R, $mode)
172    {
173        if ($this->column->isMulti()) {
174            if (count($this->value)) {
175                return $this->column->getType()->renderMultiValue($this->value, $R, $mode);
176            }
177        } else {
178            if ($this->value !== '') {
179                return $this->column->getType()->renderValue($this->value, $R, $mode);
180            }
181        }
182        return true;
183    }
184
185    /**
186     * Render this value as a tag-link in a struct cloud
187     *
188     * @param \Doku_Renderer $R
189     * @param string $mode
190     * @param string $page
191     * @param string $filterQuery
192     * @param int $weight
193     */
194    public function renderAsTagCloudLink(\Doku_Renderer $R, $mode, $page, $filterQuery, $weight)
195    {
196        $value = is_array($this->value) ? $this->value[0] : $this->value;
197        $this->column->getType()->renderTagCloudLink($value, $R, $mode, $page, $filterQuery, $weight);
198    }
199
200    /**
201     * Return the value editor for this value field
202     *
203     * @param string $name The field name to use in the editor
204     * @return string The HTML for the editor
205     */
206    public function getValueEditor($name, $id)
207    {
208        if ($this->column->isMulti()) {
209            return $this->column->getType()->multiValueEditor($name, $this->rawvalue, $id);
210        } else {
211            return $this->column->getType()->valueEditor($name, $this->rawvalue, $id);
212        }
213    }
214
215    /**
216     * Filter callback to strip empty values
217     *
218     * @param string $input
219     * @return bool
220     */
221    public function filter($input)
222    {
223        return '' !== ((string)$input);
224    }
225}
226