Added a __toString()
[AOOS.git] / AOOSModel.php
blob59244e4b48f00fb5e10a45f0a8a452e4971eac7a
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 = "";
25 foreach ($this->data() as $row) {
26 $string .= print_r($row, true);
27 $string .= "<br />";
29 return $string;
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);
40 return false;
43 if ($start >= $count || $end >= $count)
45 throw new AOOSException($this->core(), $this->tr("row_out_of_bounds"), "", true, 1);
46 return false;
49 if ($start > $end && !($end < 0))
51 throw new AOOSException($this->core(), $this->tr("start_bigger_than_end"), "", true, 1);
52 return false;
55 // If start is > 0 we count from the end
56 if ($start < 0)
58 $start = $count + $start;
60 // Same goes for end
61 if ($end < 0)
63 $end = $count + $end;
66 return true;
69 /**
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.
72 * @return bool
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);
79 return false;
82 if ($row == -1 || count($this->_data) == 0)
84 $this->_data[] = null;
86 else
88 $tmp = $this->_data;
89 $this->_data[$row] = null;
91 $count = count($this->_data);
92 while ($row < $count)
94 $val = $tmp[$row];
95 $row++;
96 $this->_data[$row] = $val;
99 $this->_updated = false;
100 $this->_rows++;
101 return true;
105 * Removes a row from the model.
106 * @param int $row The row to remove. Given -1 the last row is removed.
107 * @return bol
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);
114 return false;
117 if ($row == -1)
119 $row = count($this->_data) - 1;
121 $tmp = $this->_data;
122 $this->_data = array();
124 // Reinsert rows before $row
125 for ($i = 0; $i < $row; $i++)
127 $this->_data[] = $tmp[$i];
130 $row++;
132 // Reinsert rows after $row
133 for ($c = count($tmp); $row < $c; $row++)
135 $this->_data[] = $tmp[$row];
138 $this->_updated = false;
139 $this->_rows--;
140 return true;
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.
148 * @return bool
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);
155 return false;
157 if ($row == -1)
159 $row = $this->rows() -1;
162 if (is_string($col))
164 $i = 0;
165 foreach ($this->_columnIndex as $index)
167 if ($index == $col)
169 $col = $i;
170 break;
172 $i++;
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;
182 return true;
186 * Sets column index
187 * @param int $col Column
188 * @param string $index Column index
189 * @return bool
191 public function setColumnIndex()
193 $count = func_num_args();
194 $arg1 = func_get_arg(0);
195 switch ($count)
197 case (2):
198 $arg2 = func_get_arg(1);
199 $this->_setColumnIndexSingle($arg1, $arg2);
200 break;
201 case(1):
202 $this->_setColumnIndexArray($arg1);
203 break;
205 $this->_updated = false;
208 private function _setColumnIndexSingle($col, $index)
210 if (!is_int($col))
212 throw new AOOSException($this->core(), $this->tr("not_integer"), "", true, 1);
213 return false;
215 if (!is_string($index))
217 throw new AOOSException($this->core(), $this->tr("not_string"), "", true, 1);
218 return false;
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);
228 return false;
231 $c = 0;
232 foreach ($index as $i)
234 $this->_columnIndex[$c] = $i;
235 $c++;
240 * Returns everything in the model
241 * @return data|false
243 public function data()
245 $data = array();
246 $rowIndex = 0;
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)
255 $index = 0;
256 foreach ($this->_columnIndex as $colIndex)
258 if ($index >= count($row))
260 $row[$index] = "";
263 $col = $row[$index];
264 if ($this->escape())
266 $col = mysql_real_escape_string($col);
269 if ($this->quote())
271 $col = "\"".$col."\"";
274 $data[$rowIndex][$colIndex] = $col;
275 $index++;
277 $rowIndex++;
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.
289 * @return array
291 public function getColumn($index, $start = null, $end = null)
293 $data = $this->data();
294 $count = count($data);
295 $column = array();
297 if (!in_array($index, $this->_columnIndex))
299 throw new AOOSException($this->core(), $this->tr("not_in_column_index"), "", true, 1);
300 return false;
303 $this->_fixRange($start, $end, $count);
305 for ($i = $start; $i <= $end; $i++)
307 $column[] = $data[$i][$index];
310 return $column;
313 public function getColumns($fields, $start = null, $end = null)
315 $cols = array();
316 foreach ($fields as $index)
318 $cols[] = $this->getColumn($index, $start, $end);
320 return $cols;
324 * Returns rows
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.
328 * @return array
330 public function getRows($start = null, $end = null, $cutoff = false)
332 $data = $this->data();
333 $count = count($data);
334 $rows = array();
336 if ($this->rows() == 0)
338 throw new AOOSException($this->core(), $this->tr("model_empty"), "", true, 2);
339 return false;
342 if ($cutoff && $end > $this->rows())
344 $end = $this->rows();
347 $this->_fixRange($start, $end, $count);
349 for ($i = $start; $i <= $end; $i++)
351 $rows[] = $data[$i];
354 return $rows;
358 * Returns a single row
359 * @param int $id Row id
360 * @return array
362 public function getRow($id)
364 $tmp = $this->getRows($id, $id);
365 return $tmp[0];
370 * Returns the column index
371 * @return array
373 public function columnIndex()
375 return $this->_columnIndex;
379 * Returns the row count
380 * @return int
382 public function rows()
384 return $this->_rows;
388 * Returns the column count
389 * @return int
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
400 * @return bool
402 public function inColumn($col, $val)
404 $c = $this->getColumn($col);
405 if (!in_array($val, $c))
407 return false;
409 return true;
413 * Is the given value a column index?
414 * @param string $name
415 * @return bool
417 public function inColumnIndex($name)
419 if (!in_array($name, $this->columnIndex()))
421 return false;
423 return true;
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).
430 * @return bool
432 public function append($values, $key = null)
434 $keys = array();
435 $c = 0;
437 if (!is_array($values))
439 throw new AOOSException($this->core(), $this->tr("not_array"));
440 return false;
443 if ($key == "auto")
445 $keys = $this->columnIndex();
447 else
449 $keys = array_keys($values);
450 $values = array_values($values);
453 $this->addRow();
454 $c = count($keys);
455 for ($i=0; $i<$c; $i++)
457 $this->setData($values[$i], -1, $keys[$i]);
459 return true;
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
466 * @return int|false
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);
473 return false;
476 $c = $this->getColumn($name);
477 $r = null;
478 for($i = 0; $i < count($c); $i++)
480 if ($c[$i] == $value)
482 $r = $i;
486 if ($r === null)
488 throw new AOOSException($this->core(), $this->tr("value_not_in_row"), $this->tr("given_value").":". $value, true, 2);
489 return false;
492 return $r;
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.
508 * Default is true.
509 * @param bool $state Should data be escaped or not?
510 * @return bool
512 public function setEscape($state)
514 if (!is_bool($state))
516 throw new AOOSException($this->core(), $this->tr("not_bool"));
517 return false;
519 $this->_escape = $state;
520 $this->_updated = false;
521 return true;
525 * Is data being escaped?
526 * @return bool
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.
535 * Default is false.
536 * @param bool $state Should data have quotes or not?
537 * @return bool
539 public function setQuote($state)
541 if (!is_bool($state))
543 throw new AOOSException($this->core(), $this->tr("not_bool"));
544 return false;
546 $this->_quote = $state;
547 $this->_updated = false;
548 return true;
552 * Is data being quoted?
553 * @return bool
555 public function quote()
557 return $this->_quote;
560 /**
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?
564 * @return bool
566 public function sort($name, $order)
568 return true;
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)
578 switch ($type)
580 case("ROW"):
581 $data = $this->getRow($id);
582 break;
583 case("COL"):
584 $data = $this->getColumn($id);
585 break;
586 default:
587 throw new AOOSException($this->core(), $this->tr("not_ROW_or_COL"), "", true, 1);
588 return false;
591 $pairs = array();
592 foreach ($data as $key => $value)
594 $pairs[] = $key.$this->_equal.$value;
596 $string = implode($pairs, $this->_seperator);
597 return $string;
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)
606 $f = array();
607 $a = explode($this->_seperator, $string);
608 foreach($a as $col)
610 $s = explode($this->_equal, $col);
611 $f[$s[0]] = $s[1];
613 $colindex = $this->columnIndex();
614 foreach(array_keys($f) as $index) {
615 $colindex[] = $index;
617 $this->setColumnIndex($colindex);
618 $this->append($f);