Ongoing refactoring of custom fields for subgroups.
[timetracker.git] / plugins / CustomFields.class.php
1 <?php
2 // +----------------------------------------------------------------------+
3 // | Anuko Time Tracker
4 // +----------------------------------------------------------------------+
5 // | Copyright (c) Anuko International Ltd. (https://www.anuko.com)
6 // +----------------------------------------------------------------------+
7 // | LIBERAL FREEWARE LICENSE: This source code document may be used
8 // | by anyone for any purpose, and freely redistributed alone or in
9 // | combination with other software, provided that the license is obeyed.
10 // |
11 // | There are only two ways to violate the license:
12 // |
13 // | 1. To redistribute this code in source form, with the copyright
14 // |    notice or license removed or altered. (Distributing in compiled
15 // |    forms without embedded copyright notices is permitted).
16 // |
17 // | 2. To redistribute modified versions of this code in *any* form
18 // |    that bears insufficient indications that the modifications are
19 // |    not the work of the original author(s).
20 // |
21 // | This license applies to this document only, not any other software
22 // | that it may be combined with.
23 // |
24 // +----------------------------------------------------------------------+
25 // | Contributors:
26 // | https://www.anuko.com/time_tracker/credits.htm
27 // +----------------------------------------------------------------------+
28
29 class CustomFields {
30
31   // Definitions of custom field types.
32
33   const TYPE_TEXT = 1;     // A text field.
34   const TYPE_DROPDOWN = 2; // A dropdown field with pre-defined values.
35
36   var $fields = array();  // Array of custom fields for group.
37   var $options = array(); // Array of options for a dropdown custom field.
38
39   // Constructor.
40   function __construct($group_id) {
41     $mdb2 = getConnection();
42
43     // Get fields.
44     $sql = "select id, type, label, required from tt_custom_fields where group_id = $group_id and status = 1 and type > 0";
45     $res = $mdb2->query($sql);
46     if (!is_a($res, 'PEAR_Error')) {
47       while ($val = $res->fetchRow()) {
48         $this->fields[] = array('id'=>$val['id'],'type'=>$val['type'],'label'=>$val['label'],'required'=>$val['required'],'value'=>'');
49       }
50     }
51
52     // If we have a dropdown obtain options for it.
53     if ((count($this->fields) > 0) && ($this->fields[0]['type'] == CustomFields::TYPE_DROPDOWN)) {
54
55       $sql = "select id, value from tt_custom_field_options where field_id = ".$this->fields[0]['id']." and status = 1 order by value";
56       $res = $mdb2->query($sql);
57       if (!is_a($res, 'PEAR_Error')) {
58         while ($val = $res->fetchRow()) {
59           $this->options[$val['id']] = $val['value'];
60         }
61       }
62     }
63   }
64
65   function insert($log_id, $field_id, $option_id, $value) {
66     global $user;
67     $mdb2 = getConnection();
68
69     $group_id = $user->getGroup();
70     $org_id = $user->org_id;
71
72     $sql = "insert into tt_custom_field_log (group_id, org_id, log_id, field_id, option_id, value)".
73       " values($group_id, $org_id, $log_id, $field_id, ".$mdb2->quote($option_id).", ".$mdb2->quote($value).")";
74     $affected = $mdb2->exec($sql);
75     return (!is_a($affected, 'PEAR_Error'));
76   }
77
78   function update($log_id, $field_id, $option_id, $value) {
79     if (!$field_id)
80       return true; // Nothing to update.
81
82     // Remove older custom field values, if any.
83     $res = $this->delete($log_id);
84     if (!$res)
85       return false;
86
87     if (!$value && !$option_id)
88       return true; // Do not insert NULL values.
89
90     return $this->insert($log_id, $field_id, $option_id, $value);
91   }
92
93   function delete($log_id) {
94     global $user;
95     $mdb2 = getConnection();
96
97     $group_id = $user->getGroup();
98     $org_id = $user->org_id;
99
100     $sql = "update tt_custom_field_log set status = null".
101       " where log_id = $log_id and group_id = $group_id and org_id = $org_id";
102     $affected = $mdb2->exec($sql);
103     return (!is_a($affected, 'PEAR_Error'));
104   }
105
106   function get($log_id) {
107     global $user;
108     $mdb2 = getConnection();
109
110     $group_id = $user->getGroup();
111     $org_id = $user->org_id;
112
113     $sql = "select id, field_id, option_id, value from tt_custom_field_log".
114       " where log_id = $log_id and group_id = $group_id and org_id = $org_id and status = 1";
115     $res = $mdb2->query($sql);
116     if (!is_a($res, 'PEAR_Error')) {
117       $fields = array();
118       while ($val = $res->fetchRow()) {
119         $fields[] = $val;
120       }
121       return $fields;
122     }
123     return false;
124   }
125
126   // insertOption adds a new option to a custom field.
127   static function insertOption($field_id, $option_name) {
128     global $user;
129     $mdb2 = getConnection();
130
131     $group_id = $user->getGroup();
132     $org_id = $user->org_id;
133
134     // Check if the option exists.
135     $id = 0;
136     $sql = "select id from tt_custom_field_options".
137       " where field_id = $field_id and group_id = $group_id and org_id = $org_id and value = ".$mdb2->quote($option_name);
138     $res = $mdb2->query($sql);
139     if (is_a($res, 'PEAR_Error'))
140       return false;
141     if ($val = $res->fetchRow()) $id = $val['id'];
142
143     // Insert option.
144     if (!$id) {
145       $sql = "insert into tt_custom_field_options (group_id, org_id, field_id, value)".
146         " values($group_id, $org_id, $field_id, ".$mdb2->quote($option_name).")";
147       $affected = $mdb2->exec($sql);
148       if (is_a($affected, 'PEAR_Error'))
149         return false;
150     }
151     return true;
152   }
153
154   // updateOption updates option name.
155   static function updateOption($id, $option_name) {
156     global $user;
157     $mdb2 = getConnection();
158
159     $group_id = $user->getGroup();
160     $org_id = $user->org_id;
161
162     $sql = "update tt_custom_field_options set value = ".$mdb2->quote($option_name).
163        " where id = $id and group_id = $group_id and org_id = $org_id";
164     $affected = $mdb2->exec($sql);
165     return (!is_a($affected, 'PEAR_Error'));
166   }
167
168   // delete Option deletes an option and all custom field log entries that used it.
169   static function deleteOption($id) {
170     global $user;
171     $mdb2 = getConnection();
172
173     $group_id = $user->getGroup();
174     $org_id = $user->org_id;
175
176     $field_id = CustomFields::getFieldIdForOption($id);
177     if (!$field_id) return false;
178
179     // Delete log entries with this option. TODO: why? Research impact.
180     $sql = "update tt_custom_field_log set status = null".
181       " where field_id = $field_id and group_id = $group_id and org_id = $org_id and value = ".$mdb2->quote($id);
182     $affected = $mdb2->exec($sql);
183     if (is_a($affected, 'PEAR_Error'))
184       return false;
185
186     // Delete the option.
187     $sql = "update tt_custom_field_options set status = null".
188       " where id = $id and group_id = $group_id and org_id = $org_id";
189     $affected = $mdb2->exec($sql);
190     return (!is_a($affected, 'PEAR_Error'));
191   }
192
193   // getOptions returns an array of options for a custom field.
194   static function getOptions($field_id) {
195     global $user;
196     $mdb2 = getConnection();
197
198     $group_id = $user->getGroup();
199     $org_id = $user->org_id;
200
201     // Get options.
202     $sql = "select id, value from tt_custom_field_options".
203       " where field_id = $field_id and group_id = $group_id and org_id = $org_id and status = 1 order by value";
204     $res = $mdb2->query($sql);
205     if (!is_a($res, 'PEAR_Error')) {
206       $options = array();
207       while ($val = $res->fetchRow()) {
208         $options[$val['id']] = $val['value'];
209       }
210       return $options;
211     }
212     return false;
213   }
214
215   // getOptionName returns an option name for a custom field.
216   static function getOptionName($id) {
217     global $user;
218     $mdb2 = getConnection();
219
220     $group_id = $user->getGroup();
221     $org_id = $user->org_id;
222
223     $sql = "select value from tt_custom_field_options".
224       " where id = $id and group_id = $group_id and org_id = $org_id";
225     $res = $mdb2->query($sql);
226     if (!is_a($res, 'PEAR_Error')) {
227       $val = $res->fetchRow();
228       $name = $val['value'];
229       return $name;
230     }
231     return false;
232   }
233
234   // getFields returns an array of custom fields for group.
235   static function getFields() {
236     global $user;
237     $mdb2 = getConnection();
238
239     $group_id = $user->getGroup();
240     $org_id = $user->org_id;
241
242     $fields = array();
243     $sql = "select id, type, label from tt_custom_fields".
244       " where group_id = $group_id and org_id = $org_id and status = 1 and type > 0";
245     $res = $mdb2->query($sql);
246     if (!is_a($res, 'PEAR_Error')) {
247       while ($val = $res->fetchRow()) {
248         $fields[] = array('id'=>$val['id'],'type'=>$val['type'],'label'=>$val['label']);
249       }
250       return $fields;
251     }
252     return false;
253   }
254
255   // getField returns a custom field.
256   static function getField($id) {
257     global $user;
258     $mdb2 = getConnection();
259
260     $group_id = $user->getGroup();
261     $org_id = $user->org_id;
262
263     $sql = "select label, type, required from tt_custom_fields".
264       " where id = $id and group_id = $group_id and org_id = $org_id";
265     $res = $mdb2->query($sql);
266     if (!is_a($res, 'PEAR_Error')) {
267       $val = $res->fetchRow();
268       if (!$val)
269         return false;
270       return $val;
271     }
272     return false;
273   }
274
275   // getFieldIdForOption returns field id from an associated option id.
276   static function getFieldIdForOption($option_id) {
277     global $user;
278     $mdb2 = getConnection();
279
280     $group_id = $user->getGroup();
281     $org_id = $user->org_id;
282
283     $sql = "select field_id from tt_custom_field_options".
284       " where id = $option_id and group_id = $group_id and org_id = $org_id";
285     $res = $mdb2->query($sql);
286     if (!is_a($res, 'PEAR_Error')) {
287       $val = $res->fetchRow();
288       $field_id = $val['field_id'];
289       return $field_id;
290     }
291     return false;
292   }
293
294   // The insertField inserts a custom field for group.
295   static function insertField($field_name, $field_type, $required) {
296     global $user;
297     $mdb2 = getConnection();
298
299     $group_id = $user->getGroup();
300     $org_id = $user->org_id;
301
302     $sql = "insert into tt_custom_fields (group_id, org_id, type, label, required, status)".
303       " values($group_id, $org_id, $field_type, ".$mdb2->quote($field_name).", $required, 1)";
304     $affected = $mdb2->exec($sql);
305     return (!is_a($affected, 'PEAR_Error'));
306   }
307
308   // The updateField updates custom field for group.
309   static function updateField($id, $name, $type, $required) {
310     global $user;
311     $mdb2 = getConnection();
312
313     $group_id = $user->getGroup();
314     $org_id = $user->org_id;
315
316     $sql = "update tt_custom_fields set label = ".$mdb2->quote($name).", type = $type, required = $required".
317       " where id = $id and group_id = $group_id and org_id = $org_id";
318     $affected = $mdb2->exec($sql);
319     return (!is_a($affected, 'PEAR_Error'));
320   }
321
322   // The deleteField deletes a custom field, its options and log entries for group.
323   static function deleteField($field_id) {
324     global $user;
325     $mdb2 = getConnection();
326
327     $group_id = $user->getGroup();
328     $org_id = $user->org_id;
329
330     // Mark log entries as deleted. TODO: why are we doing this? Research impact.
331     $sql = "update tt_custom_field_log set status = null".
332       " where field_id = $field_id and group_id = $group_id and org_id = $org_id";
333     $affected = $mdb2->exec($sql);
334     if (is_a($affected, 'PEAR_Error'))
335       return false;
336
337     // Mark field options as deleted.
338     $sql = "update tt_custom_field_options set status = null".
339       " where field_id = $field_id and group_id = $group_id and org_id = $org_id";
340     $affected = $mdb2->exec($sql);
341     if (is_a($affected, 'PEAR_Error'))
342       return false;
343
344     // Mark custom field as deleted.
345     $sql = "update tt_custom_fields set status = null".
346       " where id = $field_id and group_id = $group_id and org_id = $org_id";
347     $affected = $mdb2->exec($sql);
348     return (!is_a($affected, 'PEAR_Error'));
349   }
350 }