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

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

/**
 * PorteOneToManyHasMany
 * 
 * @package    Porte
 * @subpackage plugin
 * @author     David Worms info(at)adaltas.com
 * @copyright  2008 Adaltas
 */
class PorteOneToManyHasMany{
	
	/**
	 * One-to-many from the belongs_to (many) side
	 * 
	 * @return PorteIterator Iterator containing the associated records
	 * @param $property String Name of the property being accessed
	 * @param $record PorteRecord
	 * @param $assocRecord PorteIterator Record to be associated with the current record
	 */
	public static function addRecord($property,$record,$assocRecord){
		return PorteOneToManyHasMany::addRecords($property,$record,$assocRecord);
	}
	
	/**
	 * One-to-many from the belongs_to (many) side
	 * 
	 * @return PorteIterator Iterator containing the associated records
	 * @param $property String Name of the property being accessed
	 * @param $record PorteRecord
	 * @param $assocRecords PorteIterator Records to be associated with the current record
	 */
	public static function addRecords($property,$record,$assocRecords){
		$config = $record->porte->models->{$record->type}['properties'][$property];
		$assocRecords = new PorteIterator($record->porte->tables->get($config['has_many']['type']),$assocRecords);
		if(!$assocRecords->count()) return $record;
		if(!isset($record->associations[$property])){
			$record->associations[$property] = new PorteIterator(
				$record->table,
				// Preload PorteIterator with primary_keys
				(isset($record->attributes[$property]))?explode(',',$record->attributes[$property]):array()
			);
		}
		foreach($assocRecords as $assocRecord){
				$skip = false;
				// Make sure we do not create twice the same association
				foreach($record->associations[$property] as $registeredRecord){
					if($assocRecord->isNew() && $registeredRecord===$assocRecord){
						$skip = true;
						break;
					}else if(!$assocRecord->isNew() && $registeredRecord->getIdentifier() == $assocRecord->getIdentifier()){
						$skip = true;
						break;
					}
				}
				$record->associations[$property]->rewind();
				if(!$skip){
					$record->associations[$property]->array[] = $assocRecord;
					//$config = $record->model->properties->$property;
					//$assocModel = $record->porte->models->{$config['has_many']['type']};
					$assocProperty = $config['has_many']['property'];
					PorteOneToManyBelongsTo::setRecord($assocProperty,$assocRecord,$record);
				}
		}
		return $record;
	}
	
	/**
	 * One-to-many from the belongs_to (many) side
	 * 
	 * @return PorteIterator Iterator containing the associated records
	 * @param $property String Name of the property being accessed
	 * @param $record PorteRecord
	 * @param $options array[optional] Optional array
	 */
	public static function getRecords($property,PorteRecord $record,array $options=array()){
		$model = $record->porte->models->{$record->type};
		$config = $model['properties'][$property];
		$assocModel = $record->porte->models->{$config['has_many']['type']};
		$assocProperty = $config['has_many']['property'];
		$assocConfig = $assocModel['properties'][$assocProperty];
		$primaryKeyField =  $model['primary_key'];
		$primaryKeyValue =  $record->getIdentifier();
		$options = array_merge(array(
			'select'=>'`'.$assocModel['database'].'`.`'.$assocModel['table'].'`.*',
			'from'=>'`'.$assocModel['database'].'`.`'.$assocModel['table'].'` INNER JOIN `'.$model['database'].'`.`'.$model['table'].'` on `'.$model['database'].'`.`'.$model['table'].'`.'.$model['primary_key'].' = `'.$assocModel['database'].'`.`'.$assocModel['table'].'`.`'.$assocConfig['field'].'`',
			'where'=>'`'.$assocModel['database'].'`.`'.$assocModel['table'].'`.`'.$assocConfig['field'].'` = \''.$primaryKeyValue.'\'',
		),$options);
		$options['where'] .= ' AND `'.$assocModel['database'].'`.`'.$assocModel['table'].'`.`'.$assocConfig['field'].'` = \''.$primaryKeyValue.'\'';
		$assocRecords = $record->porte->tables->{$config['has_many']['type']}->find($options);
		/*
		foreach($assocRecords as $assocRecord){
			// This is nice but it create circular references we were not able to digg at the time
			// See OneToManyBelongsToTest->testDelete
			//call_user_func(array($assocRecord,'set'.PorteUtils::camelize($assocProperty)),$record);
		}
		$assocRecords->rewind();
		*/
		return $record->associations[$property] = $assocRecords;
	}
	
	public static function deleteRecords($property,PorteRecord $record){
		$config = $record->porte->models->{$record->type}['properties'][$property];
		$assocModel = $record->porte->models->{$config['has_many']['type']};
		$query = 'update '.$assocModel['database'].'.'.$assocModel['table'].' SET '.$config['has_many']['property'].' = null WHERE '.$config['has_many']['property'].'=\''.$record->getIdentifier().'\'';
		$record->porte->exec($query);
		return $record;
	}
	
	public static function countRecords($property,$record,$options=array()){
		$model = $record->porte->models->{$record->type};
		$config = $model['properties'][$property];
		$assocModel = $record->porte->models->{$config['has_many']['type']};
		$assocConfig = $assocModel['properties'][$config['has_many']['property']];
		$options = array_merge(array(
			'select'=>'count(*)',
			'from'=>'`'.$assocModel['database'].'`.`'.$assocModel['table'].'` INNER JOIN `'.$model['database'].'`.`'.$model['table'].'` on `'.$model['database'].'`.`'.$model['table'].'`.'.$model['primary_key'].' = `'.$assocModel['database'].'`.`'.$assocModel['table'].'`.`'.$assocConfig['field'].'`',
			'where'=>'1',
		),$options);
		$options['where'] .= ' AND `'.$assocModel['database'].'`.`'.$assocModel['table'].'`.`'.$assocConfig['field'].'` = \''.$record->getIdentifier().'\'';
		// todo: why are we not calling find without execute?
		return intval($record->porte->query($record->table->find(array_merge($options,array('return_sql'=>true,'limit'=>null))))->fetchColumn());
	}
	
}

?>
Return current item: Porte