* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
abstract class Zend_Media_Asf_Object_Container extends Zend_Media_Asf_Object
{
/** @var Array */
private $_objects = array();
/**
* Reads and constructs the objects found within this object.
*/
protected final function constructObjects($defaultclassnames = array())
{
while (true) {
$offset = $this->_reader->getOffset();
if ($offset >= $this->getOffset() + $this->getSize()) {
break;
}
$guid = $this->_reader->readGuid();
$size = $this->_reader->readInt64LE();
$this->_reader->setOffset($offset);
if (isset($defaultclassnames[$guid])) {
if (@fopen($filename = 'Zend/Media/Asf/Object/' .
$defaultclassnames[$guid] . '.php',
'r', true) !== false) {
require_once($filename);
}
if (class_exists
($classname = 'Zend_Media_Asf_Object_' .
$defaultclassnames[$guid])) {
$object = new $classname($this->_reader, $this->_options);
} else {
require_once 'Zend/Media/Asf/Object/Unknown.php';
$object = new Zend_Media_Asf_Object_Unknown
($this->_reader, $this->_options);
}
} else {
require_once 'Zend/Media/Asf/Object/Unknown.php';
$object = new Zend_Media_Asf_Object_Unknown
($this->_reader, $this->_options);
}
$object->setParent($this);
if (!$this->hasObject($object->getIdentifier())) {
$this->_objects[$object->getIdentifier()] = array();
}
$this->_objects[$object->getIdentifier()][] = $object;
$this->_reader->setOffset($offset + $size);
}
}
/**
* Checks whether the object with given identifier is present in the file.
* The identifier can either be the object GUID, or name of the constant
* containing the GUID, or the name of the object class.
*
* Returns true if one or more objects are present,
* false otherwise.
*
* @param string $identifier The object GUID, name of the GUID constant, or
* object class name.
* @return boolean
*/
public final function hasObject($identifier)
{
if (defined($constname = get_class($this) . '::' . strtoupper
(preg_replace('/[A-Z]/', '_$0', $identifier)))) {
$objects = $this->getObjectsByIdentifier(constant($constname));
return isset($objects[0]);
} else {
return isset($this->_objects[$identifier]);
}
}
/**
* Returns all the objects the file contains as an associate array. The
* object identifiers work as keys having an array of ASF objects as
* associated value.
*
* @return Array
*/
public final function getObjects()
{
return $this->_objects;
}
/**
* Returns an array of objects matching the given object GUID or an empty
* array if no object matched the identifier.
*
* The identifier may contain wildcard characters '*' and '?'. The asterisk
* matches against zero or more characters, and the question mark matches
* any single character.
*
* @param string $identifier The object GUID.
* @return Array
*/
public final function getObjectsByIdentifier($identifier)
{
$matches = array();
$searchPattern = '/^' .
str_replace(array("*", "?"), array(".*", "."), $identifier) . "$/i";
foreach ($this->_objects as $identifier => $objects) {
if (preg_match($searchPattern, $identifier)) {
foreach ($objects as $object) {
$matches[] = $object;
}
}
}
return $matches;
}
/**
* Returns an array of objects matching the given object constant name or an
* empty array if no object matched the name.
*
* The object constant name can be given in three forms; either using the
* full name of the constant, the name of the class or the shorthand style
* of the class name having its first letter in lower case.
*
* One may use the shorthand $obj->name to access the first box with the
* name given directly. Shorthands will not work with user defined uuid
* types.
*
* The name may not contain wildcard characters.
*
* @param string $name The object constant name or class name.
* @return Array
*/
public final function getObjectsByName($name)
{
if (defined($constname = get_class($this) . '::' . $name) ||
defined($constname = get_class($this) . '::' . strtoupper
(preg_replace
('/^_/', '', preg_replace('/[A-Z]/', '_$0', $name))))) {
return $this->getObjectsByIdentifier(constant($constname));
}
return array();
}
/**
* Removes any objects matching the given object GUID.
*
* The identifier may contain wildcard characters '*' and '?'. The asterisk
* matches against zero or more characters, and the question mark matches
* any single character.
*
* One may also use the shorthand unset($obj->name) to achieve the same
* result. Wildcards cannot be used with the shorthand method.
*
* @param string $identifier The object GUID.
*/
public final function removeObjectsByIdentifier($identifier)
{
$searchPattern = '/^' .
str_replace(array("*", "?"), array(".*", "."), $identifier) . "$/i";
foreach ($this->_objects as $identifier => $objects) {
if (preg_match($searchPattern, $identifier)) {
unset($this->_objects[$identifier]);
}
}
}
/**
* Removes any objects matching the given object name.
*
* The name can be given in three forms; either using the full name of the
* constant, the name of the class or the shorthand style of the class name
* having its first letter in lower case.
*
* One may also use the shorthand unset($obj->name) to achieve the same
* result.
*
* The name may not contain wildcard characters.
*
* @param string $name The object constant name or class name.
*/
public final function removeObjectsByName($name)
{
if (defined($constname = get_class($this) . '::' . strtoupper
(preg_replace('/[A-Z]/', '_$0', $name)))) {
unset($this->_objects[constant($constname)]);
}
}
/**
* Adds a new object into the current object and returns it.
*
* @param Zend_Media_Asf_Object $object The object to add
* @return Zend_Media_Asf_Object
*/
public final function addObject($object)
{
$object->setParent($this);
$object->setOptions($this->_options);
if (!$this->hasObject($object->getIdentifier())) {
$this->_objects[$object->getIdentifier()] = array();
}
return $this->_objects[$object->getIdentifier()][] = $object;
}
/**
* Removes the object.
*
* @param Zend_Media_Asf_Object $object The object to remove
*/
public final function removeObject($object)
{
if ($this->hasObject($object->getIdentifier())) {
foreach ($this->_objects
[$object->getIdentifier()] as $key => $value) {
if ($object === $value) {
unset($this->_objects[$object->getIdentifier()][$key]);
}
}
}
}
/**
* Returns the number of objects this container has.
*
* @return integer
*/
public final function getObjectCount()
{
return count($this->_objects);
}
/**
* Override magic function so that $obj->value will work as expected.
*
* The method first attempts to call the appropriate getter method. If no
* field with given name is found, the method attempts to return the right
* object instead. In other words, calling $obj->value will attempt to
* return the first object returned by
* $this->getObjectsByIdentifier(self::value). If no object is found by the
* given value, a respective class name is tried to instantiate and add to
* the container.
*
* @param string $name The field or object name.
* @return mixed
*/
public function __get($name)
{
if (method_exists($this, 'get' . ucfirst($name))) {
return call_user_func(array($this, 'get' . ucfirst($name)));
}
if (method_exists($this, 'is' . ucfirst($name))) {
return call_user_func(array($this, 'is' . ucfirst($name)));
}
if (defined($constname = get_class($this) . '::' . strtoupper
(preg_replace('/[A-Z]/', '_$0', $name)))) {
$objects = $this->getObjectsByIdentifier(constant($constname));
if (isset($objects[0])) {
return $objects[0];
} else {
if (@fopen($filename = 'Zend/Media/Asf/Object/' .
ucfirst($name) . '.php', 'r', true) !== false) {
require_once($filename);
}
if (class_exists
($classname = 'Zend_Media_Asf_Object_' . ucfirst($name))) {
$obj = new $classname();
$obj->setIdentifier(constant($constname));
return $this->addObject($obj);
}
}
}
require_once 'Zend/Media/Asf/Exception.php';
throw new Zend_Media_Asf_Exception('Unknown field/object: ' . $name);
}
/**
* Override magic function so that $obj->value will work as expected.
*
* The method first attempts to call the appropriate setter method. If no
* field with given name is found, the method attempts to set the right
* object instead. In other words, assigning to $obj->value will attempt to
* set the object with given value's identifier.
*
* Please note that using this method will override any prior objects having
* the same object identifier.
*
* @param string $name The field or object name.
* @param string $value The field value or object.
* @return mixed
*/
public function __set($name, $value)
{
if (method_exists($this, 'set' . ucfirst($name))) {
call_user_func(array($this, 'set' . ucfirst($name)), $value);
}
if (defined($constname = get_class($this) . '::' . strtoupper
(preg_replace('/[A-Z]/', '_$0', $name)))) {
$value->setOptions($this->_options);
$this->_objects[constant($constname)] = array($value);
} else {
require_once 'Zend/Media/Asf/Exception.php';
throw new Zend_Media_Asf_Exception
('Unknown field/object: ' . $name);
}
}
/**
* Magic function so that isset($obj->value) will work. This method checks
* whether the object by given identifier or name is contained by this
* container.
*
* @param string $name The object identifier or logical name.
* @return boolean
*/
public function __isset($name)
{
return $this->hasObject($name);
}
/**
* Magic function so that unset($obj->value) will work. This method removes
* all the objects with the given identifier or name.
*
* @param string $name The object identifier or logical name.
*/
public function __unset($name)
{
$this->removeObjectsByName($name);
}
}