mirror of
https://github.com/torrentpier/torrentpier-lts.git
synced 2025-03-01 15:21:02 +03:00
262 lines
5.0 KiB
PHP
262 lines
5.0 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Zend Framework (http://framework.zend.com/)
|
||
|
*
|
||
|
* @link http://github.com/zendframework/zf2 for the canonical source repository
|
||
|
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
|
||
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||
|
*/
|
||
|
|
||
|
namespace Zend\Stdlib;
|
||
|
|
||
|
use Countable;
|
||
|
use Iterator;
|
||
|
|
||
|
class PriorityList implements Iterator, Countable
|
||
|
{
|
||
|
const EXTR_DATA = 0x00000001;
|
||
|
const EXTR_PRIORITY = 0x00000002;
|
||
|
const EXTR_BOTH = 0x00000003;
|
||
|
/**
|
||
|
* Internal list of all items.
|
||
|
*
|
||
|
* @var array[]
|
||
|
*/
|
||
|
protected $items = array();
|
||
|
|
||
|
/**
|
||
|
* Serial assigned to items to preserve LIFO.
|
||
|
*
|
||
|
* @var int
|
||
|
*/
|
||
|
protected $serial = 0;
|
||
|
|
||
|
/**
|
||
|
* Serial order mode
|
||
|
* @var integer
|
||
|
*/
|
||
|
protected $isLIFO = 1;
|
||
|
|
||
|
/**
|
||
|
* Internal counter to avoid usage of count().
|
||
|
*
|
||
|
* @var int
|
||
|
*/
|
||
|
protected $count = 0;
|
||
|
|
||
|
/**
|
||
|
* Whether the list was already sorted.
|
||
|
*
|
||
|
* @var bool
|
||
|
*/
|
||
|
protected $sorted = false;
|
||
|
|
||
|
/**
|
||
|
* Insert a new item.
|
||
|
*
|
||
|
* @param string $name
|
||
|
* @param mixed $value
|
||
|
* @param int $priority
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function insert($name, $value, $priority = 0)
|
||
|
{
|
||
|
$this->sorted = false;
|
||
|
$this->count++;
|
||
|
|
||
|
$this->items[$name] = array(
|
||
|
'data' => $value,
|
||
|
'priority' => (int) $priority,
|
||
|
'serial' => $this->serial++,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $name
|
||
|
* @param int $priority
|
||
|
*
|
||
|
* @return $this
|
||
|
*
|
||
|
* @throws \Exception
|
||
|
*/
|
||
|
public function setPriority($name, $priority)
|
||
|
{
|
||
|
if (!isset($this->items[$name])) {
|
||
|
throw new \Exception("item $name not found");
|
||
|
}
|
||
|
|
||
|
$this->items[$name]['priority'] = (int) $priority;
|
||
|
$this->sorted = false;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove a item.
|
||
|
*
|
||
|
* @param string $name
|
||
|
* @return void
|
||
|
*/
|
||
|
public function remove($name)
|
||
|
{
|
||
|
if (isset($this->items[$name])) {
|
||
|
$this->count--;
|
||
|
}
|
||
|
|
||
|
unset($this->items[$name]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove all items.
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function clear()
|
||
|
{
|
||
|
$this->items = array();
|
||
|
$this->serial = 0;
|
||
|
$this->count = 0;
|
||
|
$this->sorted = false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get a item.
|
||
|
*
|
||
|
* @param string $name
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function get($name)
|
||
|
{
|
||
|
if (!isset($this->items[$name])) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return $this->items[$name]['data'];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sort all items.
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
protected function sort()
|
||
|
{
|
||
|
if (!$this->sorted) {
|
||
|
uasort($this->items, array($this, 'compare'));
|
||
|
$this->sorted = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Compare the priority of two items.
|
||
|
*
|
||
|
* @param array $item1,
|
||
|
* @param array $item2
|
||
|
* @return int
|
||
|
*/
|
||
|
protected function compare(array $item1, array $item2)
|
||
|
{
|
||
|
return ($item1['priority'] === $item2['priority'])
|
||
|
? ($item1['serial'] > $item2['serial'] ? -1 : 1) * $this->isLIFO
|
||
|
: ($item1['priority'] > $item2['priority'] ? -1 : 1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get/Set serial order mode
|
||
|
*
|
||
|
* @param bool|null $flag
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function isLIFO($flag = null)
|
||
|
{
|
||
|
if ($flag !== null) {
|
||
|
$isLifo = $flag === true ? 1 : -1;
|
||
|
|
||
|
if ($isLifo !== $this->isLIFO) {
|
||
|
$this->isLIFO = $isLifo;
|
||
|
$this->sorted = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 1 === $this->isLIFO;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*/
|
||
|
public function rewind()
|
||
|
{
|
||
|
$this->sort();
|
||
|
reset($this->items);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*/
|
||
|
public function current()
|
||
|
{
|
||
|
$node = current($this->items);
|
||
|
|
||
|
return $node ? $node['data'] : false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*/
|
||
|
public function key()
|
||
|
{
|
||
|
return key($this->items);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*/
|
||
|
public function next()
|
||
|
{
|
||
|
$node = next($this->items);
|
||
|
|
||
|
return $node ? $node['data'] : false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*/
|
||
|
public function valid()
|
||
|
{
|
||
|
return current($this->items) !== false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*/
|
||
|
public function count()
|
||
|
{
|
||
|
return $this->count;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return list as array
|
||
|
*
|
||
|
* @param int $flag
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function toArray($flag = self::EXTR_DATA)
|
||
|
{
|
||
|
$this->sort();
|
||
|
|
||
|
if ($flag == self::EXTR_BOTH) {
|
||
|
return $this->items;
|
||
|
}
|
||
|
|
||
|
return array_map(
|
||
|
self::EXTR_PRIORITY === $flag
|
||
|
? function ($item) { return $item['priority']; }
|
||
|
: function ($item) { return $item['data']; },
|
||
|
$this->items
|
||
|
);
|
||
|
}
|
||
|
}
|