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;
22
23    /** @var array|int|string */
24    protected $display;
25
26    /** @var array|int|string */
27    protected $compare;
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 = [$value];
114        }
115
116        // reset/init
117        $this->value = [];
118        $this->rawvalue = [];
119        $this->display = [];
120        $this->compare = [];
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 === []);
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        } elseif ($this->value !== '') {
178            return $this->column->getType()->renderValue($this->value, $R, $mode);
179        }
180        return true;
181    }
182
183    /**
184     * Render this value as a tag-link in a struct cloud
185     *
186     * @param \Doku_Renderer $R
187     * @param string $mode
188     * @param string $page
189     * @param string $filterQuery
190     * @param int $weight
191     * @param int $showCount
192     */
193    public function renderAsTagCloudLink(\Doku_Renderer $R, $mode, $page, $filterQuery, $weight, $showCount)
194    {
195        $value = is_array($this->value) ? $this->value[0] : $this->value;
196        $this->column->getType()->renderTagCloudLink($value, $R, $mode, $page, $filterQuery, $weight, $showCount);
197    }
198
199    /**
200     * Return the value editor for this value field
201     *
202     * @param string $name The field name to use in the editor
203     * @return string The HTML for the editor
204     */
205    public function getValueEditor($name, $id)
206    {
207        if ($this->column->isMulti()) {
208            return $this->column->getType()->multiValueEditor($name, $this->rawvalue, $id);
209        } else {
210            return $this->column->getType()->valueEditor($name, $this->rawvalue, $id);
211        }
212    }
213
214    /**
215     * Filter callback to strip empty values
216     *
217     * @param string $input
218     * @return bool
219     */
220    public function filter($input)
221    {
222        return '' !== ((string)$input);
223    }
224
225    /**
226     * Get a string representation of this value
227     *
228     * @return string
229     */
230    public function __toString()
231    {
232        return '[' . $this->getColumn()->getFullQualifiedLabel() . '] ' .
233            implode(',', (array)$this->getRawValue());
234    }
235}
236