Framework  3.9
option_cross_reference_field_renderer.inc
Go to the documentation of this file.
1 <?php
22 {
23  var $options = array();
24  var $cssClass = "options_list";
25  var $separator = ", ";
28  var $onStartOption = null;
29  var $grouped = false;
30  var $groupTag = "h4";
31  var $containerClass = "";
32 
33  function OptionCrossReferenceFieldRenderer(&$form, $field, $label, $options, $nameField, $xrefClass, $grouped = false)
34  {
35  $this->options = $options;
36  $this->nameField = $nameField;
37  $this->xrefClass = $xrefClass;
38  $this->grouped = $grouped;
39 
40  $this->FieldRenderer($form);
41  if ($form->data->hasField($field))
42  {
43  $form->override($field, $label, $this);
44  }
45  else
46  {
47  $form->add($this, $field);
48  if ($label) $form->alias($field, $label);
49  }
50  }
51 
52 
53  function groupBy($groupBy, $format = "")
54  {
55  $this->groupBy = $groupBy;
56  $this->groupByFormat = $format;
57  }
58 
59  function renderScript($field)
60  {
61  if ($this->parent->readOnlyForm || $this->parent->isReadOnly($field)) return;
62  $id = "{$this->parent->id}_{$field}";
63  ?>
64  <script type='text/javascript'>
65  function <?echo $id?>_update(sel)
66  {
67  if (sel.hasClass("selected"))
68  {
69  sel.removeClass("selected");
70  }
71  else
72  {
73  sel.addClass("selected");
74  }
75 
76  var values = [];
77 
78  $$('.<?echo $id?>_list > li').each(function(elt)
79  {
80  if (elt.hasClass('selected'))
81  {
82  var v = elt.get('data-value');
83  values.push(v);
84  }
85  });
86 
87  var hidden = document.id('<?echo $id?>');
88  var v = hidden.value;
89  hidden.value = values.join(",");
90  var f = document.id('<?echo $this->parent->id?>');
91  if (v != hidden.value && f && f.manager)
92  {
93  f.manager.dirty();
94  }
95  }
96  </script>
97 <?
98  }
99 
100  function renderField($field)
101  {
102  $this->_startField($field);
103 
104  trace("# of Options: ".count($this->options), 3);
105 
106  if (count($this->options))
107  {
108  if ($this->containerClass) { echo "<div class='{$this->containerClass}'>\n"; }
109 
110  $obj = $this->parent->data;
111 
112  if (is_array($this->groupBy) && count($this->groupBy) > 0)
113  {
114  $keys = array_keys($this->options);
115  $rc = $this->options[$keys[0]][0];
116  }
117  else if ($this->grouped)
118  {
119  $keys = array_keys($this->options);
120  $rc = $this->options[$keys[0]][0];
121  }
122  else
123  {
124  $rc = $this->options[0];
125  }
126  $pk = $obj->getPrimaryKey();
127 
128  if (!$rc)
129  {
130  $this->_endField($field);
131  return;
132  }
133 
134  $selectedItems = $this->getSelected($obj, $rc, $pk);
135 
136 
137  $value = implode(",", array_keys($selectedItems));
138 
139  $id = "{$this->parent->id}_{$field}";
140 
141  echo "<input type='hidden' id='{$id}' name='{$field}' value='{$value}'/>";
142 
143  if (is_array($this->groupBy) && count($this->groupBy) > 0)
144  {
145  $gpk = $this->groupBy[0]->getPrimaryKey();
146 
147  foreach($this->groupBy as $group)
148  {
149  if (array_key_exists($group->get($gpk), $this->options))
150  {
151  echo $group->format($this->groupByFormat);
152  $this->renderOptions($field, $this->options[$group->get($gpk)], $selectedItems);
153  }
154  }
155  }
156  else if (is_string($this->groupBy))
157  {
158  trace("Rendering grouped by", 3);
159  $options = regroupList($this->options, $this->groupBy);
160 
161  foreach($options as $group => $choices)
162  {
163  echo "<{$this->groupTag}>$group</{$this->groupTag}>";
164  $this->renderOptions($field, $choices, $selectedItems);
165  }
166  }
167  else if ($this->grouped)
168  {
169  trace("Rendering grouped", 3);
170  foreach($this->options as $group => $choices)
171  {
172  echo "<{$this->groupTag}>$group</{$this->groupTag}>";
173  $this->renderOptions($field, $choices, $selectedItems);
174  }
175  }
176  else
177  {
178  trace("Rendering simple", 3);
179  $this->renderOptions($field, $this->options, $selectedItems);
180  }
181 
182  if ($this->containerClass) { echo "</div>\n"; }
183  }
184  $this->_endField($field);
185  }
186 
187  function renderOptions($field, $options, $selectedItems)
188  {
189  $id = "{$this->parent->id}_{$field}";
190 
191  echo "<ul class='{$id}_list {$this->cssClass}'>";
192  foreach($options as $option)
193  {
194  $val = $option->get($option->getPrimaryKey());
195  $classes = array();
196  if (array_key_exists($val, $selectedItems)) $classes[] = "selected";
197 
198  if ($this->onStartOption)
199  {
200  $flag = call_user_func($this->onStartOption, $option);
201  if ($flag === false) continue;
202  if ($flag) $classes[] = $flag;
203  }
204 
205  $classes = implode(" ", $classes);
206 
207  $description = $this->formatName($option, $this->nameField);
208  echo "<li class='{$classes}' data-value='{$val}' onclick='{$id}_update(this); return false;'>{$description}</li>\n";
209  }
210  echo "</ul>";
211  }
212 
213  function renderReadOnly($field)
214  {
215  $this->_startField($field);
216 
217  if (count($this->options))
218  {
219 
220  $obj = $this->parent->data;
221 
222  $rc = $this->options[0];
223  $pk = $obj->getPrimaryKey();
224 
225  $selectedItems = $this->getSelected($obj, $rc, $pk);
226 
227  $selected = array();
228  foreach($this->options as $option)
229  {
230  $val = $option->get($option->getPrimaryKey());
231  if (array_key_exists($val, $selectedItems)) $selected[] = $option;
232  }
233 
234  echo formatItems($selected, "{".$this->nameField."}", $this->separator);
235  }
236 
237  $this->_endField($field);
238  }
239 
240  function getSelected($obj, $rc, $pk)
241  {
242  return ($obj->get($pk) != "") ? indexedQuery($this->xrefClass, "WHERE {$pk}={$obj->get($pk)}", $rc->getPrimaryKey()) : array();
243  }
244 
245  function getMatchingPK($xref, $obj)
246  {
247  $pks = $obj->getPrimaryKeyList();
248  foreach($pks as $pk)
249  {
250  if ($xref->hasField($pk)) return $pk;
251  }
252 
253  throw new DataItemException("No matching foreign key in xref table");
254  }
255 
256  function postProcess($field = "")
257  {
258  if (count($this->options) == 0) return;
259 
260  $xref = new $this->xrefClass;
261 
262  $obj = $this->parent->data;
263  $pk = $this->getMatchingPK($xref, $obj);
264 
265  if (is_array($this->groupBy) && count($this->groupBy) > 0)
266  {
267  $keys = array_keys($this->options);
268  $rc = $this->options[$keys[0]][0];
269  }
270  else
271  {
272  $rc = $this->options[0];
273  }
274 
275  $optpk = $this->getMatchingPK($xref, $rc);
276 
277  $tx = new DataTransaction();
278  try
279  {
280  $this->clearOutRelations($obj, $pk, $tx);
281 
282  if (isset($_POST[$field]))
283  {
284  $ids = explode(",", $_POST[$field]);
285 
286  foreach($ids as $id)
287  {
288  $xref = new $this->xrefClass;
289  $xref->joinTransaction($tx);
290  $xref->set($pk, $obj->get($pk));
291  $xref->set($optpk, $id);
292  $xref->save();
293  }
294  }
295 
296  $tx->commit();
297  }
298  catch (Exception $e)
299  {
300  $tx->rollback();
301  throw $e;
302  }
303  }
304 
311  function clearOutRelations($obj, $pk, $tx)
312  {
313  $xref = new $this->xrefClass;
314  $xref->joinTransaction($tx);
315  $xref->delete("WHERE {$pk}=".$obj->get($pk));
316  }
317 }
318 
The DataTransaction class wraps the underlying database's transaction model.
Definition: transaction.inc:48
FieldRenderer is the abstract base class for all FieldRenderers.
_startField($field, $styles="")
Internal method to generate the starting HTML for the field (including the label)
formatName($item, $name)
Formats the given DataItem based on the supplied format string.
_endField($field)
Internal method to generate the closing HTML for the field.
FieldRenderer($parent)
Constructor.
Displays a control that provides a highly styleable set of options from which the user can select a n...
postProcess($field="")
FieldRenderers can override this method to provide behavior that occurs after the parent form's targe...
OptionCrossReferenceFieldRenderer(&$form, $field, $label, $options, $nameField, $xrefClass, $grouped=false)
renderField($field)
FieldRenderers must override this method to provide the HTML implementation of the control used to ed...
clearOutRelations($obj, $pk, $tx)
Clear out the current relations stored in the xref class.
renderScript($field)
FieldRenderers can override this method to provide any Javascript that their control requires for an ...
trace($msg, $lvl=3, $callStack=null)
Send output to the trace log.
Definition: functions.inc:1010
regroupList($list, $field)
Regroup an indexed or grouped query result by a different field.
Definition: data_item.inc:1948
indexedQuery($class)
Performs a query against the database, returning an array of DataItem objects of the specified class,...
formatItems($items, $template, $separator="")
Format a list of DataItems using the specified templated.
Definition: data_item.inc:2176