Added a single param to getColumn()
[AOOS.git] / AOOSModel.php
blob4e35073c7d2e4531a464284508380417dcbc0dbe
1 <?php
2 require_once("AOOSException.php");
3 require_once("AOOSModule.php");
5 /**
6 * AOOSModel
7 * A table-like model for containing data
8 * @author Sebastian Skejø
9 */
11 class AOOSModel extends AOOSModule
13 private $_rows = 0;
14 private $_data = array();
15 private $_model = array();
16 private $_updated = false;
17 private $_columnIndex = array();
18 private $_escape = true;
19 private $_quote = false;
20 private $_equal = "{'}";
21 private $_seperator = "]'[";
23 public function __toString() {
24 $string = nl2br(str_replace(" ", "&nbsp;", print_r($this->data(), true)));
25 /* foreach ($this->data() as $row) {
26 $string .= print_r($row, true);
27 $string .= "<br />";
30 return $string;
33 private function _fixRange(&$start, &$end, $count)
35 if ($start === null) { $start = 0; }
36 if ($end === null) { $end = $count-1; }
38 if (!is_int($start) || !is_int($end))
40 throw new AOOSException($this->core(), $this->tr("not_int"), "", true, 1);
41 return false;
44 if ($start >= $count || $end >= $count)
46 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 1);
47 return false;
50 if ($start > $end && !($end < 0))
52 throw new AOOSException($this->core(), $this->tr("start_bigger_than_end"), "", true, 1);
53 return false;
56 // If start is > 0 we count from the end
57 if ($start < 0)
59 $start = $count + $start;
61 // Same goes for end
62 if ($end < 0)
64 $end = $count + $end;
67 return true;
70 /**
71 * Adds a row before $row.
72 * @param int $row The row which the new row should be inserted before. If given -1 it will be inserted at the end of the model.
73 * @return bool
75 public function addRow($row = -1)
77 if ($row > count($this->_data) || $row < -1)
79 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 1);
80 return false;
83 if ($row == -1 || count($this->_data) == 0)
85 $this->_data[] = null;
87 else
89 $tmp = $this->_data;
90 $this->_data[$row] = null;
92 $count = count($this->_data);
93 while ($row < $count)
95 $val = $tmp[$row];
96 $row++;
97 $this->_data[$row] = $val;
100 $this->_updated = false;
101 $this->_rows++;
102 return true;
106 * Removes a row from the model.
107 * @param int $row The row to remove. Given -1 the last row is removed.
108 * @return bol
110 public function removeRow($row = -1)
112 if ($row < -1 || $row >= count($this->_data))
114 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 2);
115 return false;
118 if ($row == -1)
120 $row = count($this->_data) - 1;
122 $tmp = $this->_data;
123 $this->_data = array();
125 // Reinsert rows before $row
126 for ($i = 0; $i < $row; $i++)
128 $this->_data[] = $tmp[$i];
131 $row++;
133 // Reinsert rows after $row
134 for ($c = count($tmp); $row < $c; $row++)
136 $this->_data[] = $tmp[$row];
139 $this->_updated = false;
140 $this->_rows--;
141 return true;
145 * Sets the data of a specified row and column.
146 * @param int $row The row in which the column is selected from
147 * @param int|string $col The column in which the data should be added
148 * @param $data The data that should be added.
149 * @return bool
151 public function setData($data, $row = -1, $col = -1)
153 if ($row >= count($this->_data))
155 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 1);
156 return false;
158 if ($row == -1)
160 $row = $this->rows() -1;
163 if (is_string($col))
165 $i = 0;
166 foreach ($this->_columnIndex as $index)
168 if ($index == $col)
170 $col = $i;
171 break;
173 $i++;
176 if ($col >= count($this->_data[$row]) || $col == -1)
178 $col = count($this->_data[$row]);
181 $this->_data[$row][$col] = $data;
182 $this->_updated = false;
183 return true;
187 * Sets column index
188 * @param int $col Column
189 * @param string $index Column index
190 * @return bool
192 public function setColumnIndex()
194 $count = func_num_args();
195 $arg1 = func_get_arg(0);
196 switch ($count)
198 case (2):
199 $arg2 = func_get_arg(1);
200 $this->_setColumnIndexSingle($arg1, $arg2);
201 break;
202 case(1):
203 $this->_setColumnIndexArray($arg1);
204 break;
206 $this->_updated = false;
209 private function _setColumnIndexSingle($col, $index)
211 if (!is_int($col))
213 throw new AOOSException($this->core(), $this->tr("not_integer"), "", true, 1);
214 return false;
216 if (!is_string($index))
218 throw new AOOSException($this->core(), $this->tr("not_string"), "", true, 1);
219 return false;
221 $this->_columnIndex[$col] = $index;
224 private function _setColumnIndexArray($index)
226 if (!is_array($index))
228 throw new AOOSException($this->core(), $this->tr("not_array"), "", true, 1);
229 return false;
232 $c = 0;
233 foreach ($index as $i)
235 $this->_columnIndex[$c] = $i;
236 $c++;
241 * Returns everything in the model
242 * @return data|false
244 public function data()
246 $data = array();
247 $rowIndex = 0;
249 if ($this->_updated) // If the model is updated we don't need to iterate through the data
251 return $this->_model;
254 foreach ($this->_data as $row)
256 $index = 0;
257 foreach ($this->_columnIndex as $colIndex)
259 if ($index >= count($row))
261 $row[$index] = "";
264 $col = $row[$index];
265 if ($this->escape())
267 $col = mysql_real_escape_string($col);
270 if ($this->quote())
272 $col = "\"".$col."\"";
275 $data[$rowIndex][$colIndex] = $col;
276 $index++;
278 $rowIndex++;
280 $this->_updated = true;
281 $this->_model = $data;
282 return $this->_model;
286 * Returns a given column
287 * @param string $index The column index
288 * @param bool $single If set to true, a string with the first value in the column is returned instead of an array
289 * @param int $start "From row"
290 * @param int $end "To row". Inclusive.
291 * @return array|string
293 public function getColumn($index, $single = false, $start = null, $end = null)
295 $data = $this->data();
296 $count = count($data);
297 $column = array();
299 if (!in_array($index, $this->_columnIndex))
301 throw new AOOSException($this->core(), $this->tr("not_in_column_index"), "", true, 1);
302 return false;
305 $this->_fixRange($start, $end, $count);
307 for ($i = $start; $i <= $end; $i++)
309 $column[] = $data[$i][$index];
312 if ($single) {
313 $column = array_pop($column);
316 return $column;
319 public function getColumns($fields, $start = null, $end = null)
321 $cols = array();
322 foreach ($fields as $index)
324 $cols[] = $this->getColumn($index, $start, $end);
326 return $cols;
330 * Returns rows
331 * @param int $start "From row"
332 * @param int $end "To row". Inclusive.
333 * @param int $cutoff If set to true the $end row will be adjusted to fit within the number of rows if the given $end is bigger.
334 * @return array
336 public function getRows($start = null, $end = null, $cutoff = false)
338 $data = $this->data();
339 $count = count($data);
340 $rows = array();
342 if ($this->rows() == 0)
344 throw new AOOSException($this->core(), $this->tr("model_empty"), "", true, 2);
345 return false;
348 if ($cutoff && $end > $this->rows())
350 $end = $this->rows();
353 $this->_fixRange($start, $end, $count);
355 for ($i = $start; $i <= $end; $i++)
357 $rows[] = $data[$i];
360 return $rows;
364 * Returns a single row
365 * @param int $id Row id
366 * @return array
368 public function getRow($id)
370 $tmp = $this->getRows($id, $id);
371 return $tmp[0];
376 * Returns the column index
377 * @return array
379 public function columnIndex()
381 return $this->_columnIndex;
385 * Returns the row count
386 * @return int
388 public function rows()
390 return $this->_rows;
394 * Returns the column count
395 * @return int
397 public function columns()
399 return count($this->_columnIndex);
403 * Is the given value in the given column?
404 * @param string $col Column id
405 * @param value $val Value
406 * @return bool
408 public function inColumn($col, $val)
410 $c = $this->getColumn($col);
411 if (!in_array($val, $c))
413 return false;
415 return true;
419 * Is the given value a column index?
420 * @param string $name
421 * @return bool
423 public function inColumnIndex($name)
425 if (!in_array($name, $this->columnIndex()))
427 return false;
429 return true;
433 * Appends given values to the end of the model. The number of keys is the number of values added.
434 * @param array $values Values to append.
435 * @param auto|null $key If "auto" is given the column ids we be determined automatically. If not the function expects the array to be a hash which keys is used as column indexes(default).
436 * @return bool
438 public function append($values, $key = null)
440 $keys = array();
441 $c = 0;
443 if (!is_array($values))
445 throw new AOOSException($this->core(), $this->tr("not_array"));
446 return false;
449 if ($key == "auto")
451 $keys = $this->columnIndex();
453 else
455 $keys = array_keys($values);
456 $values = array_values($values);
459 $this->addRow();
460 $c = count($keys);
461 for ($i=0; $i<$c; $i++)
463 $this->setData($values[$i], -1, $keys[$i]);
465 return true;
469 * Returns the row index in which the given field has the given value. Returns false if none is found
470 * @param string $name Field name
471 * @param string $value Field value
472 * @return int|false
474 public function getRowFromValue($name, $value)
476 if (!$this->inColumnIndex($name))
478 throw new AOOSException($this->core(), $this->tr("not_in_column_index"), "", true, 2);
479 return false;
482 $c = $this->getColumn($name);
483 $r = null;
484 for($i = 0; $i < count($c); $i++)
486 if ($c[$i] == $value)
488 $r = $i;
492 if ($r === null)
494 throw new AOOSException($this->core(), $this->tr("value_not_in_row"), $this->tr("given_value").":". $value, true, 2);
495 return false;
498 return $r;
502 * Returns a given field. Calls getColum.
503 * @param int $row The row
504 * @param string $column Column index
505 * @return value|false
507 public function getField($row, $column)
509 return $this->getColumn($column, $row, $row);
513 * When set to true all data is escaped. Escaping is done in the data() call, which means *all* data is escaped, not only newly added data.
514 * Default is true.
515 * @param bool $state Should data be escaped or not?
516 * @return bool
518 public function setEscape($state)
520 if (!is_bool($state))
522 throw new AOOSException($this->core(), $this->tr("not_bool"));
523 return false;
525 $this->_escape = $state;
526 $this->_updated = false;
527 return true;
531 * Is data being escaped?
532 * @return bool
534 public function escape()
536 return $this->_escape;
540 * When set to true all data have quotes around it. Like setEscape(), quotes are added during the data() call. This means that all data, and not only newly added data, is quoted.
541 * Default is false.
542 * @param bool $state Should data have quotes or not?
543 * @return bool
545 public function setQuote($state)
547 if (!is_bool($state))
549 throw new AOOSException($this->core(), $this->tr("not_bool"));
550 return false;
552 $this->_quote = $state;
553 $this->_updated = false;
554 return true;
558 * Is data being quoted?
559 * @return bool
561 public function quote()
563 return $this->_quote;
566 /**
567 * Sort using mergesort
568 * @param string $name The column the data should be sorted by.
569 * @param ASC|DESC $order Should data be sorting in ascending or descending order?
570 * @return bool
572 public function sort($name, $order)
574 return true;
578 * Merges the selected data to a string
579 * @param ROW|COL $type Should data be selected from row or column?
580 * @param id $id Identifier.
582 public function merge($type, $id)
584 switch ($type)
586 case("ROW"):
587 $data = $this->getRow($id);
588 break;
589 case("COL"):
590 $data = $this->getColumn($id);
591 break;
592 default:
593 throw new AOOSException($this->core(), $this->tr("not_ROW_or_COL"), "", true, 1);
594 return false;
597 $pairs = array();
598 foreach ($data as $key => $value)
600 $pairs[] = $key.$this->_equal.$value;
602 $string = implode($pairs, $this->_seperator);
603 return $string;
607 * Splits the given string and appends it to the current model
608 * $param string $string The string to be splittet
610 public function split($string)
612 $f = array();
613 $a = explode($this->_seperator, $string);
614 foreach($a as $col)
616 $s = explode($this->_equal, $col);
617 $f[$s[0]] = $s[1];
619 $colindex = $this->columnIndex();
620 foreach(array_keys($f) as $index) {
621 $colindex[] = $index;
623 $this->setColumnIndex($colindex);
624 $this->append($f);