php8
[web.mtrack] / MTrack / Ticket_CustomFields.php
1 <?php # vim:ts=2:sw=2:et:
2
3 require_once  'MTrack/Ticket_CustomField.php';
4 require_once  'MTrack/Interface/IssueListener.php';
5 require_once  'MTrack/Config.php';
6 require_once  'MTrack/DB.php';
7 require_once  'MTrack/Issue.php';
8 require_once  'MTrack/Milestone.php';
9
10
11 class MTrackTicket_CustomFields implements IMTrackIssueListener
12 {
13   var $fields = array();
14
15   var $field_types = array(
16     'text' => 'Text (single line)',
17     'multi' => 'Text (multi-line)',
18     'wiki' => 'Wiki',
19     'shortwiki' => 'Wiki (shorter height)',
20     'select' => 'Select box (choice of one)',
21     // Don't allow multi-select for now; need a sane way to make the value
22     // into an array.
23     //    'multiselect' => 'Multiple select',
24   );
25
26   function save() {
27     $this->alterSchema();
28
29     $fieldlist = join(',', array_keys($this->fields));
30     MTrackConfig::set('ticket', 'customfields', $fieldlist);
31
32     foreach ($this->fields as $field) {
33       $field->save();
34     }
35   }
36
37   function fieldByName($name, $create = false) {
38     $name = MTrackTicket_CustomField::canonName($name);
39     if (!isset($this->fields[$name]) && $create) {
40       $field = new MTrackTicket_CustomField;
41       $field->name = $name;
42       $this->fields[$name] = $field;
43     } else if (!isset($this->fields[$name])) {
44       return null;
45     }
46     return $this->fields[$name];
47   }
48
49   function deleteField($field) {
50     if (!($field instanceof MTrackTicket_CustomField)) {
51       $field = $this->fieldByName($field);
52     }
53     if (!($field instanceof MTrackTicket_CustomField)) {
54       throw new Exception("can't delete an unknown field");
55     }
56     unset($this->fields[$field->name]);
57   }
58
59   function vetoMilestone(MTrackIssue $issue, MTrack_Milestone $ms, $assoc = true) {
60     return true;
61   }
62   function vetoKeyword(MTrackIssue $issue, MTrackKeyword $kw, $assoc = true) {
63     return true;
64   }
65   function vetoComponent(MTrackIssue $issue, MTrackComponent $comp, $assoc = true) {
66     return true;
67   }
68   function vetoProject(MTrackIssue $issue, MTrackProject $proj, $assoc = true) {
69     return true;
70   }
71   function vetoComment(MTrackIssue $issue, $comment) {
72     return true;
73   }
74   function vetoSave(MTrackIssue $issue, $oldFields) {
75     return true;
76   }
77
78   function _orderField($a, $b) {
79     $diff = $a->order - $b->order;
80     if ($diff == 0) {
81       return strnatcasecmp($a->label, $b->label);
82     }
83     return $diff;
84   }
85
86   function getGroupedFields() {
87     $grouped = array();
88     foreach ($this->fields as $field) {
89       $grouped[$field->group][$field->name] = $field;
90     }
91     $result = array();
92     $names = array_keys($grouped);
93     asort($grouped);
94     foreach ($grouped as $name => $group) {
95       uasort($group, array($this, '_orderField'));
96       $result[$name] = $group;
97     }
98     return $result;
99   }
100
101   function augmentFormFields(MTrackIssue $issue, &$fieldset) {
102     $grouped = $this->getGroupedFields();
103     foreach ($grouped as $group) {
104       foreach ($group as $field) {
105         $fieldset[$field->group][$field->name] = $field->ticketData();
106       }
107     }
108   }
109
110   function augmentSaveParams(MTrackIssue $issue, &$params) {
111     foreach ($this->fields as $field) {
112       $params[$field->name] = $issue->{$field->name};
113     }
114   }
115   function augmentIndexerFields(MTrackIssue $issue, &$idx) {
116     foreach ($this->fields as $field) {
117       $idx[$field->name] = $issue->{$field->name};
118     }
119   }
120
121   function applyPOSTData(MTrackIssue $issue, $post) {
122     foreach ($this->fields as $field) {
123       if ($field->type == 'multiselect') {
124         $issue->{$field->name} = join('|', $post[$field->name]);
125       } else {
126         $issue->{$field->name} = $post[$field->name];
127       }
128     }
129   }
130
131   function alterSchema() {
132     $names = array();
133     foreach ($this->fields as $field) {
134       $names[] = $field->name;
135     }
136     $db = MTrackDB::get();
137     try {
138       $db->exec("select " . join(', ', $names) . ' from tickets limit 1');
139     } catch (Exception $e) {
140       foreach ($names as $name) {
141         try {
142           $db->exec("ALTER TABLE tickets add column $name text");
143         } catch (Exception $e) {
144         }
145       }
146     }
147   }
148
149   function __construct() {
150     MTrackIssue::registerListener($this);
151
152     /* read in custom fields from ini */
153     $fieldlist = MTrackConfig::get('ticket', 'customfields');
154     if ($fieldlist) {
155       $fieldlist = preg_split("/\s*,\s*/", $fieldlist);
156       foreach ($fieldlist as $fieldname) {
157         $field = MTrackTicket_CustomField::load($fieldname);
158         $this->fields[$field->name] = $field;
159       }
160     }
161   }
162
163   static $me = null;
164   static function getInstance() {
165     if (self::$me !== null) {
166       return self::$me;
167     }
168     self::$me = new MTrackTicket_CustomFields;
169     return self::$me;
170   }
171 }
172
173 MTrackTicket_CustomFields::getInstance();
174
175