egroupware/phpgwapi/inc/xajax/xajax_core/xajaxControl.inc.php
2010-01-07 23:33:20 +00:00

683 lines
17 KiB
PHP

<?php
/*
File: xajaxControl.inc.php
Contains the base class for all controls.
Title: xajaxControl class
Please see <copyright.inc.php> for a detailed description, copyright
and license information.
*/
/*
@package xajax
@version $Id: xajaxControl.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $
@copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
@copyright Copyright (c) 2008-2009 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson
@license http://www.xajaxproject.org/bsd_license.txt BSD License
*/
/*
Constant: XAJAX_HTML_CONTROL_DOCTYPE_FORMAT
Defines the doctype of the current document; this will effect how the HTML is formatted
when the html control library is used to construct html documents and fragments. This can
be one of the following values:
'XHTML' - (default) Typical effects are that certain elements are closed with '/>'
'HTML' - Typical differences are that closing tags for certain elements cannot be '/>'
*/
if (false == defined('XAJAX_HTML_CONTROL_DOCTYPE_FORMAT')) define('XAJAX_HTML_CONTROL_DOCTYPE_FORMAT', 'XHTML');
/*
Constant: XAJAX_HTML_CONTROL_DOCTYPE_VERSION
*/
if (false == defined('XAJAX_HTML_CONTROL_DOCTYPE_VERSION')) define('XAJAX_HTML_CONTROL_DOCTYPE_VERSION', '1.0');
/*
Constant: XAJAX_HTML_CONTROL_DOCTYPE_VALIDATION
*/
if (false == defined('XAJAX_HTML_CONTROL_DOCTYPE_VALIDATION')) define('XAJAX_HTML_CONTROL_DOCTYPE_VALIDATION', 'TRANSITIONAL');
/*
Class: xajaxControl
The base class for all xajax enabled controls. Derived classes will generate the
HTML and javascript code that will be sent to the browser via <xajaxControl->printHTML>
or sent to the browser in a <xajaxResponse> via <xajaxControl->getHTML>.
*/
class xajaxControl
{
/*
String: sTag
*/
var $sTag;
/*
Boolean: sEndTag
'required' - (default) Indicates the control must have a full end tag
'optional' - The control may have an abbr. begin tag or a full end tag
'forbidden' - The control must have an abbr. begin tag and no end tag
*/
var $sEndTag;
/*
Array: aAttributes
An associative array of attributes that will be used in the generation
of the HMTL code for this control.
*/
var $aAttributes;
/*
Array: aEvents
An associative array of events that will be assigned to this control. Each
event declaration will include a reference to a <xajaxRequest> object; it's
script will be extracted using <xajaxRequest->printScript> or
<xajaxRequest->getScript>.
*/
var $aEvents;
/*
String: sClass
Contains a declaration of the class of this control. %inline controls do not
need to be indented, %block controls should be indented.
*/
var $sClass;
/*
Function: xajaxControl
Parameters:
$aConfiguration - (array): An associative array that contains a variety
of configuration options for this <xajaxControl> object.
Note:
This array may contain the following entries:
'attributes' - (array): An associative array containing attributes
that will be passed to the <xajaxControl->setAttribute> function.
'children' - (array): An array of <xajaxControl> derived objects that
will be the children of this control.
*/
function xajaxControl($sTag, $aConfiguration=array())
{
$this->sTag = $sTag;
$this->clearAttributes();
if (isset($aConfiguration['attributes']))
if (is_array($aConfiguration['attributes']))
foreach ($aConfiguration['attributes'] as $sKey => $sValue)
$this->setAttribute($sKey, $sValue);
$this->clearEvents();
if (isset($aConfiguration['event']))
call_user_func_array(array(&$this, 'setEvent'), $aConfiguration['event']);
else if (isset($aConfiguration['events']))
if (is_array($aConfiguration['events']))
foreach ($aConfiguration['events'] as $aEvent)
call_user_func_array(array(&$this, 'setEvent'), $aEvent);
$this->sClass = '%block';
$this->sEndTag = 'forbidden';
}
/*
Function: getClass
Returns the *adjusted* class of the element
*/
function getClass()
{
return $this->sClass;
}
/*
Function: clearAttributes
Removes all attributes assigned to this control.
*/
function clearAttributes()
{
$this->aAttributes = array();
}
/*
Function: setAttribute
Call to set various control specific attributes to be included in the HTML
script that is returned when <xajaxControl->printHTML> or <xajaxControl->getHTML>
is called.
Parameters:
$sName - (string): The attribute name to set the value.
$sValue - (string): The value to be set.
*/
function setAttribute($sName, $sValue)
{
//SkipDebug
if (class_exists('clsValidator'))
{
$objValidator =& clsValidator::getInstance();
if (false == $objValidator->attributeValid($this->sTag, $sName)) {
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:IAERR:01')
. $sName
. $objLanguageManager->getText('XJXCTL:IAERR:02')
. $this->sTag
. $objLanguageManager->getText('XJXCTL:IAERR:03')
, E_USER_ERROR
);
}
}
//EndSkipDebug
$this->aAttributes[$sName] = $sValue;
}
/*
Function: getAttribute
Call to obtain the value currently associated with the specified attribute
if set.
Parameters:
sName - (string): The name of the attribute to be returned.
Returns:
mixed : The value associated with the attribute, or null.
*/
function getAttribute($sName)
{
if (false == isset($this->aAttributes[$sName]))
return null;
return $this->aAttributes[$sName];
}
/*
Function: clearEvents
Clear the events that have been associated with this object.
*/
function clearEvents()
{
$this->aEvents = array();
}
/*
Function: setEvent
Call this function to assign a <xajaxRequest> object as the handler for
the specific DOM event. The <xajaxRequest->printScript> function will
be called to generate the javascript for this request.
Parameters:
sEvent - (string): A string containing the name of the event to be assigned.
objRequest - (xajaxRequest object): The <xajaxRequest> object to be associated
with the specified event.
aParameters - (array, optional): An array containing parameter declarations
that will be passed to this <xajaxRequest> object just before the javascript
is generated.
sBeforeRequest - (string, optional): a string containing a snippet of javascript code
to execute prior to calling the xajaxRequest function
sAfterRequest - (string, optional): a string containing a snippet of javascript code
to execute after calling the xajaxRequest function
*/
function setEvent($sEvent, &$objRequest, $aParameters=array(), $sBeforeRequest='', $sAfterRequest='; return false;')
{
//SkipDebug
if (false == is_a($objRequest, 'xajaxRequest')) {
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:IRERR:01')
. $this->backtrace()
, E_USER_ERROR
);
}
if (class_exists('clsValidator')) {
$objValidator =& clsValidator::getInstance();
if (false == $objValidator->attributeValid($this->sTag, $sEvent)) {
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:IEERR:01')
. $sEvent
. $objLanguageManager->getText('XJXCTL:IEERR:02')
. $this->sTag
. $objLanguageManager->getText('XJXCTL:IEERR:03')
, E_USER_ERROR
);
}
}
//EndSkipDebug
$this->aEvents[$sEvent] = array(
&$objRequest,
$aParameters,
$sBeforeRequest,
$sAfterRequest
);
}
/*
Function: getHTML
Generates and returns the HTML representation of this control and
it's children.
Returns:
string : The HTML representation of this control.
*/
function getHTML($bFormat=false)
{
ob_start();
if ($bFormat)
$this->printHTML();
else
$this->printHTML(false);
return ob_get_clean();
}
/*
Function: printHTML
Generates and prints the HTML representation of this control and
it's children.
Returns:
string : The HTML representation of this control.
*/
function printHTML($sIndent='')
{
//SkipDebug
if (class_exists('clsValidator'))
{
$objValidator =& clsValidator::getInstance();
$sMissing = '';
if (false == $objValidator->checkRequiredAttributes($this->sTag, $this->aAttributes, $sMissing)) {
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:MAERR:01')
. $sMissing
. $objLanguageManager->getText('XJXCTL:MAERR:02')
. $this->sTag
. $objLanguageManager->getText('XJXCTL:MAERR:03')
, E_USER_ERROR
);
}
}
//EndSkipDebug
$sClass = $this->getClass();
if ('%inline' != $sClass)
// this odd syntax is necessary to detect request for no formatting
if (false === (false === $sIndent))
echo $sIndent;
echo '<';
echo $this->sTag;
echo ' ';
$this->_printAttributes();
$this->_printEvents();
if ('forbidden' == $this->sEndTag)
{
if ('HTML' == XAJAX_HTML_CONTROL_DOCTYPE_FORMAT)
echo '>';
else if ('XHTML' == XAJAX_HTML_CONTROL_DOCTYPE_FORMAT)
echo '/>';
if ('%inline' != $sClass)
// this odd syntax is necessary to detect request for no formatting
if (false === (false === $sIndent))
echo "\n";
return;
}
else if ('optional' == $this->sEndTag)
{
echo '/>';
if ('%inline' == $sClass)
// this odd syntax is necessary to detect request for no formatting
if (false === (false === $sIndent))
echo "\n";
return;
}
//SkipDebug
else
{
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:IETERR:01')
. $this->backtrace()
, E_USER_ERROR
);
}
//EndSkipDebug
}
function _printAttributes()
{
// NOTE: Special case here: disabled='false' does not work in HTML; does work in javascript
foreach ($this->aAttributes as $sKey => $sValue)
if ('disabled' != $sKey || 'false' != $sValue)
echo "{$sKey}='{$sValue}' ";
}
function _printEvents()
{
foreach (array_keys($this->aEvents) as $sKey)
{
$aEvent =& $this->aEvents[$sKey];
$objRequest =& $aEvent[0];
$aParameters = $aEvent[1];
$sBeforeRequest = $aEvent[2];
$sAfterRequest = $aEvent[3];
foreach ($aParameters as $aParameter)
{
$nParameter = $aParameter[0];
$sType = $aParameter[1];
$sValue = $aParameter[2];
$objRequest->setParameter($nParameter, $sType, $sValue);
}
$objRequest->useDoubleQuote();
echo "{$sKey}='{$sBeforeRequest}";
$objRequest->printScript();
echo "{$sAfterRequest}' ";
}
}
function backtrace()
{
// debug_backtrace was added to php in version 4.3.0
// version_compare was added to php in version 4.0.7
if (0 <= version_compare(PHP_VERSION, '4.3.0'))
return '<div><div>Backtrace:</div><pre>'
. print_r(debug_backtrace(), true)
. '</pre></div>';
return '';
}
}
/*
Class: xajaxControlContainer
This class is used as the base class for controls that will contain
other child controls.
*/
class xajaxControlContainer extends xajaxControl
{
/*
Array: aChildren
An array of child controls.
*/
var $aChildren;
/*
Boolean: sChildClass
Will contain '%inline' if all children are class = '%inline', '%block' if all children are '%block' or
'%flow' if both '%inline' and '%block' elements are detected.
*/
var $sChildClass;
/*
Function: xajaxControlContainer
Called to construct and configure this control.
Parameters:
aConfiguration - (array): See <xajaxControl->xajaxControl> for more
information.
*/
function xajaxControlContainer($sTag, $aConfiguration=array())
{
xajaxControl::xajaxControl($sTag, $aConfiguration);
$this->clearChildren();
if (isset($aConfiguration['child']))
$this->addChild($aConfiguration['child']);
else if (isset($aConfiguration['children']))
$this->addChildren($aConfiguration['children']);
$this->sEndTag = 'required';
}
/*
Function: getClass
Returns the *adjusted* class of the element
*/
function getClass()
{
$sClass = xajaxControl::getClass();
if (0 < count($this->aChildren) && '%flow' == $sClass)
return $this->getContentClass();
else if (0 == count($this->aChildren) || '%inline' == $sClass || '%block' == $sClass)
return $sClass;
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:ICERR:01')
. $this->backtrace()
, E_USER_ERROR
);
}
/*
Function: getContentClass
Returns the *adjusted* class of the content (children) of this element
*/
function getContentClass()
{
$sClass = '';
foreach (array_keys($this->aChildren) as $sKey)
{
if ('' == $sClass)
$sClass = $this->aChildren[$sKey]->getClass();
else if ($sClass != $this->aChildren[$sKey]->getClass())
return '%flow';
}
if ('' == $sClass)
return '%inline';
return $sClass;
}
/*
Function: clearChildren
Clears the list of child controls associated with this control.
*/
function clearChildren()
{
$this->sChildClass = '%inline';
$this->aChildren = array();
}
/*
Function: addChild
Adds a control to the array of child controls. Child controls
must be derived from <xajaxControl>.
*/
function addChild(&$objControl)
{
//SkipDebug
if (false == is_a($objControl, 'xajaxControl')) {
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:ICLERR:01')
. $this->backtrace()
, E_USER_ERROR
);
}
if (class_exists('clsValidator'))
{
$objValidator =& clsValidator::getInstance();
if (false == $objValidator->childValid($this->sTag, $objControl->sTag)) {
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:ICLERR:02')
. $objControl->sTag
. $objLanguageManager->getText('XJXCTL:ICLERR:03')
. $this->sTag
. $objLanguageManager->getText('XJXCTL:ICLERR:04')
. $this->backtrace()
, E_USER_ERROR
);
}
}
//EndSkipDebug
$this->aChildren[] =& $objControl;
}
function addChildren(&$aChildren)
{
//SkipDebug
if (false == is_array($aChildren)) {
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:ICHERR:01')
. $this->backtrace()
, E_USER_ERROR
);
}
//EndSkipDebug
foreach (array_keys($aChildren) as $sKey)
$this->addChild($aChildren[$sKey]);
}
function printHTML($sIndent='')
{
//SkipDebug
if (class_exists('clsValidator'))
{
$objValidator =& clsValidator::getInstance();
$sMissing = '';
if (false == $objValidator->checkRequiredAttributes($this->sTag, $this->aAttributes, $sMissing)) {
$objLanguageManager =& xajaxLanguageManager::getInstance();
trigger_error(
$objLanguageManager->getText('XJXCTL:MRAERR:01')
. $sMissing
. $objLanguageManager->getText('XJXCTL:MRAERR:02')
. $this->sTag
. $objLanguageManager->getText('XJXCTL:MRAERR:03')
, E_USER_ERROR
);
}
}
//EndSkipDebug
$sClass = $this->getClass();
if ('%inline' != $sClass)
// this odd syntax is necessary to detect request for no formatting
if (false === (false === $sIndent))
echo $sIndent;
echo '<';
echo $this->sTag;
echo ' ';
$this->_printAttributes();
$this->_printEvents();
if (0 == count($this->aChildren))
{
if ('optional' == $this->sEndTag)
{
echo '/>';
if ('%inline' != $sClass)
// this odd syntax is necessary to detect request for no formatting
if (false === (false === $sIndent))
echo "\n";
return;
}
//SkipDebug
else if ('required' != $this->sEndTag)
trigger_error("Invalid end tag designation; should be optional or required.\n"
. $this->backtrace(),
E_USER_ERROR
);
//EndSkipDebug
}
echo '>';
$sContentClass = $this->getContentClass();
if ('%inline' != $sContentClass)
// this odd syntax is necessary to detect request for no formatting
if (false === (false === $sIndent))
echo "\n";
$this->_printChildren($sIndent);
if ('%inline' != $sContentClass)
// this odd syntax is necessary to detect request for no formatting
if (false === (false === $sIndent))
echo $sIndent;
echo '<' . '/';
echo $this->sTag;
echo '>';
if ('%inline' != $sClass)
// this odd syntax is necessary to detect request for no formatting
if (false === (false === $sIndent))
echo "\n";
}
function _printChildren($sIndent='')
{
if (false == is_a($this, 'clsDocument'))
// this odd syntax is necessary to detect request for no formatting
if (false === (false === $sIndent))
$sIndent .= "\t";
// children
foreach (array_keys($this->aChildren) as $sKey)
{
$objChild =& $this->aChildren[$sKey];
$objChild->printHTML($sIndent);
}
}
}