1<?php
2namespace dokuwiki\plugin\structcombolookup\types;
3
4use dokuwiki\plugin\struct\meta\Column;
5use dokuwiki\plugin\struct\meta\Search;
6use dokuwiki\plugin\struct\meta\Value;
7use dokuwiki\plugin\struct\types\Lookup;
8
9class NarrowingLookup extends Lookup
10{
11    protected $config = array(
12        'schema' => '',
13        'field' => '',
14        'narrow by' => '',
15        'disable child' => true
16    );
17
18    /** @var  Column caches the referenced column */
19    protected $narrowByColumn = null;
20
21    /**
22     * Get the configured lookup column
23     *
24     * @return Column|false
25     */
26    protected function getNarrowByColumn() {
27        if($this->narrowByColumn !== null) return $this->narrowByColumn;
28        $this->narrowByColumn = $this->getColumn($this->config['schema'], $this->config['narrow by']);
29        return $this->narrowByColumn;
30    }
31
32
33    /**
34     * Creates the options array
35     *
36     * @return array
37     */
38    protected function getNarrowByOptions() {
39        $schema = $this->config['schema'];
40        $column = $this->getNarrowByColumn();
41        if(!$column) return array();
42        $field = $column->getLabel();
43
44        $search = new Search();
45        $search->addSchema($schema);
46        $search->addColumn($field);
47        $search->addSort($field);
48
49        $options = array('' => '');
50        $results = $search->execute();
51        foreach ($results as $result) {
52            $options[$result[0]->getRawValue()] = $result[0]->getDisplayValue();
53        }
54        return $options;
55    }
56
57    protected function getRawValueNarrowingValue($rawvalue) {
58        $schema = $this->config['schema'];
59        $column = $this->getNarrowByColumn();
60        if(!$column) return '';
61        $field = $column->getLabel();
62
63        $search = new Search();
64        $search->addSchema($schema);
65        $search->addColumn($field);
66        $search->addFilter($this->config['field'], $rawvalue, '=');
67        $result = $search->execute();
68        if (!isset($result[0])) return '';
69        return $result[0][0]->getRawValue();
70    }
71
72    /**
73     * Creates the options array
74     *
75     * @return array
76     */
77    protected function getOptions() {
78        $schema = $this->config['schema'];
79        $column = $this->getLookupColumn();
80        if(!$column) return array();
81        $field = $column->getLabel();
82
83        $narrowingColumn = $this->getNarrowByColumn();
84        if(!$narrowingColumn) return array();
85        $narrowingField = $narrowingColumn->getLabel();
86
87
88
89        $search = new Search();
90        $search->addSchema($schema);
91        $search->addColumn($field);
92        $search->addColumn($narrowingField);
93
94        $search->addSort($field);
95        $result = $search->execute();
96        $pids = $search->getPids();
97        $len = count($result);
98
99        /** @var Value[][] $result */
100        $options = array('' => array('', ''));
101        for($i = 0; $i < $len; $i++) {
102            $options[$pids[$i]] = array($result[$i][0]->getDisplayValue(), $result[$i][1]->getRawValue());
103        }
104        return $options;
105    }
106
107
108    protected function parentValueEditor($name, $rawvalue, $htmlID) {
109        $params = array(
110            'data-child-id' => $htmlID,
111            'class' => 'struct_'.strtolower($this->getClass()). '_parent',
112            'onchange' => 'structcombolookup_change_narrowby(this, '.(int)$this->config['disable child'].')'
113        );
114        $attributes = buildAttributes($params, true);
115        $html = "<select $attributes>";
116        foreach($this->getNarrowByOptions() as $opt => $val) {
117            if($opt == $this->getRawValueNarrowingValue($rawvalue)) {
118                $selected = 'selected="selected"';
119            } else {
120                $selected = '';
121            }
122
123            $html .= "<option $selected value=\"" . hsc($opt) . "\">" . hsc($val) . '</option>';
124        }
125        $html .= '</select>';
126
127        return $html;
128    }
129
130    /**
131     * A Dropdown with a single value to pick
132     *
133     * @param string $name
134     * @param string $rawvalue
135     * @return string
136     */
137    public function valueEditor($name, $rawvalue, $htmlID) {
138        $html = $this->parentValueEditor($name, $rawvalue, $htmlID);
139
140        $params = array(
141            'name' => $name,
142            'class' => 'struct_'.strtolower($this->getClass()) . '_child',
143            'id' => $htmlID
144        );
145        if ($this->config['disable child']) {
146            $params['disabled'] = 'disabled';
147        }
148        $attributes = buildAttributes($params, true);
149        $html .= "<select $attributes>";
150        foreach($this->getOptions() as $opt => $option) {
151            list($val, $parent) = $option;
152            if($opt == $rawvalue) {
153                $selected = 'selected="selected"';
154            } else {
155                $selected = '';
156            }
157
158            $html .= "<option data-parent=\"" . hsc($parent) . "\" $selected value=\"" . hsc($opt) . "\">" . hsc($val) . '</option>';
159        }
160        $html .= '</select>';
161
162        return $html;
163    }
164}