<?php
/**
* PHP VoiceViewer - Channel Class
*
* Channel Entity
*
* Project : PHP VoiceViewer
* Copyright : Christopher Cooper © 2010
* License : FreeBSD
* Author : Christopher Cooper (PaNtHaLooN), hide@address.com
* Date : March 2010
* Version : 1.0.0
*
* Copyright 2010 Christopher Cooper. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY CHRISTOPHER COOPER ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CHRISTOPHER COOPER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of Christopher Cooper.
*/
// Define acronyms
defined('DS') || define('DS', DIRECTORY_SEPARATOR);
// Main include
@require_once(dirname(__FILE__) . DS . '..' . DS . 'main.inc.php');
final class vvChannel extends avvEntity implements ivvChannel
{
const ELEMENT_CHANNELS = 'channels';
const ELEMENT_USERS = 'users';
private static $_proplist = array( 'id' => self::PROP_INIT_NOCDATA,
'name' => self::PROP_INIT,
'default' => self::PROP_NOCDATA,
'sortorder' => self::PROP_NOCDATA,
'temporary' => self::PROP_NOCDATA,
'private' => self::PROP_NOCDATA,
'moderated' => self::PROP_NOCDATA,
'url' => self::PROP_VALUE,
'description' => self::PROP_VALUE,
self::ELEMENT_CHANNELS => self::PROP_IGNORE,
self::ELEMENT_USERS => self::PROP_IGNORE
);
private static $_xpath_channels = null;
private static $_xpath_users = null;
private $_regchannels = array();
private $_regusers = array();
private $_channels = array();
private $_users = array();
private $_parent = null;
public function __construct( &$data )
{
// Call parent constructor;
parent::__construct(self::$_proplist, $data);
if ( self::$_xpath_channels === null )
{
self::$_xpath_channels = './' . self::ELEMENT_CHANNELS . '/' . self::ELEMENT_NAME;
self::$_xpath_users = './' . self::ELEMENT_USERS . '/' . ivvUser::ELEMENT_NAME;
}
if ( $root =& vv::transformToDOMElement($data) !== null )
{
$xpath = new DOMXPath($root->ownerDocument);
foreach( $xpath->query(self::$_xpath_channels, $root) as $channel )
{
$this->appendChannel(new vvChannel($channel));
}
foreach( $xpath->query(self::$_xpath_users, $root) as $user )
{
$this->appendUser(new vvUser($user));
}
}
$this->registerChannel($this);
}
public function getElementName()
{
return self::ELEMENT_NAME;
}
public function &createDOMElement( DOMDocument &$doc )
{
$element =& parent::createDOMElement($doc);
if ( $this->hasChannels() )
{
$channels = $element->appendChild($doc->createElement(self::ELEMENT_CHANNELS));
foreach( $this->_channels as &$sub )
{
$channels->appendChild($sub->createDOMElement($doc));
}
}
if ( $this->hasUsers() )
{
$users = $element->appendChild($doc->createElement(self::ELEMENT_USERS));
foreach( $this->_users as &$user )
{
$users->appendChild($user->createDOMElement($doc));
}
}
return $element;
}
private function setParent( ivvChannel &$parent = null )
{
// First set reference to parent
$this->_parent =& $parent;
if ( $this->_parent !== null )
{
$regto =& $this->_parent;
// In case this was a filled base channel remove regdata
if ( count($this->_regchannels) > 0 )
{
$this->_regchannels = array();
}
if ( count($this->_regusers) > 0 )
{
$this->_regusers = array();
}
}
else
{
$regto =& $this;
}
// NOTE: Channel/Users can only be added once -> To move unregister frist
$regto->registerChannel($this);
foreach( $this->_users as &$user )
{
$regto->registerUser($user);
}
foreach( $this->_channels as &$channel )
{
$channel->setParent($this);
}
}
public function &getParent()
{
return $this->_parent;
}
public function &appendChannel( &$input )
{
if ( is_array($input) )
{
$channel =& new vvChannel($input);
}
else if ( $input instanceof ivvChannel )
{
$channel =& $input;
}
else
{
throw new vvException('CHANNEL_APPENDCHANNEL_INVALID_ARG');
}
$channel->setParent($this);
return $this->_channels[$channel->getID()] =& $channel;
}
public function &appendUser( &$input )
{
if ( is_array($input) )
{
$user =& new vvUser($input);
}
else if ( $input instanceof ivvUser )
{
$user =& $input;
}
else
{
throw new vvException('CHANNEL_APPENDUSER_INVALID_ARG');
}
$this->registerUser($user);
$user->setParent($this);
return $this->_users[$user->getID()] =& $user;
}
public function hasChannels()
{
if ( count($this->_channels) > 0 )
{
return true;
}
return false;
}
public function hasUsers( $recursive = false )
{
if ( count($this->_users) > 0 )
{
return true;
}
if ( $recursive && (count($this->_channels) > 0) )
{
foreach( $this->_channels as &$channel )
{
if ( $channel->hasUsers(true) )
{
return true;
}
}
}
return false;
}
public function channelExists( $id, $local = true )
{
if ( $local === true )
{
return array_key_exists($id, $this->_channels);
}
else if ( $local === false )
{
if ( $this->_parent !== null )
{
return $this->_parent->channelExists($id, false);
}
return array_key_exists($id, $this->_regchannels);
}
else
{
throw new vvException('CHANNEL_CHANNELEXISTS_INVALID_ARG');
}
}
public function userExists( $id, $local = true )
{
if ( $local === true )
{
return array_key_exists($id, $this->_users);
}
else if ( $local === false )
{
if ( $this->_parent !== null )
{
return $this->_parent->userExists($id, false);
}
return array_key_exists($id, $this->_regusers);
}
else
{
throw new vvException('CHANNEL_USEREXISTS_INVALID_ARG');
}
}
public function &getChannel( $id )
{
$result = null;
if ( $this->_parent !== null )
{
$result = $this->_parent->getChannel($id);
}
if ( !array_key_exists($id, $this->_regchannels) )
{
if ( vv::isDebug() )
{
throw new vvException('CHANNEL_GET_UNKNOWN_CHANNEL', 0, $id);
}
}
else
{
$result = $this->_regchannels[$id];
}
return $result;
}
public function &getChannels()
{
return $this->_channels;
}
public function &getUser( $id )
{
$result = null;
if ( $this->_parent !== null )
{
$result = $this->_parent->getUser($id);
}
if ( !array_key_exists($id, $this->_regusers) )
{
if ( vv::isDebug() )
{
throw new vvException('CHANNEL_GET_UNKNOWN_USER', 0, $id);
}
}
else
{
$result = $this->_regusers[$id];
}
return $result;
}
public function &getUsers()
{
return $this->_users;
}
public function &removeChannel( $id, $remove = true )
{
if ( !array_key_exists($id, $this->_channels) )
{
throw new vvException('CHANNEL_REMOVE_UNKNOWN_CHANNEL', 0, $id, $thid->id);
}
$remchannel =& $this->_channels[$id];
foreach( $remchannel->_channels as &$channel )
{
$remchannel->removeChannel($channel->getID(), false);
}
$this->unregisterChannel($id);
foreach( $remchannel->_users as &$user )
{
$this->unregisterUser($user->getID(), false);
}
if ( $remove )
{
unset($this->_channels[$id]);
$remchannel->setParent();
}
return $remchannel;
}
public function &removeUser( $id, $remove = true )
{
if ( !array_key_exists($id, $this->_users) )
{
throw new vvException('CHANNEL_REMOVE_UNKNOWN_USER', 0, $id, $this->id);
}
$remuser =& $this->_users[$id];
$this->unregisterUser($id);
if ( $remove )
{
unset($this->_users[$id]);
$remuser->setParent();
}
return $remuser;
}
private function registerChannel( ivvChannel &$channel )
{
if ( $this->_parent !== null )
{
$this->_parent->registerChannel($channel);
}
else
{
$id = $channel->getID();
if ( $this->channelExists($id, false) )
{
throw new vvException('CHANNEL_REGISTER_CHANNEL_DUPLICATE', 0, $id);
}
$this->_regchannels[$id] =& $channel;
}
}
private function unregisterChannel( $id )
{
if ( $this->_parent !== null )
{
$this->_parent->unregisterChannel($id);
}
else
{
unset($this->_regchannels[$id]);
}
}
private function registerUser( ivvUser &$user )
{
if ( $this->_parent !== null )
{
$this->_parent->registerUser($user);
}
else
{
$id = $user->getID();
if ( $this->userExists($id, false) )
{
throw new vvException('CHANNEL_REGISTER_USER_DUPLICATE', 0, $id);
}
$this->_regusers[$id] =& $user;
}
}
/** Removes user from root channel's user list. Internal method only.
*/
private function unregisterUser( $id )
{
if ( $this->_parent !== null )
{
$this->_parent->unregisterUser($id);
}
else
{
unset($this->_regusers[$id]);
}
}
public function getID()
{
return ($this->id == '-1') ? 'vv:' . spl_object_hash($this) : $this->id;
}
}
?>