Вход Регистрация
Файл: framework/model/Map.php
Строк: 269
<?php

/**
 * Creates a map from an SS_List by defining a key column and a value column.
 *
 * @package framework
 * @subpackage model
 */
class SS_Map implements ArrayAccessCountableIteratorAggregate {

    protected 
$list$keyField$valueField;

    
/**
     * @see SS_Map::unshift()
     *
     * @var array $firstItems
     */
    
protected $firstItems = array();

    
/**
     * @see SS_Map::push()
     *
     * @var array $lastItems
     */
    
protected $lastItems = 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
     */
    
public function __construct(SS_List $list$keyField "ID"$valueField "Title") {
        
$this->list $list;
        
$this->keyField $keyField;
        
$this->valueField $valueField;
    }

    
/**
     * Set the key field for this map.
     *
     * @var string $keyField
     */
    
public function setKeyField($keyField) {
        
$this->keyField $keyField;
    }

    
/**
     * Set the value field for this map.
     *
     * @var string $valueField
     */
    
public function setValueField($valueField) {
        
$this->valueField $valueField;
    }

    
/**
     * Return an array equivalent to this map.
     *
     * @return array
     */
    
public function toArray() {
        
$array = array();

        foreach(
$this as $k => $v) {
            
$array[$k] = $v;
        }

        return 
$array;
    }

    
/**
     * Return all the keys of this map.
     *
     * @return array
     */
    
public function keys() {
        return 
array_keys($this->toArray());
    }

    
/**
     * Return all the values of this map.
     *
     * @return array
     */
    
public function values() {
        return 
array_values($this->toArray());
    }

    
/**
     * Unshift an item onto the start of the map.
     *
     * Stores the value in addition to the {@link DataQuery} for the map.
     *
     * @var string $key
     * @var mixed $value
     */
    
public function unshift($key$value) {
        
$oldItems $this->firstItems;
        
$this->firstItems = array(
            
$key => $value
        
);

        if(
$oldItems) {
            
$this->firstItems $this->firstItems $oldItems;
        }

        return 
$this;
    }

    
/**
     * Pushes an item onto the end of the map.
     *
     * @var string $key
     * @var mixed $value
     */
    
public function push($key$value) {
        
$oldItems $this->lastItems;

        
$this->lastItems = array(
            
$key => $value
        
);

        if(
$oldItems) {
            
$this->lastItems $this->lastItems $oldItems;
        }

        return 
$this;
    }

    
// ArrayAccess

    /**
     * @var string $key
     *
     * @return boolean
     */
    
public function offsetExists($key) {
        if(isset(
$this->firstItems[$key])) {
            return 
true;
        }

        if(isset(
$this->lastItems[$key])) {
            return 
true;
        }

        
$record $this->list->find($this->keyField$key);

        return 
$record != null;
    }

    
/**
     * @var string $key
     *
     * @return mixed
     */
    
public function offsetGet($key) {
        if(isset(
$this->firstItems[$key])) {
            return 
$this->firstItems[$key];
        }

        if(isset(
$this->lastItems[$key])) {
            return 
$this->lastItems[$key];
        }

        
$record $this->list->find($this->keyField$key);

        if(
$record) {
            
$col $this->valueField;

            return 
$record->$col;
        }

        return 
null;
    }

    
/**
     * Sets a value in the map by a given key that has been set via
     * {@link SS_Map::push()} or {@link SS_Map::unshift()}
     *
     * Keys in the map cannot be set since these values are derived from a
     * {@link DataQuery} instance. In this case, use {@link SS_Map::toArray()}
     * and manipulate the resulting array.
     *
     * @var string $key
     * @var mixed $value
     */
    
public function offsetSet($key$value) {
        if(isset(
$this->firstItems[$key])) {
            return 
$this->firstItems[$key] = $value;
        }

        if(isset(
$this->lastItems[$key])) {
            return 
$this->lastItems[$key] = $value;
        }

        
user_error(
            
"SS_Map is read-only. Please use $map->push($key$value) to append values",
            
E_USER_ERROR
        
);
    }

    
/**
     * Removes a value in the map by a given key which has been added to the map
     * via {@link SS_Map::push()} or {@link SS_Map::unshift()}
     *
     * Keys in the map cannot be unset since these values are derived from a
     * {@link DataQuery} instance. In this case, use {@link SS_Map::toArray()}
     * and manipulate the resulting array.
     *
     * @var string $key
     * @var mixed $value
     */
    
public function offsetUnset($key) {
        if(isset(
$this->firstItems[$key])) {
            unset(
$this->firstItems[$key]);

            return;
        }

        if(isset(
$this->lastItems[$key])) {
            unset(
$this->lastItems[$key]);

            return;
        }

        
user_error(
            
"SS_Map is read-only. Unset cannot be called on keys derived from the DataQuery",
            
E_USER_ERROR
        
);
    }

    
/**
     * Returns an SS_Map_Iterator instance for iterating over the complete set
     * of items in the map.
     *
     * Satisfies the IteratorAggreagte interface.
     *
     * @return SS_Map_Iterator
     */
    
public function getIterator() {
        return new 
SS_Map_Iterator(
            
$this->list->getIterator(),
            
$this->keyField,
            
$this->valueField,
            
$this->firstItems,
            
$this->lastItems
        
);
    }

    
/**
     * Returns the count of items in the list including the additional items set
     * through {@link SS_Map::push()} and {@link SS_Map::unshift}.
     *
     * @return int
     */
    
public function count() {
        return 
$this->list->count() +
            
count($this->firstItems) +
            
count($this->lastItems);
    }
}

/**
 * Builds a map iterator around an Iterator.  Called by SS_Map
 *
 * @package framework
 * @subpackage model
 */
class SS_Map_Iterator implements Iterator {

    protected 
$items;
    protected 
$keyField$titleField;

    protected 
$firstItemIdx 0;

    protected 
$endItemIdx;

    protected 
$firstItems = array();
    protected 
$lastItems = array();

    protected 
$excludedItems = array();

    
/**
     * @param Iterator $items The iterator to build this map from
     * @param string $keyField The field to use for the keys
     * @param string $titleField The field to use for the values
     * @param array $fristItems An optional map of items to show first
     * @param array $lastItems An optional map of items to show last
     */
    
public function __construct(Iterator $items$keyField$titleField$firstItems null$lastItems null) {
        
$this->items $items;
        
$this->keyField $keyField;
        
$this->titleField $titleField;
        
$this->endItemIdx null;

        if(
$firstItems) {
            foreach(
$firstItems as $k => $v) {
                
$this->firstItems[] = array($k,$v);
                
$this->excludedItems[] = $k;
            }
        }

        if(
$lastItems) {
            foreach(
$lastItems as $k => $v) {
                
$this->lastItems[] = array($k$v);
                
$this->excludedItems[] = $k;
            }
        }

    }

    
/**
     * Rewind the Iterator to the first element.
     *
     * @return mixed
     */
    
public function rewind() {
        
$this->firstItemIdx 0;
        
$this->endItemIdx null;

        
$rewoundItem $this->items->rewind();

        if(isset(
$this->firstItems[$this->firstItemIdx])) {
            return 
$this->firstItems[$this->firstItemIdx][1];
        } else {
            if(
$rewoundItem) {
                if(
$rewoundItem->hasMethod($this->titleField)) {
                    return 
$rewoundItem->{$this->titleField}();
                }

                return 
$rewoundItem->{$this->titleField};
            } else if(!
$this->items->valid() && $this->lastItems) {
                
$this->endItemIdx 0;

                return 
$this->lastItems[0][1];
            }
        }
    }

    
/**
     * Return the current element.
     *
     * @return mixed
     */
    
public function current() {
        if((
$this->endItemIdx !== null) && isset($this->lastItems[$this->endItemIdx])) {
            return 
$this->lastItems[$this->endItemIdx][1];
        } else if(isset(
$this->firstItems[$this->firstItemIdx])) {
            return 
$this->firstItems[$this->firstItemIdx][1];
        } else {
            if(
$this->items->current()->hasMethod($this->titleField)) {
                return 
$this->items->current()->{$this->titleField}();
            }

            return 
$this->items->current()->{$this->titleField};
        }
    }

    
/**
     * Return the key of the current element.
     *
     * @return string
     */
    
public function key() {
        if((
$this->endItemIdx !== null) && isset($this->lastItems[$this->endItemIdx])) {
            return 
$this->lastItems[$this->endItemIdx][0];
        } else if(isset(
$this->firstItems[$this->firstItemIdx])) {
            return 
$this->firstItems[$this->firstItemIdx][0];
        } else {
            return 
$this->items->current()->{$this->keyField};
        }
    }

    
/**
     * Move forward to next element.
     *
     * @return mixed
     */
    
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->excludedItemstrue)) {
                    
$this->items->next();
                }
            }
        }

        if(!
$this->items->valid()) {
            
// iterator has passed the preface items, off the end of the items
            // list. Track through the end items to go through to the next
            
if($this->endItemIdx === null) {
                
$this->endItemIdx = -1;
            }

            
$this->endItemIdx++;

            if(isset(
$this->lastItems[$this->endItemIdx])) {
                return 
$this->lastItems[$this->endItemIdx];
            }

            return 
false;
        }
    }

    
/**
     * Checks if current position is valid.
     *
     * @return boolean
     */
    
public function valid() {
        return (
            (isset(
$this->firstItems[$this->firstItemIdx])) ||
            ((
$this->endItemIdx !== null) && isset($this->lastItems[$this->endItemIdx])) ||
            
$this->items->valid()
        );
    }
}
Онлайн: 0
Реклама