mirror of
https://github.com/php/php-src.git
synced 2024-11-25 10:54:15 +08:00
- MFH: Add new files
This commit is contained in:
parent
b4dd030782
commit
a29501195f
55
ext/spl/examples/recursivearrayiterator.inc
Executable file
55
ext/spl/examples/recursivearrayiterator.inc
Executable file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/** @file recursivearrayiterator.inc
|
||||
* @ingroup Examples
|
||||
* @brief class RecursiveArrayIterator
|
||||
* @author Marcus Boerger
|
||||
* @date 2003 - 2005
|
||||
*
|
||||
* SPL - Standard PHP Library
|
||||
*/
|
||||
|
||||
/** @ingroup Examples
|
||||
* @brief A recursive array iterator
|
||||
* @author Marcus Boerger
|
||||
* @version 1.0
|
||||
* @since PHP 6.0
|
||||
*
|
||||
* Passes the RecursiveIterator interface to the inner Iterator and provides
|
||||
* the same functionality as FilterIterator. This allows you to skip parents
|
||||
* and all their childs before loading them all. You need to care about
|
||||
* function getChildren() because it may not always suit your needs. The
|
||||
* builtin behavior uses reflection to return a new instance of the exact same
|
||||
* class it is called from. That is you extend RecursiveFilterIterator and
|
||||
* getChildren() will create instance of that class. The problem is that doing
|
||||
* this does not transport any state or control information of your accept()
|
||||
* implementation to the new instance. To overcome this problem you might
|
||||
* need to overwrite getChildren(), call this implementation and pass the
|
||||
* control vaules manually.
|
||||
*/
|
||||
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
{
|
||||
/** @return whether the current element has children
|
||||
*/
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
/** @return an iterator for the current elements children
|
||||
*
|
||||
* @note the returned iterator will be of the same class as $this
|
||||
*/
|
||||
function getChildren()
|
||||
{
|
||||
if (empty($this->ref))
|
||||
{
|
||||
$this->ref = new ReflectionClass($this);
|
||||
}
|
||||
return $this->ref->newInstance($this->current());
|
||||
}
|
||||
|
||||
private $ref;
|
||||
}
|
||||
|
||||
?>
|
62
ext/spl/internal/recursivefilteriterator.inc
Executable file
62
ext/spl/internal/recursivefilteriterator.inc
Executable file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/** @file recursivefilteriterator.inc
|
||||
* @ingroup SPL
|
||||
* @brief class RecursiveFilterIterator
|
||||
* @author Marcus Boerger
|
||||
* @date 2003 - 2005
|
||||
*
|
||||
* SPL - Standard PHP Library
|
||||
*/
|
||||
|
||||
/** @ingroup SPL
|
||||
* @brief Iterator to filter recursive iterators
|
||||
* @author Marcus Boerger
|
||||
* @version 1.0
|
||||
* @since PHP 5.1
|
||||
*
|
||||
* Passes the RecursiveIterator interface to the inner Iterator and provides
|
||||
* the same functionality as FilterIterator. This allows you to skip parents
|
||||
* and all their childs before loading them all. You need to care about
|
||||
* function getChildren() because it may not always suit your needs. The
|
||||
* builtin behavior uses reflection to return a new instance of the exact same
|
||||
* class it is called from. That is you extend RecursiveFilterIterator and
|
||||
* getChildren() will create instance of that class. The problem is that doing
|
||||
* this does not transport any state or control information of your accept()
|
||||
* implementation to the new instance. To overcome this problem you might
|
||||
* need to overwrite getChildren(), call this implementation and pass the
|
||||
* control vaules manually.
|
||||
*/
|
||||
abstract class RecursiveFilterIterator extends FilterIterator implements RecursiveIterator
|
||||
{
|
||||
/** @param $it the RecursiveIterator to filter
|
||||
*/
|
||||
function __construct(RecursiveIterator $it)
|
||||
{
|
||||
parent::__construct($it);
|
||||
}
|
||||
|
||||
/** @return whether the current element has children
|
||||
*/
|
||||
function hasChildren()
|
||||
{
|
||||
return $this->getInnerIterator()->hasChildren();
|
||||
}
|
||||
|
||||
/** @return an iterator for the current elements children
|
||||
*
|
||||
* @note the returned iterator will be of the same class as $this
|
||||
*/
|
||||
function getChildren()
|
||||
{
|
||||
if (empty($this->ref))
|
||||
{
|
||||
$this->ref = new ReflectionClass($this);
|
||||
}
|
||||
return $this->ref->newInstance($this->getInnerIterator()->getChildren());
|
||||
}
|
||||
|
||||
private $ref;
|
||||
}
|
||||
|
||||
?>
|
118
ext/spl/internal/splobjectstorage.inc
Executable file
118
ext/spl/internal/splobjectstorage.inc
Executable file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/** @file splobjectstorage.inc
|
||||
* @ingroup SPL
|
||||
* @brief class SplObjectStorage
|
||||
* @author Marcus Boerger
|
||||
* @date 2003 - 2005
|
||||
*
|
||||
* SPL - Standard PHP Library
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Object storage
|
||||
* @author Marcus Boerger
|
||||
* @version 1.0
|
||||
* @since PHP 6.0
|
||||
*
|
||||
* This container allows to store objects uniquly without the need to compare
|
||||
* them one by one. This is only possible internally. The code represenation
|
||||
* here therefore has a complexity of O(n) while the actual implementation has
|
||||
* complexity O(1).
|
||||
*/
|
||||
class SplObjectStorage implements Iterator, Countable
|
||||
{
|
||||
private $storage = array();
|
||||
private $index = 0;
|
||||
|
||||
/** Rewind to top iterator as set in constructor
|
||||
*/
|
||||
function rewind()
|
||||
{
|
||||
rewind($this->storage);
|
||||
}
|
||||
|
||||
/** @return whether iterator is valid
|
||||
*/
|
||||
function valid()
|
||||
{
|
||||
return key($this->storage) !== false;
|
||||
}
|
||||
|
||||
/** @return current key
|
||||
*/
|
||||
function key()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/** @return current object
|
||||
*/
|
||||
function current()
|
||||
{
|
||||
return current($this->storage);
|
||||
}
|
||||
|
||||
/** Forward to next element
|
||||
*/
|
||||
function next()
|
||||
{
|
||||
next($this->storage);
|
||||
$this->index++;
|
||||
}
|
||||
|
||||
/** @return number of objects in storage
|
||||
*/
|
||||
function count()
|
||||
{
|
||||
return count($this->storage);
|
||||
}
|
||||
|
||||
/** @param obj object to look for
|
||||
* @return whether $obj is contained in storage
|
||||
*/
|
||||
function contains($obj)
|
||||
{
|
||||
if (is_object($obj))
|
||||
{
|
||||
foreach($this->storage as $object)
|
||||
{
|
||||
if ($object === $obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @param $obj new object to attach to storage if not yet contained
|
||||
*/
|
||||
function attach($obj)
|
||||
{
|
||||
if (is_object($obj) && !$this->contains($obj))
|
||||
{
|
||||
$this->storage[] = $obj;
|
||||
}
|
||||
}
|
||||
|
||||
/** @param $obj object to remove from storage
|
||||
*/
|
||||
function detach($obj)
|
||||
{
|
||||
if (is_object($obj))
|
||||
{
|
||||
foreach($this->storage as $idx => $object)
|
||||
{
|
||||
if ($object === $obj)
|
||||
{
|
||||
unset($this->storage[$idx]);
|
||||
$this->rewind();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
199
ext/spl/tests/observer_002.phpt
Executable file
199
ext/spl/tests/observer_002.phpt
Executable file
@ -0,0 +1,199 @@
|
||||
--TEST--
|
||||
SPL: SplObjectStorage
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class MyObjectStorage extends SplObjectStorage
|
||||
{
|
||||
function rewind()
|
||||
{
|
||||
echo __METHOD__ . "()\n";
|
||||
parent::rewind();
|
||||
}
|
||||
|
||||
function valid()
|
||||
{
|
||||
echo __METHOD__ . "(" . (parent::valid() ? 1 : 0) . ")\n";
|
||||
return parent::valid();
|
||||
}
|
||||
|
||||
function key()
|
||||
{
|
||||
echo __METHOD__ . "(" . parent::key() . ")\n";
|
||||
return parent::key();
|
||||
}
|
||||
|
||||
function current()
|
||||
{
|
||||
echo __METHOD__ . "(" . parent::current()->getName() . ")\n";
|
||||
return parent::current();
|
||||
}
|
||||
|
||||
function next()
|
||||
{
|
||||
echo __METHOD__ . "()\n";
|
||||
parent::next();
|
||||
}
|
||||
}
|
||||
|
||||
class ObserverImpl implements SplObserver
|
||||
{
|
||||
protected $name = '';
|
||||
|
||||
function __construct($name = 'obj')
|
||||
{
|
||||
$this->name = '$' . $name;
|
||||
}
|
||||
|
||||
function update(SplSubject $subject)
|
||||
{
|
||||
echo $this->name . '->' . __METHOD__ . '(' . $subject->getName() . ");\n";
|
||||
}
|
||||
|
||||
function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
class SubjectImpl implements SplSubject
|
||||
{
|
||||
protected $name = '';
|
||||
protected $observers;
|
||||
|
||||
function __construct($name = 'sub')
|
||||
{
|
||||
$this->observers = new MyObjectStorage;
|
||||
$this->name = '$' . $name;
|
||||
}
|
||||
|
||||
function attach(SplObserver $observer)
|
||||
{
|
||||
echo $this->name . '->' . __METHOD__ . '(' . $observer->getName() . ");\n";
|
||||
$this->observers->attach($observer);
|
||||
}
|
||||
|
||||
function detach(SplObserver $observer)
|
||||
{
|
||||
echo $this->name . '->' . __METHOD__ . '(' . $observer->getName() . ");\n";
|
||||
$this->observers->detach($observer);
|
||||
}
|
||||
|
||||
function count()
|
||||
{
|
||||
return $this->observers->count();
|
||||
}
|
||||
|
||||
function notify()
|
||||
{
|
||||
echo $this->name . '->' . __METHOD__ . "();\n";
|
||||
foreach($this->observers as $key => $observer)
|
||||
{
|
||||
$observer->update($this);
|
||||
}
|
||||
}
|
||||
|
||||
function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
function contains($obj)
|
||||
{
|
||||
return $this->observers->contains($obj);
|
||||
}
|
||||
}
|
||||
|
||||
$sub = new SubjectImpl;
|
||||
|
||||
$ob1 = new ObserverImpl("ob1");
|
||||
$ob2 = new ObserverImpl("ob2");
|
||||
$ob3 = new ObserverImpl("ob3");
|
||||
|
||||
var_dump($sub->contains($ob1));
|
||||
$sub->attach($ob1);
|
||||
var_dump($sub->contains($ob1));
|
||||
$sub->attach($ob1);
|
||||
$sub->attach($ob2);
|
||||
$sub->attach($ob3);
|
||||
var_dump($sub->count());
|
||||
|
||||
$sub->notify();
|
||||
|
||||
$sub->detach($ob3);
|
||||
var_dump($sub->count());
|
||||
|
||||
$sub->notify();
|
||||
|
||||
$sub->detach($ob2);
|
||||
$sub->detach($ob1);
|
||||
var_dump($sub->count());
|
||||
|
||||
$sub->notify();
|
||||
|
||||
$sub->attach($ob3);
|
||||
var_dump($sub->count());
|
||||
|
||||
$sub->notify();
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
<?php exit(0); ?>
|
||||
--EXPECT--
|
||||
bool(false)
|
||||
$sub->SubjectImpl::attach($ob1);
|
||||
bool(true)
|
||||
$sub->SubjectImpl::attach($ob1);
|
||||
$sub->SubjectImpl::attach($ob2);
|
||||
$sub->SubjectImpl::attach($ob3);
|
||||
int(3)
|
||||
$sub->SubjectImpl::notify();
|
||||
MyObjectStorage::rewind()
|
||||
MyObjectStorage::valid(1)
|
||||
MyObjectStorage::current($ob1)
|
||||
MyObjectStorage::key(0)
|
||||
$ob1->ObserverImpl::update($sub);
|
||||
MyObjectStorage::next()
|
||||
MyObjectStorage::valid(1)
|
||||
MyObjectStorage::current($ob2)
|
||||
MyObjectStorage::key(1)
|
||||
$ob2->ObserverImpl::update($sub);
|
||||
MyObjectStorage::next()
|
||||
MyObjectStorage::valid(1)
|
||||
MyObjectStorage::current($ob3)
|
||||
MyObjectStorage::key(2)
|
||||
$ob3->ObserverImpl::update($sub);
|
||||
MyObjectStorage::next()
|
||||
MyObjectStorage::valid(0)
|
||||
$sub->SubjectImpl::detach($ob3);
|
||||
int(2)
|
||||
$sub->SubjectImpl::notify();
|
||||
MyObjectStorage::rewind()
|
||||
MyObjectStorage::valid(1)
|
||||
MyObjectStorage::current($ob1)
|
||||
MyObjectStorage::key(0)
|
||||
$ob1->ObserverImpl::update($sub);
|
||||
MyObjectStorage::next()
|
||||
MyObjectStorage::valid(1)
|
||||
MyObjectStorage::current($ob2)
|
||||
MyObjectStorage::key(1)
|
||||
$ob2->ObserverImpl::update($sub);
|
||||
MyObjectStorage::next()
|
||||
MyObjectStorage::valid(0)
|
||||
$sub->SubjectImpl::detach($ob2);
|
||||
$sub->SubjectImpl::detach($ob1);
|
||||
int(0)
|
||||
$sub->SubjectImpl::notify();
|
||||
MyObjectStorage::rewind()
|
||||
MyObjectStorage::valid(0)
|
||||
$sub->SubjectImpl::attach($ob3);
|
||||
int(1)
|
||||
$sub->SubjectImpl::notify();
|
||||
MyObjectStorage::rewind()
|
||||
MyObjectStorage::valid(1)
|
||||
MyObjectStorage::current($ob3)
|
||||
MyObjectStorage::key(0)
|
||||
$ob3->ObserverImpl::update($sub);
|
||||
MyObjectStorage::next()
|
||||
MyObjectStorage::valid(0)
|
||||
===DONE===
|
Loading…
Reference in New Issue
Block a user