Source for file Relation.inc
Documentation is available at Relation.inc
require_once $config->get('sysRoot'). 'alpha/exceptions/AlphaException.inc';
require_once $config->get('sysRoot'). 'alpha/model/types/AlphaType.inc';
require_once $config->get('sysRoot'). 'alpha/model/types/AlphaTypeInterface.inc';
require_once $config->get('sysRoot'). 'alpha/model/types/RelationLookup.inc';
* The Relation complex data type
* @package alpha::model::types
* @author John Collins <dev@alphaframework.org>
* @version $Id: Relation.inc 1341 2011-03-17 15:02:02Z johnc $
* @license http://www.opensource.org/licenses/bsd-license.php The BSD License
* @copyright Copyright (c) 2011, John Collins (founder of Alpha Framework).
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the
* following conditions are met:
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* * 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.
* * Neither the name of the Alpha Framework nor the names
* of its contributors may be used to endorse or promote
* products derived from this software without specific
* prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "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 THE COPYRIGHT HOLDER 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 name of the business object class which this class is related to
* The name of the fields of the business object class by which this class is related by
private $relatedClassField;
* The name of the field from the related business object class which is displayed by the selection widget
private $relatedClassDisplayField;
* An array of fields to use the values of while rendering related display values via the selection widget
private $relatedClassHeaderFields = array();
* The name of the business object class on the left of a MANY-TO-MANY relation
private $relatedClassLeft;
* The name of the field from the related business object class on the left of a
* MANY-TO-MANY relation which is displayed by the selection widget
private $relatedClassLeftDisplayField;
* The name of the business object class on the right of a MANY-TO-MANY relation
private $relatedClassRight;
* The name of the field from the related business object class on the right of a
* MANY-TO-MANY relation which is displayed by the selection widget
private $relatedClassRightDisplayField;
* The type of relation ('MANY-TO-ONE' or 'ONE-TO-MANY' or 'ONE-TO-ONE' or 'MANY-TO-MANY')
* In the case of MANY-TO-MANY relationship, a lookup object will be required
* When building a relation with the TagObject BO, set this to the name of the tagged class
* An array of the allowable relationship types ('MANY-TO-ONE' or 'ONE-TO-MANY' or 'ONE-TO-ONE' or 'MANY-TO-MANY')
private $allowableRelationTypes = array('MANY-TO-ONE','ONE-TO-MANY','ONE-TO-ONE','MANY-TO-MANY');
* The object ID (OID) value of the related object. In the special case of a MANY-TO-MANY
* relation, contains the OID of the object on the current, accessing side. Can contain NULL.
* The validation rule for the Relation type
* The error message for the Relation type when validation fails
* The size of the value for the this Relation
* The absolute maximum size of the value for the this Relation
$this->helper = ' not a valid Relation value! A maximum of '. $this->size. ' characters is allowed.';
* Set the name of the business object class that this class is related to
* @param string $side Only required for MANY-TO-MANY relations
* @throws IllegalArguementException
// load the class definition if it has not been loaded already
$this->relatedClass = $RC;
$this->relatedClassLeft = $RC;
$this->relatedClassRight = $RC;
* Get the name of the business object class that this class is related to
* @throws IllegalArguementException
return $this->relatedClass;
return $this->relatedClassLeft;
return $this->relatedClassRight;
* Setter for the field of the related class
* @throws IllegalArguementException
// use reflection to sure the related class has the field $RCF
$reflection = new ReflectionClass($this->relatedClass);
$properties = $reflection->getProperties();
foreach($properties as $propObj) {
if($RCF == $propObj->name) {
$this->relatedClassField = $RCF;
* Getter for the field of the related class
return $this->relatedClassField;
* Setter for ONE-TO-MANY relations, which sets the header fields to
* render from the related class
* @param array $fieldNames
$this->relatedClassHeaderFields = $fieldNames;
* Getter for the selection widget field headings of the related class
return $this->relatedClassHeaderFields;
* Setter for the display field from the related class
* @param string $side Only required for MANY-TO-MANY relations
* @throws IllegalArguementException
$this->relatedClassDisplayField = $RCDF;
$this->relatedClassLeftDisplayField = $RCDF;
$this->relatedClassRightDisplayField = $RCDF;
* Getter for the display field from the related class
* @param string $side Only required for MANY-TO-MANY relations
* @throws IllegalArguementException
return $this->relatedClassDisplayField;
return $this->relatedClassLeftDisplayField;
return $this->relatedClassRightDisplayField;
* Setter for the relation type
* @throws IllegalArguementException
* @throws FailedLookupCreateException
* @throws IllegalArguementException
if(in_array($RT, $this->allowableRelationTypes)) {
$this->relationType = $RT;
if($RT == 'MANY-TO-MANY') {
$this->lookup = new RelationLookup($this->relatedClassLeft, $this->relatedClassRight);
* Getter for the relation type
return $this->relationType;
* Setter for the value (OID of related object) of this relation
* @throws IllegalArguementException
if (strlen($val) <= $this->size) {
$this->value = str_pad($val, 11, '0', STR_PAD_LEFT);
* Getter for the Relation value
* Get the validation rule
return $this->validationRule;
* Setter to override the default validation rule
$this->validationRule = $rule;
* Getter for the display value of the related class field. In the case of a
* MANY-TO-MANY Relation, a comma-seperated sorted list of values is returned.
* @param string $accessingClassName Used to indicate the reading side when accessing from MANY-TO-MANY relation (leave blank for other relation types)
* @throws IllegalArguementException
if($this->relationType == 'MANY-TO-MANY') {
* 1. Use RelationLookup to get OIDs of related objects
* 2. Load related objects
* 3. Access the value of the field on the object to build the
throw new AlphaException('Tried to load related MANY-TO-MANY fields but no RelationLookup set on the Relation object!');
if(empty($accessingClassName))
throw new IllegalArguementException('Tried to load related MANY-TO-MANY fields but no accessingClassName parameter set on the call to getRelatedClassDisplayFieldValue!');
// load objects on the right from accessing on the left
if($accessingClassName == $this->relatedClassLeft) {
$obj = new $this->relatedClassRight;
foreach($lookupObjects as $lookupObject) {
$obj->load($lookupObject->get('rightID'));
array_push($values, $obj->get($this->relatedClassRightDisplayField));
// sort array, then return as comma-seperated string
// load objects on the left from accessing on the right
if($accessingClassName == $this->relatedClassRight) {
$obj = new $this->relatedClassLeft;
foreach($lookupObjects as $lookupObject) {
$obj->load($lookupObject->get('leftID'));
array_push($values, $obj->get($this->relatedClassLeftDisplayField));
// sort array, then return as comma-seperated string
$obj = new $this->relatedClass;
// making sure we have an object to load
if(empty($this->value) || $this->value == '00000000000') {
$obj->load($this->value);
return $obj->get($this->relatedClassDisplayField);
* For one-to-many and many-to-many relations, get the objects on the other side
* string $accessingClassName Used to indicate the reading side when accessing from MANY-TO-MANY relation (leave blank for other relation types)
* @throws IllegalArguementException
if($this->relationType == 'ONE-TO-MANY') {
throw new AlphaException('Could not load the definition for the BO class ['. $this->relatedClass. ']');
$obj = new $this->relatedClass;
if($this->relatedClass == 'TagObject') {
$objects = $obj->loadTags($this->taggedClass, $this->getValue());
if(empty($this->lookup)) {
throw new AlphaException('Tried to load related MANY-TO-MANY objects but no RelationLookup set on the Relation object!');
if(empty($accessingClassName)) {
throw new IllegalArguementException('Tried to load related MANY-TO-MANY objects but no accessingClassName parameter set on the call to getRelatedObjects!');
// load objects on the right from accessing on the left
if($accessingClassName == $this->relatedClassLeft) {
foreach($lookupObjects as $lookupObject) {
$obj = new $this->relatedClassRight;
$obj->load($lookupObject->get('rightID'));
// load objects on the left from accessing on the right
if($accessingClassName == $this->relatedClassRight) {
foreach($lookupObjects as $lookupObject) {
$obj = new $this->relatedClassLeft;
$obj->load($lookupObject->get('leftID'));
* For one-to-one relations, get the object on the other side
throw new AlphaException('Could not load the definition for the BO class ['. $this->relatedClass. ']');
$obj = new $this->relatedClass;
* Get the allowable size of the Relation in the database field
* Get the lookup object if available (only on MANY-TO-MANY relations, null otherwise)
* Gets the side ('left' or 'right') of the passed classname on the current Relation object
* @param string $BOClassname
* @throws IllegalArguementException
public function getSide($BOClassname) {
if($BOClassname == $this->relatedClassLeft) {
}elseif($BOClassname == $this->relatedClassRight) {
throw new IllegalArguementException('Error trying to determine the MANY-TO-MANY relationship side for the classname ['. $BOClassname. ']');
* Set the taggedClass property to the name of the tagged class when building relations
$this->taggedClass = $taggedClass;
|