Source for file classes.inc.php
Documentation is available at classes.inc.php
* This file is part of the VCL for PHP project
* Copyright (c) 2004-2007 qadram software <support@qadram.com>
* Checkout AUTHORS file for more information on the developers
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
global $exceptions_enabled;
$exceptions_enabled= true;
* Component it's being loaded
* Component it's being edited on the IDE designer
//TODO: Provide a way to show this info using templates so is customizable by final users
* Common exception handler, it provides a way to pretty format exceptions and to
* get an stack trace to find out where the problem is
* @param Exception $exception Exception to raise
$stacktrace.= "Application raised an exception class <b>". get_class($exception). "</b> with message <b>'". $exception->getMessage(). "'</b>\n";
while (list ($k,$v)= each($stack))
$stacktrace.= $tab. $c. "Callstack #$k File: <b>". $v['file']. "</b> Line: <b>". $v['line']. "</b>\n";
$tolog.= $v['line']. "@". $v['file']. '@'. $msg;
* Exception thrown when a resource is not found on an xml stream
$message= sprintf("Resource not found [%s]", $message);
// make sure everything is assigned properly
parent::__construct($message, $code);
* ENameDuplicated exception
* Exception thrown when a component has the same name on the same owner
$message= sprintf("A component named %s already exists", $message);
// make sure everything is assigned properly
parent::__construct($message, $code);
* Exception thrown when trying to assign an object to another
$message= sprintf("Cannot assign a %s to a %s", $sourcename, $classname);
// make sure everything is assigned properly
parent::__construct($message, 0);
* ECollectionError exception
* Exception thrown for Collection errors
$message= sprintf("List index out of bounds (%s)", $message);
// make sure everything is assigned properly
parent::__construct($message, $code);
* A base class to read/write components from/to an xml stream
* Initializes the object by setting up a list of parents and the xml parser used to read/write components
* @param xmlparser $xmlparser xml parser to read/write components
//List of parents to provide a stack
//TODO: Develop a TStringList class
//Root members, to initialize them with the right components
* Processed the opening tags to select which action to take
* @param xmlparser $parser xml parser in use
* @param string $tag opening tag
* @param array $attributes attributes of the opening tag
function tagOpen($parser, $tag, $attributes)
case 'OBJECT': //Read object parameters
//Class and name for that component
$class= $attributes['CLASS'];
$name= $attributes['NAME'];
//If there is a root component and it has not been read yet
//And the class we are reading matches
if (($this->_root->classNameIs($class)) || ($this->_root->inheritsFrom($class)))
//We must read root properties, so set the lastread to the root
//We must create a new object of the class just read
//If that class has been declared somewhere
//Creates a new instance of that class
//This is a kind of a hack to get the right reference to the newly created component
echo "Error reading language resource file, object ($name) not found";
//We find the member of the root object and we set the reference
//TODO: Decide to dump here an error or not
if ($this->_lastread->inheritsfrom("Control"))
//TODO: Change this by an exception when possible, there's a bug in PHP 5, because the exception is raised inside an xml reader
echo "Error reading resource file, class ($class) doesn't exists";
//throw new EResNotFound("Error reading resource file, class ($class) doesn't exists");
$name= $attributes['NAME'];
//If we are reading a property, must be inside an object
echo "Error reading resource file, property ($name) doesn't have an object to assign to";
default: echo "Error reading resource file, tag ($tag) not recognized"; break;
* Processed the data for tags
* @param xmlparser $parser xml parser in use
* @param string $cdata data to be processed
function cData($parser, $cdata)
//If we have an object and a property
$method= 'get'. $aproperty;
if ($aroot->methodExists($method))
$value= $aroot->$method();
$method= 'set'. $aproperty;
if ($aroot->methodExists($method))
if (($aroot->inheritsFrom('Component')) && (!$aroot->inheritsFrom('Control')) && ($aproperty== 'Left'))
else if (($aroot->inheritsFrom('Component')) && (!$aroot->inheritsFrom('Control')) && ($aproperty== 'Top'))
else echo "Error setting property (". $aroot->className(). "::$this->_lastproperty), doesn't exists";
* @param xmlparser $parser xml parser in use
* @param string $tag tag being closed
// Pop last array element
//Pop the parent from the stack
//Call the last read component
//TODO: Check if the last item from the stack is the right one to call loaded
if (($this->_lastread->inheritsFrom('Page')) || ($this->_lastread->inheritsFrom('DataModule')))
if (($this->_lastread->inheritsFrom('Page')) || ($this->_lastread->inheritsFrom('DataModule')))
if (($this->_lastread->inheritsFrom('Page')) || ($this->_lastread->inheritsFrom('DataModule')))
if (($this->_lastread->inheritsFrom('Page')) || ($this->_lastread->inheritsFrom('DataModule')))
if ($this->_root->inheritsFrom('Page'))
if (!$this->_root->UseAjax) $this->_lastread->loaded();
$this->_lastread->loaded();
function getRoot() { return($this->_root); }
* @param object $value new property value
//TODO: Check here $value for null
//Get the vars from the root object to get the pointers for the components
//Clear parents list and set the root as the first parent
* A class to read components from an xml stream
* Read a component and all its children from a stream
* @param object $root Root component to read
* @param string $stream XML stream to read from
$this->_root->ControlState= 0;
* A class to store and manage a list of objects
* Add an item to the list
* @param object $item Object to add to the list
//Set the array to the end
//Adds the item as the last one
* Delete an item from the list by its index
* @param integer $index Index of the item to delete
//Deletes the item from the array, so the rest of items are reordered
if ($index< $this->count())
* Finds an item into the list
* @param object $item Item to find
* Remove an item from the list
* @param object $item Item to delete from the list
//Delete the index if exists
* Return the number of items in the list
* Return the last element from the collection
* Base class for persistent objects, which are the ones provide the required
* features to be serialized/unserialized easily
* Used to serialize/unserialize
if ($this->readOwner()!= null)
$s= $this->readOwner()->readNamePath();
if ($s!= "") $result = $s . "." . $result;
* Owner of the component, in Persistent always return null
* Assing the source properties to this object
* @param Persistent $source Object to get assigned to this object
if ($source!= null) $source->assignTo($this);
* Assign this object to another object
* @param Persistent $dest Object to assign this object to
$dest->assignError($this);
* Raises an assignation error
* @param Persistent $source Component tried to assign
if ($source!= null) $sourcename= $source->className();
* Stores this object into the session, it uses PHP reflection system
* to get published properties, the ones that will be stored.
* Components need an owner to be serialized
$owner= $this->readOwner();
$refclass= new ReflectionClass($this->ClassName());
$methods= $refclass->getMethods();
while (list ($k,$method)= each($methods))
$methodname= $method->name;
if ($methodname[0] == 's' && $methodname[1] == 'e' && $methodname[2] == 't') // fast check of: substr($methodname,0,3)=='set'
$propname= substr($methodname, 3);
$propvalue= $this->$propname;
$_SESSION[$owner->readNamePath(). ".". $this->readNamePath(). ".". $propname]= $propvalue;
$this->serializeChildren();
global $exceptions_enabled;
throw new Exception('Cannot serialize a component without an owner');
* Read this object properties from the session, only published properties
* will be recovered, components need an owner to be unserialized.
$owner= $this->readOwner();
$refclass= new ReflectionClass($this->ClassName());
$methods= $refclass->getMethods();
while (list ($k,$method)= each($methods))
$methodname= $method->name;
if ($methodname[0] == 's' && $methodname[1] == 'e' && $methodname[2] == 't') // fast check of: substr($methodname,0,3)=='set'
$propname= substr($methodname, 3);
$fullname = $owner->readNamePath(). ".". $this->readNamePath(). ".". $propname;
if (isset ($_SESSION[$fullname]))
$this->$propname= $_SESSION[$fullname];
global $exceptions_enabled;
throw new Exception('Cannot unserialize a component without an owner');
* Base class for components, it provides owner relationships properties and
* basic methods to call events.
* Non-visible components must inherit from Component and not from Control, the
* IDE automatically handles the component as iconic.
* @param object $aowner The owner of this component
//Calls the inherited constructor
parent::__construct($aowner);
//Adds itself to the list of components from the owner
$this->owner->insertComponent($this);
throw new Exception("Owner must be an object");
* A virtual method to get notified when the object has been fully loaded from a stream
* Calls childrens loaded recursively
//Calls childrens loaded recursively
* Overwrite this method to provide accessibility info for the RPC engine
return(Accessibility_Fail);
* This method returns the right object (or the input string if object not found) for an object name
* Should be used on the loaded method for object properties to find the right reference
* @param mixed $value string or object to set the property to
* Unserialize all children
* @return mixed calling event result
if ($this->$ievent!= null)
if (!$this->owner->classNameIs('application'))
return($this->owner->$event($this,$params));
else return($this->$event($this,$params));
* Returns the js event attribute to call the server using Ajax
* we use xajax to handle all the ajax stuff.
* @param string $jsevent javascript event
* @param string $phpevent php event to call
$result= " $jsevent=\"xajax_ajaxProcess('". $this->owner->Name. "','". $this->Name. "',null,'$phpevent',xajax.getFormValues('". $this->owner->Name. "'))\" ";
//TODO: Full implement the param exchange
* Returns the js event attribute to call the server using ajax
* @param string $phpevent php event to call
* @param array $params values to send to the server
function ajaxCall($phpevent, $params= array())
$result= " xajax_ajaxProcess('". $this->owner->Name. "','". $this->Name. "',params,'$phpevent',xajax.getFormValues('". $this->owner->Name. "'));\n ";
* To initialize a component, called before init()
//Calls childrens init recursively
* To initialize a component, the right place to process events
//Calls childrens init recursively
* Checks if there is any datafield attached to the component
* and sets the dataset in edit state and all the fields with
* the appropiate values so the dataset is able to update the
* Properties for data-aware components must be named
* This is for basic single-field data-aware controls, for more
* complicated controls like DBGrid, each component must create
* its own mechanism to update information in the database
if ($this->_datafield!= "")
if ($this->_datasource!= null)
if ($this->_datasource->Dataset!= null)
//Check here for the index fields
$keyfields= $this->Name. "_key";
$keys= $this->input->$keyfields;
// check if the keys were posted
$this->_datasource->Dataset->edit();
$values= $keys->asStringArray();
while (list ($k,$v)= each($values))
$this->_datasource->Dataset->$k= $v;
$this->_datasource->Dataset->$fname= $value;
else $this->_datasource->Dataset->{$this->_datafield}= $value;
* This function returns true if the datafield is valid
if ($this->_datafield!= "")
if ($this->_datasource!= null)
if ($this->_datasource->Dataset!= null)
* This function returns the value of the datafield, if any
function readDataFieldValue()
$value= $this->_datasource->Dataset->$fname;
* This function dumps out the key fields for the current row, useful to
* send information about the current register
if ($this->_datasource!= null)
if ($this->_datasource->Dataset!= null)
if (($this->_datasource->Dataset->State!= dsInsert) || ($force))
//Dump the key values for this record so I'm able to update it in the future
$this->_datasource->Dataset->dumpHiddenKeyFields($this->Name. "_key");
//Calls childrens serialize recursively
* To dump the javascript code needed by this component
* To dump header code required
* Dump the javascript code for all the children
//Iterates through components, dumping all javascript
if ($v->inheritsFrom('Control'))
else $v->dumpJavascript();
* Dump the header code for all the children
* @param boolean $return_contents If true, code is returned instead be dumped
//Iterates through components, dumping all javascript
if ($v->inheritsFrom('Control'))
else $v->dumpHeaderCode();
* Load this component from a string
* @param string $filename xml file name
* @param boolean $inherited specifies if we are going to read an inherited resource
function loadResource($filename, $inherited= false, $storelastresource= true)
//TODO: Check here for the path to the resource file
//$resourcename=basename($filename);
if ((($application->Language!= '')) || (($this->inheritsFrom('Page')) && ($this->Language!= '(default)')))
$resourcename= str_replace('.php',$l. '.xml.php',$filename);
$l= ".". $application->Language;
$resourcename= str_replace('.php',$l. '.xml.php',$filename);
$resourcename= str_replace('.php',$l. '.xml.php',$resourcename);
* Read a component from a resource file
* @param string $filename Filename of the resource file
* @param boolean $createobjects Specifies if create the objects found or just read properties
//Reads the component from an xml stream
$filelines= file($filename);
$reader->createobjects= $createobjects;
$reader->readRootComponent($this, $file);
global $exceptions_enabled;
* Insert a component into the components collection
* @param object $acomponent Component to insert
//Adds a component to the components list
$acomponent->owner= $this;
* Remove a component from the components collection
* @param object $acomponent Component to remove
//Remove a component from the components list
* Component list containing all the components owned by this component
function readComponents() { return $this->components; }
* Indicates how many components this component is owner
function readComponentCount() { return $this->components->count(); }
* A flag to know the state of the control, csLoading, csDesigning
* Example: To test if the component is rendered inside the IDE:
* if (($this->ControlState & csDesigning)==csDesigning)
* //Write here the design-time code
function writeControlState($value) { $this->_controlstate= $value; }
* The path to uniquely identify a component, qualified by the owner when required
function readNamePath() { return($this->_name); }
* The owner of this component, usually the page component, but the owner of pages is the application object
function readOwner() { return($this->owner); }
* Name for the component, to be used as an identifier, should be unique
function getName() { return $this->_name; }
//TODO: If there is an owner, check there are no any other component with the same name
if ($value!= $this->_name)
if (!$this->owner->classNameIs('application'))
reset($owner->components->items);
while (list ($k,$v)= each($owner->components->items))
else $this->_name= $value;
else $this->_name= $value;
function defaultName() { return(""); }
* A versatily property of every Component that can be used in any way you want
function getTag() { return $this->_tag; }
function setTag($value) { $this->_tag= $value; }
function defaultTag() { return 0; }
|