2011-10-29 03:04:17 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a map from an SS_List by defining a key column and a value column.
|
|
|
|
*
|
2012-04-12 08:02:46 +02:00
|
|
|
* @package framework
|
2011-10-29 03:04:17 +02:00
|
|
|
* @subpackage model
|
|
|
|
*/
|
|
|
|
class SS_Map implements ArrayAccess, Countable, IteratorAggregate {
|
|
|
|
protected $list, $keyField, $valueField;
|
|
|
|
|
|
|
|
protected $firstItems = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a new map around an SS_list.
|
|
|
|
* @param $list The list to build a map from
|
|
|
|
* @param $keyField The field to use as the key of each map entry
|
|
|
|
* @param $valueField The field to use as the value of each map entry
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct(SS_List $list, $keyField = "ID", $valueField = "Title") {
|
2011-10-29 03:04:17 +02:00
|
|
|
$this->list = $list;
|
|
|
|
$this->keyField = $keyField;
|
|
|
|
$this->valueField = $valueField;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the key field for this map
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function setKeyField($keyField) {
|
2011-10-29 03:04:17 +02:00
|
|
|
$this->keyField = $keyField;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the value field for this map
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function setValueField($valueField) {
|
2011-10-29 03:04:17 +02:00
|
|
|
$this->valueField = $valueField;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return an array equivalent to this map
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function toArray() {
|
2011-10-29 03:04:17 +02:00
|
|
|
$array = array();
|
|
|
|
foreach($this as $k => $v) {
|
|
|
|
$array[$k] = $v;
|
|
|
|
}
|
|
|
|
return $array;
|
|
|
|
}
|
2012-02-10 23:44:04 +01:00
|
|
|
|
2011-10-29 03:04:17 +02:00
|
|
|
/**
|
|
|
|
* Return all the keys of this map
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function keys() {
|
2012-02-10 23:44:04 +01:00
|
|
|
$output = array();
|
2011-10-29 03:04:17 +02:00
|
|
|
foreach($this as $k => $v) {
|
2012-02-10 23:44:04 +01:00
|
|
|
$output[] = $k;
|
2011-10-29 03:04:17 +02:00
|
|
|
}
|
2012-02-10 23:44:04 +01:00
|
|
|
return $output;
|
2011-10-29 03:04:17 +02:00
|
|
|
}
|
2012-02-10 23:44:04 +01:00
|
|
|
|
2011-10-29 03:04:17 +02:00
|
|
|
/**
|
|
|
|
* Return all the values of this map
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function values() {
|
2012-02-10 23:44:04 +01:00
|
|
|
$output = array();
|
2011-10-29 03:04:17 +02:00
|
|
|
foreach($this as $k => $v) {
|
2012-02-10 23:44:04 +01:00
|
|
|
$output[] = $v;
|
2011-10-29 03:04:17 +02:00
|
|
|
}
|
2012-02-10 23:44:04 +01:00
|
|
|
return $output;
|
2011-10-29 03:04:17 +02:00
|
|
|
}
|
2012-02-10 23:44:04 +01:00
|
|
|
|
2011-10-29 03:04:17 +02:00
|
|
|
/**
|
|
|
|
* Unshift an item onto the start of the map
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function unshift($key, $value) {
|
2011-10-29 03:04:17 +02:00
|
|
|
$oldItems = $this->firstItems;
|
|
|
|
$this->firstItems = array($key => $value);
|
|
|
|
if($oldItems) $this->firstItems = $this->firstItems + $oldItems;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ArrayAccess
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function offsetExists($key) {
|
2011-10-29 03:04:17 +02:00
|
|
|
if(isset($this->firstItems[$key])) return true;
|
|
|
|
|
|
|
|
$record = $this->list->find($this->keyField, $key);
|
|
|
|
return $record != null;
|
|
|
|
}
|
2012-09-19 12:07:39 +02:00
|
|
|
public function offsetGet($key) {
|
2011-10-29 03:04:17 +02:00
|
|
|
if(isset($this->firstItems[$key])) return $this->firstItems[$key];
|
|
|
|
|
|
|
|
$record = $this->list->find($this->keyField, $key);
|
|
|
|
if($record) {
|
|
|
|
$col = $this->valueField;
|
|
|
|
return $record->$col;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2012-09-19 12:07:39 +02:00
|
|
|
public function offsetSet($key, $value) {
|
2011-10-29 03:04:17 +02:00
|
|
|
if(isset($this->firstItems[$key])) return $this->firstItems[$key] = $value;
|
|
|
|
|
|
|
|
user_error("SS_Map is read-only", E_USER_ERROR);
|
|
|
|
}
|
2012-09-19 12:07:39 +02:00
|
|
|
public function offsetUnset($key) {
|
2011-10-29 03:04:17 +02:00
|
|
|
if(isset($this->firstItems[$key])) {
|
|
|
|
unset($this->firstItems[$key]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
user_error("SS_Map is read-only", E_USER_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
// IteratorAggreagte
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getIterator() {
|
2011-10-29 03:04:17 +02:00
|
|
|
return new SS_Map_Iterator($this->list->getIterator(), $this->keyField, $this->valueField, $this->firstItems);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Countable
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function count() {
|
2011-10-29 03:04:17 +02:00
|
|
|
return $this->list->count();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Builds a map iterator around an Iterator. Called by SS_Map
|
2012-04-12 08:02:46 +02:00
|
|
|
* @package framework
|
2011-10-29 03:04:17 +02:00
|
|
|
* @subpackage model
|
|
|
|
*/
|
|
|
|
class SS_Map_Iterator implements Iterator {
|
|
|
|
protected $items;
|
|
|
|
protected $keyField, $titleField;
|
|
|
|
|
|
|
|
protected $firstItemIdx = 0;
|
|
|
|
protected $firstItems = array();
|
|
|
|
protected $excludedItems = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $items The iterator to build this map from
|
|
|
|
* @param $keyField The field to use for the keys
|
|
|
|
* @param $titleField The field to use for the values
|
|
|
|
* @param $fistItems An optional map of items to show first
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct(Iterator $items, $keyField, $titleField, $firstItems = null) {
|
2011-10-29 03:04:17 +02:00
|
|
|
$this->items = $items;
|
|
|
|
$this->keyField = $keyField;
|
|
|
|
$this->titleField = $titleField;
|
|
|
|
|
|
|
|
foreach($firstItems as $k => $v) {
|
|
|
|
$this->firstItems[] = array($k,$v);
|
|
|
|
$this->excludedItems[] = $k;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterator functions
|
|
|
|
|
|
|
|
public function rewind() {
|
|
|
|
$this->firstItemIdx = 0;
|
|
|
|
$rewoundItem = $this->items->rewind();
|
|
|
|
|
|
|
|
if(isset($this->firstItems[$this->firstItemIdx])) {
|
|
|
|
return $this->firstItems[$this->firstItemIdx][1];
|
|
|
|
} else {
|
2012-03-15 05:28:00 +01:00
|
|
|
if($rewoundItem) return ($rewoundItem->hasMethod($this->titleField))
|
|
|
|
? $rewoundItem->{$this->titleField}()
|
|
|
|
: $rewoundItem->{$this->titleField};
|
2011-10-29 03:04:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public function current() {
|
|
|
|
if(isset($this->firstItems[$this->firstItemIdx])) {
|
|
|
|
return $this->firstItems[$this->firstItemIdx][1];
|
|
|
|
} else {
|
2012-03-15 05:28:00 +01:00
|
|
|
return ($this->items->current()->hasMethod($this->titleField))
|
|
|
|
? $this->items->current()->{$this->titleField}()
|
|
|
|
: $this->items->current()->{$this->titleField};
|
2011-10-29 03:04:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function key() {
|
|
|
|
if(isset($this->firstItems[$this->firstItemIdx])) {
|
|
|
|
return $this->firstItems[$this->firstItemIdx][0];
|
|
|
|
|
|
|
|
} else {
|
|
|
|
return $this->items->current()->{$this->keyField};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function next() {
|
|
|
|
$this->firstItemIdx++;
|
|
|
|
if(isset($this->firstItems[$this->firstItemIdx])) {
|
|
|
|
return $this->firstItems[$this->firstItemIdx][1];
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if(!isset($this->firstItems[$this->firstItemIdx-1])) $this->items->next();
|
|
|
|
|
|
|
|
if($this->excludedItems) while(($c = $this->items->current()) && in_array($c->{$this->keyField}, $this->excludedItems, true)) {
|
|
|
|
$this->items->next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function valid() {
|
|
|
|
return $this->items->valid();
|
|
|
|
}
|
|
|
|
}
|