2 require_once("AOOSException.php");
3 require_once("AOOSModule.php");
7 * A table-like model for containing data
8 * @author Sebastian Skejø
11 class AOOSModel
extends AOOSModule
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(" ", " ", print_r($this->data(), true)));
25 /* foreach ($this->data() as $row) {
26 $string .= print_r($row, true);
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);
44 if ($start >= $count ||
$end >= $count)
46 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 1);
50 if ($start > $end && !($end < 0))
52 throw new AOOSException($this->core(), $this->tr("start_bigger_than_end"), "", true, 1);
56 // If start is > 0 we count from the end
59 $start = $count +
$start;
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.
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);
83 if ($row == -1 ||
count($this->_data
) == 0)
85 $this->_data
[] = null;
90 $this->_data
[$row] = null;
92 $count = count($this->_data
);
97 $this->_data
[$row] = $val;
100 $this->_updated
= false;
106 * Removes a row from the model.
107 * @param int $row The row to remove. Given -1 the last row is removed.
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);
120 $row = count($this->_data
) - 1;
123 $this->_data
= array();
125 // Reinsert rows before $row
126 for ($i = 0; $i < $row; $i++
)
128 $this->_data
[] = $tmp[$i];
133 // Reinsert rows after $row
134 for ($c = count($tmp); $row < $c; $row++
)
136 $this->_data
[] = $tmp[$row];
139 $this->_updated
= false;
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.
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);
160 $row = $this->rows() -1;
166 foreach ($this->_columnIndex
as $index)
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;
188 * @param int $col Column
189 * @param string $index Column index
192 public function setColumnIndex()
194 $count = func_num_args();
195 $arg1 = func_get_arg(0);
199 $arg2 = func_get_arg(1);
200 $this->_setColumnIndexSingle($arg1, $arg2);
203 $this->_setColumnIndexArray($arg1);
206 $this->_updated
= false;
209 private function _setColumnIndexSingle($col, $index)
213 throw new AOOSException($this->core(), $this->tr("not_integer"), "", true, 1);
216 if (!is_string($index))
218 throw new AOOSException($this->core(), $this->tr("not_string"), "", true, 1);
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);
233 foreach ($index as $i)
235 $this->_columnIndex
[$c] = $i;
241 * Returns everything in the model
244 public function data()
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)
257 foreach ($this->_columnIndex
as $colIndex)
259 if ($index >= count($row))
267 $col = mysql_real_escape_string($col);
272 $col = "\"".$col."\"";
275 $data[$rowIndex][$colIndex] = $col;
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);
299 if (!in_array($index, $this->_columnIndex
))
301 throw new AOOSException($this->core(), $this->tr("not_in_column_index"), "", true, 1);
305 $this->_fixRange($start, $end, $count);
307 for ($i = $start; $i <= $end; $i++
)
309 $column[] = $data[$i][$index];
313 $column = array_pop($column);
319 public function getColumns($fields, $start = null, $end = null)
322 foreach ($fields as $index)
324 $cols[] = $this->getColumn($index, $start, $end);
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.
336 public function getRows($start = null, $end = null, $cutoff = false)
338 $data = $this->data();
339 $count = count($data);
342 if ($this->rows() == 0)
344 throw new AOOSException($this->core(), $this->tr("model_empty"), "", true, 2);
348 if ($cutoff && $end > $this->rows())
350 $end = $this->rows();
353 $this->_fixRange($start, $end, $count);
355 for ($i = $start; $i <= $end; $i++
)
364 * Returns a single row
365 * @param int $id Row id
368 public function getRow($id)
370 $tmp = $this->getRows($id, $id);
376 * Returns the column index
379 public function columnIndex()
381 return $this->_columnIndex
;
385 * Returns the row count
388 public function rows()
394 * Returns the column count
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
408 public function inColumn($col, $val)
410 $c = $this->getColumn($col);
411 if (!in_array($val, $c))
419 * Is the given value a column index?
420 * @param string $name
423 public function inColumnIndex($name)
425 if (!in_array($name, $this->columnIndex()))
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).
438 public function append($values, $key = null)
443 if (!is_array($values))
445 throw new AOOSException($this->core(), $this->tr("not_array"));
451 $keys = $this->columnIndex();
455 $keys = array_keys($values);
456 $values = array_values($values);
461 for ($i=0; $i<$c; $i++
)
463 $this->setData($values[$i], -1, $keys[$i]);
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
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);
482 $c = $this->getColumn($name);
484 for($i = 0; $i < count($c); $i++
)
486 if ($c[$i] == $value)
494 throw new AOOSException($this->core(), $this->tr("value_not_in_row"), $this->tr("given_value").":". $value, true, 2);
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.
515 * @param bool $state Should data be escaped or not?
518 public function setEscape($state)
520 if (!is_bool($state))
522 throw new AOOSException($this->core(), $this->tr("not_bool"));
525 $this->_escape
= $state;
526 $this->_updated
= false;
531 * Is data being escaped?
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.
542 * @param bool $state Should data have quotes or not?
545 public function setQuote($state)
547 if (!is_bool($state))
549 throw new AOOSException($this->core(), $this->tr("not_bool"));
552 $this->_quote
= $state;
553 $this->_updated
= false;
558 * Is data being quoted?
561 public function quote()
563 return $this->_quote
;
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?
572 public function sort($name, $order)
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)
587 $data = $this->getRow($id);
590 $data = $this->getColumn($id);
593 throw new AOOSException($this->core(), $this->tr("not_ROW_or_COL"), "", true, 1);
598 foreach ($data as $key => $value)
600 $pairs[] = $key.$this->_equal
.$value;
602 $string = implode($pairs, $this->_seperator
);
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)
613 $a = explode($this->_seperator
, $string);
616 $s = explode($this->_equal
, $col);
619 $colindex = $this->columnIndex();
620 foreach(array_keys($f) as $index) {
621 $colindex[] = $index;
623 $this->setColumnIndex($colindex);