1<?php
2# $Id$
3
4/**
5 * class to handle add and edit in Cli
6 *
7 * extends the "Shell" class
8 */
9class CliEdit extends Shell {
10    public $handler_to_use = "";
11    public $new = 0;
12
13
14    /**
15     * Execution method always used for tasks
16     */
17    public function execute() {
18        if (empty($this->args)) {
19            return $this->__interactive();
20        } else {
21            return $this->__handle_params();
22        }
23    }
24
25    /**
26     * non-interactive mode
27     * read, check and handle all --* parameters
28     * The list of allowed params is based on $handler->struct
29     */
30    private function __handle_params() {
31        $handler = new $this->handler_to_use($this->new);
32        $form_fields = $handler->getStruct();
33        $id_field = $handler->getId_field();
34
35        $values = array();
36        $param_error = 0;
37
38        foreach ($this->params as $key => $val) {
39            $key = preg_replace('/^-/', '', $key); # allow --param, not only -param
40            $key = str_replace('-', '_', $key);    # allow --foo-bar even if field is named foo_bar
41
42            if (isset($form_fields[$key]) && $form_fields[$key]['editable'] && $form_fields[$key]['display_in_form'] && $key != $id_field) {
43                if ($form_fields[$key]['type'] == 'txtl') {
44                    $values[$key] = explode(',', $val);
45                } elseif ($form_fields[$key]['type'] == 'bool') {
46                    if (strtolower($val) == 'y') {
47                        $val = 1;
48                    } # convert y to 1
49                    elseif (strtolower($val) == 'n') {
50                        $val = 0;
51                    } # convert n to 0
52                    $values[$key] = $val; # don't modify any other value - *Handler will complain if it's invalid ;-)
53                } else {
54                    $values[$key] = $val;
55                }
56            } elseif ($key == 'webroot') {
57                # always set, ignore
58            } else { # not editable, unknown field etc.
59                $param_error = 1;
60                $this->err("invalid parameter --$key => $val");
61                return 1;
62            }
63        }
64
65        return $this->__handle($this->args[0], $values);
66    }
67
68    /**
69     * Interactive mode
70     */
71    private function __interactive() {
72        $handler = new $this->handler_to_use($this->new);
73
74        $form_fields = $handler->getStruct();
75        $id_field = $handler->getId_field();
76
77
78        $values = array($id_field => '');
79        while ($form_fields[$id_field]['editable'] != 0) { # endlees loop - except if input is valid or id_field is not editable (like auto_increment)
80            $question = $form_fields[$id_field]['label'] . ":";
81            if ($form_fields[$id_field]['desc'] != '') {
82                $question .= "\n(" . $form_fields[$id_field]['desc'] . ')';
83            }
84
85            $values[$id_field] = $this->in($form_fields[$id_field]['label'] . ':');
86
87            if ($handler->init($values[$id_field])) {
88                break;
89            } else {
90                $this->err($handler->errormsg);
91                # always use a fresh handler to avoid problems with previous error messages
92                $handler = new $this->handler_to_use($this->new);
93            }
94        }
95
96        # update $form_fields (needed for example to display the correct allowed quota)
97        # TODO: doesn't (always?) work - wrong time for the refresh?
98        #        $handler->set(array());
99        $form_fields = $handler->getStruct();
100
101        foreach ($form_fields as $key => $field) {
102            if ($field['editable'] && $field['display_in_form'] && $key != $id_field) {
103                while (true) { # endlees loop - except if input is valid
104                    $question = $field['label'] . ':';
105                    if ($field['desc'] != '') {
106                        $question .= "\n(" . $field['desc'] . ')';
107                    }
108
109                    if ($field['type'] == 'bool') {
110                        $values[$key] = $this->in($question, array('y', 'n'));
111
112                        if ($values[$key] == 'y') {
113                            $values[$key] = 1;
114                        } else {
115                            $values[$key] = 0;
116                        }
117                    } elseif ($field['type'] == 'enum') {
118                        $optiontxt = array();
119                        $optionlist = array();
120
121                        foreach ($field['options'] as $optionkey => $optionval) {
122                            // $this->in hates number 0
123                            $optionkey = $optionkey + 1;
124                            $optiontxt[] = '[' . $optionkey . '] - ' . $optionval;
125                            $optionlist[] = $optionkey;
126                        }
127
128                        $question .= "\n" . join("\n", $optiontxt) . "\n";
129
130                        $selected = (int) $this->in($question, $optionlist);
131
132                        $values[$key] = $field['options'][$selected - 1]; # convert int to option name
133                    } elseif ($field['type'] == 'txtl') {
134                        $values[$key] = array();
135                        $nextval = $this->in($question);
136                        while ($nextval != '') {
137                            if ($nextval != '') {
138                                $values[$key][] = $nextval;
139                            }
140                            $nextval = $this->in("");
141                        }
142                    } else {
143                        $values[$key] = $this->in($question);
144                    }
145
146                    if (is_null($values[$key])) { # TODO: insull() is probably obsoleted by change in Shell class
147                        $this->err("*** value of $key is NULL - this should not happen! ***");
148                        return 1;
149                    }
150
151                    if ($values[$key] == '' && (!$this->new)) { # edit mode
152                        unset($values[$key]); # empty input - don't change
153                    }
154
155                    # always use a fresh handler to avoid problems with previous error messages
156                    $handler = new $this->handler_to_use($this->new);
157                    $handler->init($values[$id_field]);
158
159                    $handler->set($values);
160
161                    if (isset($handler->errormsg[$key])) { # only check the errormessage for this field
162                        $this->err($handler->errormsg[$key]);
163                        return 1;
164                    } else {
165                        break;
166                    }
167                } # end while
168            } # end if $field[editable] etc.
169        } # end foreach
170
171        return $this->__handle($values[$id_field], $values);
172    }
173
174    /**
175     * (try to) store values
176     */
177    private function __handle($id, $values) {
178        $handler = new $this->handler_to_use($this->new);
179        if (!$handler->init($id)) {
180            $this->err($handler->errormsg);
181            return 1;
182        }
183
184        if (!$handler->set($values)) {
185            $this->err($handler->errormsg);
186            return 1;
187        }
188
189        if (!$handler->save()) {
190            $this->err($handler->errormsg);
191            return 1;
192        }
193
194        $this->out("");
195        $this->out($handler->infomsg);
196        $this->hr();
197        return 0;
198    }
199
200    /**
201     * Displays help contents
202     */
203    public function help() {
204        if ($this->new) {
205            $cmd = 'add';
206            $cmdtext = 'Adds';
207        } else {
208            $cmd = 'update';
209            $cmdtext = 'Changes';
210        }
211
212        $module = preg_replace('/Handler$/', '', $this->handler_to_use);
213        $module = strtolower($module);
214
215        $this->out(
216            "Usage:
217
218    postfixadmin-cli $module $cmd
219
220        $cmdtext $module in interactive mode.
221
222- or -
223
224    postfixadmin-cli $module $cmd <address> --option value --option2 value [...]
225
226        $cmdtext $module in non-interactive mode.
227
228        Available options are:
229"
230        );
231
232        $handler = new $this->handler_to_use($this->new);
233
234        $form_fields = $handler->getStruct();
235        $id_field = $handler->getId_field();
236
237        foreach ($form_fields as $key => $field) {
238            if ($field['editable'] && $field['display_in_form'] && $key != $id_field) {
239                $optkey = str_replace('_', '-', $key);
240                $this->out("        --$optkey");
241                $this->out("            " . $field['label']);
242                if ($field['desc']) {
243                    $this->out("            " . $field['desc']);
244                }
245                $this->out("");
246            }
247        }
248
249
250        $this->_stop(1);
251    }
252}
253/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
254