Location: PHPKode > projects > Porte > porte-0.2.2/src/plugins/associations/OneToOneHasOne.php
<?php

/**
 * Copyright (c) 2008, SARL Adaltas. All rights reserved.
 * Code licensed under the BSD License:
 * http://porte.adaltas.com/en/developer/license.html
 */

/**
 * PorteOneToOneHasOne
 * 
 * @package    Porte
 * @subpackage plugin
 * @author     David Worms info(at)adaltas.com
 * @copyright  2008 Adaltas
 */
class PorteOneToOneHasOne{
	
	public static function setProperty(PorteModels $models,$type,$property){
		$model = $models->{$type};
		$relatedModel = null;
		$config = $models->{$type}['properties'][$property];
		$config['transient'] = true;
		if(is_string($config['has_one'])){
			$config['has_one'] = array('type'=>$config['has_one']);
		}else if(!is_array($config['has_one'])){
			$config['has_one'] = array();
		}
		// Take care of type
		if(!isset($config['has_one']['type'])){
			if(isset($config['has_one']['class'])&&$config['has_one']['class']!='PorteRecord'){
				$relatedModel = $config['has_one']['class'];
				$relatedModel = $models->get(new $relatedModel());
				$config['has_one']['type'] = $relatedModel['class'];
			}else{
				$config['has_one']['type'] = PorteUtils::underscore($property);
			}
		}
		// Deal with model
		if(!$relatedModel){
			$relatedModel = $models->get($config['has_one']['type']);
		}
		// Deal with class
		if(!isset($config['has_one']['class'])){
			$config['has_one']['class'] = $relatedModel['class'];
		}
		if(empty($config['has_one']['property'])){
			$config['has_one']['property'] = $model['type'];
		}
		$config['lazy'] = true;
		if(isset($relatedModel['properties'][$config['has_one']['property']])){
			$relatedProperty = $config['has_one']['property'];
			$models->{$type}['properties'][$property] = $config;
			/*
			if(!isset($relatedModel->properties->$relatedProperty)){
				$relatedModel->properties->get($relatedProperty);
			}
			*/
		}else{
			//unset($config['has_one']['property']);
		}
		// Deals with methods
		$camelizedProperty = PorteUtils::camelize($property);
		PorteModel::addMethod($models,$type,'get'.$camelizedProperty,$property,array('PorteOneToOneHasOne','getRecord'));
		PorteModel::addMethod($models,$type,'set'.$camelizedProperty,$property,array('PorteOneToOneHasOne','setRecord'));
		PorteModel::addMethod($models,$type,'delete'.$camelizedProperty,$property,array('PorteOneToOneHasOne','deleteRecord'));
	}
	
	/**
	 * Return the associated record or null if not defined.
	 * 
	 * @return mixed PorteRecord if association is defined or null
	 * @param $property string Record property
	 * @param $record PorteRecord Record recieving the association
	 */
	public static function getRecord($property,PorteRecord $record){
		$config = $record->porte->models->{$record->type}['properties'][$property];
		// if association not yet created and we got a foreign key then create the association
		if(!array_key_exists($property,$record->associations)){
			$relatedTable = $record->porte->tables->{$config['has_one']['type']};
			//$relatedConfig = $relatedTable->model->properties->$config['has_one']['property'];
			$relatedConfig = $record->porte->models->{$config['has_one']['type']}['properties'][$config['has_one']['property']];
			$assoc = $relatedTable->find($relatedConfig['field'].' = ?',array(1=>$record->getIdentifier()));
			switch(count($assoc)){
				case 0:
					return $record->associations[$property] = null;
				case 1:
					return $record->associations[$property] = $assoc->current();
				default:
					throw new PorteException('Corrupted database: more than one association');
			}
		// if association already set, return it
		}else if(!empty($record->associations[$property])){
			return $record->associations[$property];
		}else if(array_key_exists('default',$config)){
			return $config['default'];
		}else{
			// we wanted to return null but for some weird reason, 
			// when we do this, we get an integer 0
			return null;
		}
	}
	
	/**
	 * Associated record may be an object (instance of PorteRecord), an int (or a 
	 * string casted to an int), an array (representing the record, like the return value
	 * of the "record->toArray" method) or null (if property not tagged as not_null).
	 * 
	 * @return PorteRecord Current record
	 * @param $property string Record property
	 * @param $record PorteRecord Record recieving the association
	 * @param $assocRecord mixed[optional] Associated record as a record, primary key, array or null; default to null of not provided
	 */
	public static function setRecord($property,PorteRecord $record,$assocRecord=null){
		$config = $record->porte->models->{$record->type}['properties'][$property];
		$assocRecord = PorteAssociations::makeRecord($record,$config,'has_one',$assocRecord);
		$record->associations[$property] = $assocRecord;
		$assocRecord->associations[$config['has_one']['property']] = $record;
		return $record;
	}
	
	/**
	 * Break the association if one existed.
	 * 
	 * @return PorteRecord Current record
	 * @param $property string Record property
	 * @param $record PorteRecord Record recieving the association
	 */
	public static function deleteRecord($property,PorteRecord $record){
		if(isset($record->associations[$property])){
			$config = $record->porte->models->{$record->type}['properties'][$property];
			$assocRecord = $record->associations[$property];
			PorteOneToOneBelongsTo::setRecord($config['has_one']['property'],$assocRecord);
			$record->events->connect('record_save_before',array($assocRecord,'save'),array('once','arguments'=>array()));
			return $record;
		}
	}
	
}

?>
Return current item: Porte