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() {
25 foreach ($this->data() as $row) {
26 $string .= print_r($row, true);
32 private function _fixRange(&$start, &$end, $count)
34 if ($start === null) { $start = 0; }
35 if ($end === null) { $end = $count-1; }
37 if (!is_int($start) ||
!is_int($end))
39 throw new AOOSException($this->core(), $this->tr("not_int"), "", true, 1);
43 if ($start >= $count ||
$end >= $count)
45 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 1);
49 if ($start > $end && !($end < 0))
51 throw new AOOSException($this->core(), $this->tr("start_bigger_than_end"), "", true, 1);
55 // If start is > 0 we count from the end
58 $start = $count +
$start;
70 * Adds a row before $row.
71 * @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.
74 public function addRow($row = -1)
76 if ($row > count($this->_data
) ||
$row < -1)
78 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 1);
82 if ($row == -1 ||
count($this->_data
) == 0)
84 $this->_data
[] = null;
89 $this->_data
[$row] = null;
91 $count = count($this->_data
);
96 $this->_data
[$row] = $val;
99 $this->_updated
= false;
105 * Removes a row from the model.
106 * @param int $row The row to remove. Given -1 the last row is removed.
109 public function removeRow($row = -1)
111 if ($row < -1 ||
$row >= count($this->_data
))
113 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 2);
119 $row = count($this->_data
) - 1;
122 $this->_data
= array();
124 // Reinsert rows before $row
125 for ($i = 0; $i < $row; $i++
)
127 $this->_data
[] = $tmp[$i];
132 // Reinsert rows after $row
133 for ($c = count($tmp); $row < $c; $row++
)
135 $this->_data
[] = $tmp[$row];
138 $this->_updated
= false;
144 * Sets the data of a specified row and column.
145 * @param int $row The row in which the column is selected from
146 * @param int|string $col The column in which the data should be added
147 * @param $data The data that should be added.
150 public function setData($data, $row = -1, $col = -1)
152 if ($row >= count($this->_data
))
154 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 1);
159 $row = $this->rows() -1;
165 foreach ($this->_columnIndex
as $index)
175 if ($col >= count($this->_data
[$row]) ||
$col == -1)
177 $col = count($this->_data
[$row]);
180 $this->_data
[$row][$col] = $data;
181 $this->_updated
= false;
187 * @param int $col Column
188 * @param string $index Column index
191 public function setColumnIndex()
193 $count = func_num_args();
194 $arg1 = func_get_arg(0);
198 $arg2 = func_get_arg(1);
199 $this->_setColumnIndexSingle($arg1, $arg2);
202 $this->_setColumnIndexArray($arg1);
205 $this->_updated
= false;
208 private function _setColumnIndexSingle($col, $index)
212 throw new AOOSException($this->core(), $this->tr("not_integer"), "", true, 1);
215 if (!is_string($index))
217 throw new AOOSException($this->core(), $this->tr("not_string"), "", true, 1);
220 $this->_columnIndex
[$col] = $index;
223 private function _setColumnIndexArray($index)
225 if (!is_array($index))
227 throw new AOOSException($this->core(), $this->tr("not_array"), "", true, 1);
232 foreach ($index as $i)
234 $this->_columnIndex
[$c] = $i;
240 * Returns everything in the model
243 public function data()
248 if ($this->_updated
) // If the model is updated we don't need to iterate through the data
250 return $this->_model
;
253 foreach ($this->_data
as $row)
256 foreach ($this->_columnIndex
as $colIndex)
258 if ($index >= count($row))
266 $col = mysql_real_escape_string($col);
271 $col = "\"".$col."\"";
274 $data[$rowIndex][$colIndex] = $col;
279 $this->_updated
= true;
280 $this->_model
= $data;
281 return $this->_model
;
285 * Returns a given column
286 * @param string $index The column index
287 * @param int $start "From row"
288 * @param int $end "To row". Inclusive.
291 public function getColumn($index, $start = null, $end = null)
293 $data = $this->data();
294 $count = count($data);
297 if (!in_array($index, $this->_columnIndex
))
299 throw new AOOSException($this->core(), $this->tr("not_in_column_index"), "", true, 1);
303 $this->_fixRange($start, $end, $count);
305 for ($i = $start; $i <= $end; $i++
)
307 $column[] = $data[$i][$index];
313 public function getColumns($fields, $start = null, $end = null)
316 foreach ($fields as $index)
318 $cols[] = $this->getColumn($index, $start, $end);
325 * @param int $start "From row"
326 * @param int $end "To row". Inclusive.
327 * @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.
330 public function getRows($start = null, $end = null, $cutoff = false)
332 $data = $this->data();
333 $count = count($data);
336 if ($this->rows() == 0)
338 throw new AOOSException($this->core(), $this->tr("model_empty"), "", true, 2);
342 if ($cutoff && $end > $this->rows())
344 $end = $this->rows();
347 $this->_fixRange($start, $end, $count);
349 for ($i = $start; $i <= $end; $i++
)
358 * Returns a single row
359 * @param int $id Row id
362 public function getRow($id)
364 $tmp = $this->getRows($id, $id);
370 * Returns the column index
373 public function columnIndex()
375 return $this->_columnIndex
;
379 * Returns the row count
382 public function rows()
388 * Returns the column count
391 public function columns()
393 return count($this->_columnIndex
);
397 * Is the given value in the given column?
398 * @param string $col Column id
399 * @param value $val Value
402 public function inColumn($col, $val)
404 $c = $this->getColumn($col);
405 if (!in_array($val, $c))
413 * Is the given value a column index?
414 * @param string $name
417 public function inColumnIndex($name)
419 if (!in_array($name, $this->columnIndex()))
427 * Appends given values to the end of the model. The number of keys is the number of values added.
428 * @param array $values Values to append.
429 * @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).
432 public function append($values, $key = null)
437 if (!is_array($values))
439 throw new AOOSException($this->core(), $this->tr("not_array"));
445 $keys = $this->columnIndex();
449 $keys = array_keys($values);
450 $values = array_values($values);
455 for ($i=0; $i<$c; $i++
)
457 $this->setData($values[$i], -1, $keys[$i]);
463 * Returns the row index in which the given field has the given value. Returns false if none is found
464 * @param string $name Field name
465 * @param string $value Field value
468 public function getRowFromValue($name, $value)
470 if (!$this->inColumnIndex($name))
472 throw new AOOSException($this->core(), $this->tr("not_in_column_index"), "", true, 2);
476 $c = $this->getColumn($name);
478 for($i = 0; $i < count($c); $i++
)
480 if ($c[$i] == $value)
488 throw new AOOSException($this->core(), $this->tr("value_not_in_row"), $this->tr("given_value").":". $value, true, 2);
496 * Returns a given field. Calls getColum.
497 * @param int $row The row
498 * @param string $column Column index
499 * @return value|false
501 public function getField($row, $column)
503 return $this->getColumn($column, $row, $row);
507 * 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.
509 * @param bool $state Should data be escaped or not?
512 public function setEscape($state)
514 if (!is_bool($state))
516 throw new AOOSException($this->core(), $this->tr("not_bool"));
519 $this->_escape
= $state;
520 $this->_updated
= false;
525 * Is data being escaped?
528 public function escape()
530 return $this->_escape
;
534 * 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.
536 * @param bool $state Should data have quotes or not?
539 public function setQuote($state)
541 if (!is_bool($state))
543 throw new AOOSException($this->core(), $this->tr("not_bool"));
546 $this->_quote
= $state;
547 $this->_updated
= false;
552 * Is data being quoted?
555 public function quote()
557 return $this->_quote
;
561 * Sort using mergesort
562 * @param string $name The column the data should be sorted by.
563 * @param ASC|DESC $order Should data be sorting in ascending or descending order?
566 public function sort($name, $order)
572 * Merges the selected data to a string
573 * @param ROW|COL $type Should data be selected from row or column?
574 * @param id $id Identifier.
576 public function merge($type, $id)
581 $data = $this->getRow($id);
584 $data = $this->getColumn($id);
587 throw new AOOSException($this->core(), $this->tr("not_ROW_or_COL"), "", true, 1);
592 foreach ($data as $key => $value)
594 $pairs[] = $key.$this->_equal
.$value;
596 $string = implode($pairs, $this->_seperator
);
601 * Splits the given string and appends it to the current model
602 * $param string $string The string to be splittet
604 public function split($string)
607 $a = explode($this->_seperator
, $string);
610 $s = explode($this->_equal
, $col);
613 $colindex = $this->columnIndex();
614 foreach(array_keys($f) as $index) {
615 $colindex[] = $index;
617 $this->setColumnIndex($colindex);