<?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;
}
}
}
?>