175 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			175 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * @package   FOF
 | |
|  * @copyright Copyright (c)2010-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
 | |
|  * @license   GNU General Public License version 2, or later
 | |
|  */
 | |
| 
 | |
| namespace FOF30\Model\DataModel\Relation;
 | |
| 
 | |
| defined('_JEXEC') || die;
 | |
| 
 | |
| use FOF30\Model\DataModel;
 | |
| use FOF30\Model\DataModel\Relation;
 | |
| use JDatabaseQuery;
 | |
| 
 | |
| /**
 | |
|  * HasMany (1-to-many) relation: this model is a parent which has zero or more children in the foreign table
 | |
|  *
 | |
|  * For example, parentModel is Users and foreignModel is Articles. Each user has zero or more articles.
 | |
|  */
 | |
| class HasMany extends Relation
 | |
| {
 | |
| 	/**
 | |
| 	 * Public constructor. Initialises the relation.
 | |
| 	 *
 | |
| 	 * @param   DataModel  $parentModel       The data model we are attached to
 | |
| 	 * @param   string     $foreignModelName  The name of the foreign key's model in the format
 | |
| 	 *                                        "modelName@com_something"
 | |
| 	 * @param   string     $localKey          The local table key for this relation, default: parentModel's ID field
 | |
| 	 *                                        name
 | |
| 	 * @param   string     $foreignKey        The foreign key for this relation, default: parentModel's ID field name
 | |
| 	 * @param   string     $pivotTable        IGNORED
 | |
| 	 * @param   string     $pivotLocalKey     IGNORED
 | |
| 	 * @param   string     $pivotForeignKey   IGNORED
 | |
| 	 */
 | |
| 	public function __construct(DataModel $parentModel, $foreignModelName, $localKey = null, $foreignKey = null, $pivotTable = null, $pivotLocalKey = null, $pivotForeignKey = null)
 | |
| 	{
 | |
| 		parent::__construct($parentModel, $foreignModelName, $localKey, $foreignKey, $pivotTable, $pivotLocalKey, $pivotForeignKey);
 | |
| 
 | |
| 		if (empty($this->localKey))
 | |
| 		{
 | |
| 			$this->localKey = $parentModel->getIdFieldName();
 | |
| 		}
 | |
| 
 | |
| 		if (empty($this->foreignKey))
 | |
| 		{
 | |
| 			$this->foreignKey = $this->localKey;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns the count sub-query for DataModel's has() and whereHas() methods.
 | |
| 	 *
 | |
| 	 * @param   string  $tableAlias  The alias of the local table in the query. Leave blank to use the table's name.
 | |
| 	 *
 | |
| 	 * @return JDatabaseQuery
 | |
| 	 */
 | |
| 	public function getCountSubquery($tableAlias = null)
 | |
| 	{
 | |
| 		// Get a model instance
 | |
| 		$foreignModel = $this->getForeignModel();
 | |
| 		$foreignModel->setIgnoreRequest(true);
 | |
| 
 | |
| 		$db = $foreignModel->getDbo();
 | |
| 
 | |
| 		if (empty($tableAlias))
 | |
| 		{
 | |
| 			$tableAlias = $this->parentModel->getTableName();
 | |
| 		}
 | |
| 
 | |
| 		$query = $db->getQuery(true)
 | |
| 			->select('COUNT(*)')
 | |
| 			->from($db->qn($foreignModel->getTableName(), 'reltbl'))
 | |
| 			->where($db->qn('reltbl') . '.' . $db->qn($foreignModel->getFieldAlias($this->foreignKey)) . ' = '
 | |
| 				. $db->qn($tableAlias) . '.'
 | |
| 				. $db->qn($this->parentModel->getFieldAlias($this->localKey)));
 | |
| 
 | |
| 		return $query;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns a new item of the foreignModel type, pre-initialised to fulfil this relation
 | |
| 	 *
 | |
| 	 * @return DataModel
 | |
| 	 *
 | |
| 	 * @throws DataModel\Relation\Exception\NewNotSupported when it's not supported
 | |
| 	 */
 | |
| 	public function getNew()
 | |
| 	{
 | |
| 		// Get a model instance
 | |
| 		$foreignModel = $this->getForeignModel();
 | |
| 		$foreignModel->setIgnoreRequest(true);
 | |
| 
 | |
| 		// Prime the model
 | |
| 		$foreignModel->setFieldValue($this->foreignKey, $this->parentModel->getFieldValue($this->localKey));
 | |
| 
 | |
| 		// Make sure we do have a data list
 | |
| 		if (!($this->data instanceof DataModel\Collection))
 | |
| 		{
 | |
| 			$this->getData();
 | |
| 		}
 | |
| 
 | |
| 		// Add the model to the data list
 | |
| 		$this->data->add($foreignModel);
 | |
| 
 | |
| 		return $this->data->last();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Applies the relation filters to the foreign model when getData is called
 | |
| 	 *
 | |
| 	 * @param   DataModel             $foreignModel    The foreign model you're operating on
 | |
| 	 * @param   DataModel\Collection  $dataCollection  If it's an eager loaded relation, the collection of loaded
 | |
| 	 *                                                 parent records
 | |
| 	 *
 | |
| 	 * @return boolean Return false to force an empty data collection
 | |
| 	 */
 | |
| 	protected function filterForeignModel(DataModel $foreignModel, DataModel\Collection $dataCollection = null)
 | |
| 	{
 | |
| 		// Decide how to proceed, based on eager or lazy loading
 | |
| 		if (is_object($dataCollection))
 | |
| 		{
 | |
| 			// Eager loaded relation
 | |
| 			if (!empty($dataCollection))
 | |
| 			{
 | |
| 				// Get a list of local keys from the collection
 | |
| 				$values = [];
 | |
| 
 | |
| 				/** @var $item DataModel */
 | |
| 				foreach ($dataCollection as $item)
 | |
| 				{
 | |
| 					$v = $item->getFieldValue($this->localKey, null);
 | |
| 
 | |
| 					if (!is_null($v))
 | |
| 					{
 | |
| 						$values[] = $v;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				// Keep only unique values. This double step is required to re-index the array and avoid issues with
 | |
| 				// Joomla Registry class. See issue #681
 | |
| 				$values = array_values(array_unique($values));
 | |
| 
 | |
| 				// Apply the filter
 | |
| 				if (!empty($values))
 | |
| 				{
 | |
| 					$foreignModel->where($this->foreignKey, 'in', $values);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					return false;
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				return false;
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			// Lazy loaded relation; get the single local key
 | |
| 			$localKey = $this->parentModel->getFieldValue($this->localKey, null);
 | |
| 
 | |
| 			if (is_null($localKey) || ($localKey === ''))
 | |
| 			{
 | |
| 				return false;
 | |
| 			}
 | |
| 
 | |
| 			$foreignModel->where($this->foreignKey, '==', $localKey);
 | |
| 		}
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| }
 |