Mantis Bugtracker
  

Viewing Issue Advanced Details Jump to Notes ] View Simple ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0003230 [Quercus] major always 01-09-09 07:41 01-15-09 18:10
Reporter haplo View Status public  
Assigned To ferg
Priority normal Resolution fixed Platform
Status closed   OS
Projection none   OS Version
ETA none Fixed in Version 4.0.0 Product Version 3.2.1
  Product Build
Summary 0003230: instanceof does not include interface hierarchy
Description Hi everyone,

i am trying hard to get PRADO running on resin and i found a nasty bug.

The Traversable interface is extended by the IteratorAggregate, but if i implement the IteratorAggregate interface (i.e. IteratorAggregateImpl ) the following test fails!


$impl = new IteratorAggregateImpl();
$impl instanceof Traversable; // is false on quercus and true on apache

Try this code on quercus and apache.


<?php

class MyMap implements IteratorAggregate,ArrayAccess,Countable
{
/**
* @var array internal data storage
*/
private $_d=array();
/**
* @var boolean whether this list is read-only
*/
private $_r=false;

/**
* Constructor.
* Initializes the list with an array or an iterable object.
* @param array|Iterator the intial data. Default is null, meaning no initialization.
* @param boolean whether the list is read-only
* @throws TInvalidDataTypeException If data is not null and neither an array nor an iterator.
*/
public function __construct($data=null,$readOnly=false)
{
if($data!==null) {
$this->copyFrom($data);
}
$this->setReadOnly($readOnly);
}

/**
* @return boolean whether this map is read-only or not. Defaults to false.
*/
public function getReadOnly()
{
return $this->_r;
}

/**
* @param boolean whether this list is read-only or not
*/
protected function setReadOnly($value)
{
$this->_r=$value ;
}

/**
* Returns an iterator for traversing the items in the list.
* This method is required by the interface IteratorAggregate.
* @return Iterator an iterator for traversing the items in the list.
*/
public function getIterator()
{
return new TMapIterator($this->_d);
}

/**
* Returns the number of items in the map.
* This method is required by Countable interface.
* @return integer number of items in the map.
*/
public function count()
{
return $this->getCount();
}

/**
* @return integer the number of items in the map
*/
public function getCount()
{
return count($this->_d);
}

/**
* @return array the key list
*/
public function getKeys()
{
return array_keys($this->_d);
}

/**
* Returns the item with the specified key.
* This method is exactly the same as {@link offsetGet}.
* @param mixed the key
* @return mixed the element at the offset, null if no element is found at the offset
*/
public function itemAt($key)
{
return isset($this->_d[$key]) ? $this->_d[$key] : null;
}

/**
* Adds an item into the map.
* Note, if the specified key already exists, the old value will be overwritten.
* @param mixed key
* @param mixed value
* @throws TInvalidOperationException if the map is read-only
*/
public function add($key,$value)
{
if(!$this->_r)
$this->_d[$key]=$value;
}

/**
* Removes an item from the map by its key.
* @param mixed the key of the item to be removed
* @return mixed the removed value, null if no such key exists.
* @throws TInvalidOperationException if the map is read-only
*/
public function remove($key)
{
if(!$this->_r)
{
if(isset($this->_d[$key]) || array_key_exists($key,$this->_d))
{
$value=$this->_d[$key];
unset($this->_d[$key]);
return $value;
}
else
return null;
}
}

/**
* Removes all items in the map.
*/
public function clear()
{
foreach(array_keys($this->_d) as $key)
$this->remove($key);
}

/**
* @param mixed the key
* @return boolean whether the map contains an item with the specified key
*/
public function contains($key)
{
return isset($this->_d[$key]) || array_key_exists($key,$this->_d);
}

/**
* @return array the list of items in array
*/
public function toArray()
{
return $this->_d;
}

/**
* Copies iterable data into the map.
* Note, existing data in the map will be cleared first.
* @param mixed the data to be copied from, must be an array or object implementing Traversable
* @throws TInvalidDataTypeException If data is neither an array nor an iterator.
*/
public function copyFrom($data)
{
if(is_array($data) || $data instanceof IteratorAggregate || $data instanceof Iterator)
{
if($this->getCount()>0) {
$this->clear();
}
foreach($data as $key=>$value) {
$this->add($key,$value);
}
}
}

/**
* Merges iterable data into the map.
* Existing data in the map will be kept and overwritten if the keys are the same.
* @param mixed the data to be merged with, must be an array or object implementing Traversable
* @throws TInvalidDataTypeException If data is neither an array nor an iterator.
*/
public function mergeWith($data)
{
if(is_array($data) || $data instanceof IteratorAggregate || $data instanceof Iterator)
{
foreach($data as $key=>$value)
$this->add($key,$value);
}
else if($data!==null)
throw new TInvalidDataTypeException('map_data_not_iterable');
}

/**
* Returns whether there is an element at the specified offset.
* This method is required by the interface ArrayAccess.
* @param mixed the offset to check on
* @return boolean
*/
public function offsetExists($offset)
{
return $this->contains($offset);
}

/**
* Returns the element at the specified offset.
* This method is required by the interface ArrayAccess.
* @param integer the offset to retrieve element.
* @return mixed the element at the offset, null if no element is found at the offset
*/
public function offsetGet($offset)
{
return $this->itemAt($offset);
}

/**
* Sets the element at the specified offset.
* This method is required by the interface ArrayAccess.
* @param integer the offset to set element
* @param mixed the element value
*/
public function offsetSet($offset,$item)
{
$this->add($offset,$item);
}

/**
* Unsets the element at the specified offset.
* This method is required by the interface ArrayAccess.
* @param mixed the offset to unset element
*/
public function offsetUnset($offset)
{
$this->remove($offset);
}
}

/**
* TMapIterator class
*
* TMapIterator implements Iterator interface.
*
* TMapIterator is used by TMap. It allows TMap to return a new iterator
* for traversing the items in the map.
*
* @author Qiang Xue
* @version $Id: TMap.php 1398 2006-09-08 19:31:03Z xue $
* @package System.Collections
* @since 3.0
*/
class TMapIterator implements Iterator
{
/**
* @var array the data to be iterated through
*/
private $_d;
/**
* @var array list of keys in the map
*/
private $_keys;
/**
* @var mixed current key
*/
private $_key;

/**
* Constructor.
* @param array the data to be iterated through
*/
public function __construct(&$data)
{
$this->_d=&$data;
$this->_keys=array_keys($data);
}

/**
* Rewinds internal array pointer.
* This method is required by the interface Iterator.
*/
public function rewind()
{
$this->_key=reset($this->_keys);
}

/**
* Returns the key of the current array element.
* This method is required by the interface Iterator.
* @return mixed the key of the current array element
*/
public function key()
{
return $this->_key;
}

/**
* Returns the current array element.
* This method is required by the interface Iterator.
* @return mixed the current array element
*/
public function current()
{
return $this->_d[$this->_key];
}

/**
* Moves the internal pointer to the next array element.
* This method is required by the interface Iterator.
*/
public function next()
{
$this->_key=next($this->_keys);
}

/**
* Returns whether there is an element at current position.
* This method is required by the interface Iterator.
* @return boolean
*/
public function valid()
{
return $this->_key!==false;
}
}

$array = new MyMap();

echo ($array instanceof Traversable ? ' MyMap is instance of Traversable ' : ' MyMap is NOT instance of Traversable ' );
echo ($array instanceof IteratorAggregate ? ' MyMap is instance of IteratorAggregate ' : ' MyMap is NOT instance of IteratorAggregate ' );
echo ($array instanceof Iterator ? ' MyMap is instance of Iterator ' : ' MyMap is NOT instance of Iterator ' );

The result on quercus is:

MyMap is NOT instance of Traversable
MyMap is instance of IteratorAggregate
MyMap is NOT instance of Iterator

The result on apache:

MyMap is instance of Traversable
MyMap is instance of IteratorAggregate
MyMap is NOT instance of Iterator

i used the resin 3.2.1 binary from the website
Steps To Reproduce
Additional Information
Attached Files

- Relationships

- Notes
(0003742)
ferg
01-15-09 18:10

php/4as6
 

- Issue History
Date Modified Username Field Change
01-09-09 07:41 haplo New Issue
01-15-09 18:10 ferg Note Added: 0003742
01-15-09 18:10 ferg Assigned To  => ferg
01-15-09 18:10 ferg Status new => closed
01-15-09 18:10 ferg Resolution open => fixed
01-15-09 18:10 ferg Fixed in Version  => 4.0.0


Mantis 1.0.0rc3[^]
Copyright © 2000 - 2005 Mantis Group
29 total queries executed.
26 unique queries executed.
Powered by Mantis Bugtracker