primo commit
This commit is contained in:
		
							
								
								
									
										76
									
								
								libraries/fof30/Model/DataModel/Behaviour/Access.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								libraries/fof30/Model/DataModel/Behaviour/Access.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use JDatabaseQuery; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to filter access to items based on the viewing access levels. | ||||
|  * | ||||
|  * @since    2.1 | ||||
|  */ | ||||
| class Access extends Observer | ||||
| { | ||||
| 	/** | ||||
| 	 * This event runs after we have built the query used to fetch a record | ||||
| 	 * list in a model. It is used to apply automatic query filters. | ||||
| 	 * | ||||
| 	 * @param   DataModel      &$model  The model which calls this event | ||||
| 	 * @param   JDatabaseQuery &$query  The query we are manipulating | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterBuildQuery(&$model, &$query) | ||||
| 	{ | ||||
| 		// Make sure the field actually exists | ||||
| 		if (!$model->hasField('access')) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$model->applyAccessFiltering(null); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * The event runs after DataModel has retrieved a single item from the database. It is used to apply automatic | ||||
| 	 * filters. | ||||
| 	 * | ||||
| 	 * @param   DataModel &$model  The model which was called | ||||
| 	 * @param   Array     &$keys   The keys used to locate the record which was loaded | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterLoad(&$model, &$keys) | ||||
| 	{ | ||||
| 		// Make sure we have a DataModel | ||||
| 		if (!($model instanceof DataModel)) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Make sure the field actually exists | ||||
| 		if (!$model->hasField('access')) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Get the user | ||||
| 		$user              = $model->getContainer()->platform->getUser(); | ||||
| 		$recordAccessLevel = $model->getFieldValue('access', null); | ||||
|  | ||||
| 		// Filter by authorised access levels | ||||
| 		if (!in_array($recordAccessLevel, $user->getAuthorisedViewLevels())) | ||||
| 		{ | ||||
| 			$model->reset(true); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										198
									
								
								libraries/fof30/Model/DataModel/Behaviour/Assets.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								libraries/fof30/Model/DataModel/Behaviour/Assets.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,198 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use Exception; | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use Joomla\CMS\Access\Rules; | ||||
| use Joomla\CMS\Table\Table; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to add Joomla! ACL assets support | ||||
|  * | ||||
|  * @since    2.1 | ||||
|  */ | ||||
| class Assets extends Observer | ||||
| { | ||||
| 	public function onAfterSave(DataModel &$model) | ||||
| 	{ | ||||
| 		if (!$model->hasField('asset_id') || !$model->isAssetsTracked()) | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		$assetFieldAlias = $model->getFieldAlias('asset_id'); | ||||
| 		$currentAssetId  = $model->getFieldValue('asset_id'); | ||||
|  | ||||
| 		unset($model->$assetFieldAlias); | ||||
|  | ||||
| 		// Create the object used for inserting/updating data to the database | ||||
| 		$fields = $model->getTableFields(); | ||||
|  | ||||
| 		// Let's remove the asset_id field, since we unset the property above and we would get a PHP notice | ||||
| 		if (isset($fields[$assetFieldAlias])) | ||||
| 		{ | ||||
| 			unset($fields[$assetFieldAlias]); | ||||
| 		} | ||||
|  | ||||
| 		// Asset Tracking | ||||
| 		$parentId = $model->getAssetParentId(); | ||||
| 		$name     = $model->getAssetName(); | ||||
| 		$title    = $model->getAssetTitle(); | ||||
|  | ||||
| 		$asset = Table::getInstance('Asset'); | ||||
| 		$asset->loadByName($name); | ||||
|  | ||||
| 		// Re-inject the asset id. | ||||
| 		$this->$assetFieldAlias = $asset->id; | ||||
|  | ||||
| 		// Check for an error. | ||||
| 		$error = $asset->getError(); | ||||
|  | ||||
| 		// Since we are using JTable, there is no way to mock it and test for failures :( | ||||
| 		// @codeCoverageIgnoreStart | ||||
| 		if ($error) | ||||
| 		{ | ||||
| 			throw new Exception($error); | ||||
| 		} | ||||
| 		// @codeCoverageIgnoreEnd | ||||
|  | ||||
| 		// Specify how a new or moved node asset is inserted into the tree. | ||||
| 		// Since we're unsetting the table field before, this statement is always true... | ||||
| 		if (empty($model->$assetFieldAlias) || $asset->parent_id != $parentId) | ||||
| 		{ | ||||
| 			$asset->setLocation($parentId, 'last-child'); | ||||
| 		} | ||||
|  | ||||
| 		// Prepare the asset to be stored. | ||||
| 		$asset->parent_id = $parentId; | ||||
| 		$asset->name      = $name; | ||||
| 		$asset->title     = $title; | ||||
|  | ||||
| 		if ($model->getRules() instanceof Rules) | ||||
| 		{ | ||||
| 			$asset->rules = (string) $model->getRules(); | ||||
| 		} | ||||
|  | ||||
| 		// Since we are using JTable, there is no way to mock it and test for failures :( | ||||
| 		// @codeCoverageIgnoreStart | ||||
| 		if (!$asset->check() || !$asset->store()) | ||||
| 		{ | ||||
| 			throw new Exception($asset->getError()); | ||||
| 		} | ||||
| 		// @codeCoverageIgnoreEnd | ||||
|  | ||||
| 		// Create an asset_id or heal one that is corrupted. | ||||
| 		if (empty($model->$assetFieldAlias) || (($currentAssetId != $model->$assetFieldAlias) && !empty($model->$assetFieldAlias))) | ||||
| 		{ | ||||
| 			// Update the asset_id field in this table. | ||||
| 			$model->$assetFieldAlias = (int) $asset->id; | ||||
|  | ||||
| 			$k = $model->getKeyName(); | ||||
|  | ||||
| 			$db = $model->getDbo(); | ||||
|  | ||||
| 			$query = $db->getQuery(true) | ||||
| 				->update($db->qn($model->getTableName())) | ||||
| 				->set($db->qn($assetFieldAlias) . ' = ' . (int) $model->$assetFieldAlias) | ||||
| 				->where($db->qn($k) . ' = ' . (int) $model->$k); | ||||
|  | ||||
| 			$db->setQuery($query)->execute(); | ||||
| 		} | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	public function onAfterBind(DataModel &$model, &$src) | ||||
| 	{ | ||||
| 		if (!$model->isAssetsTracked()) | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		$rawRules = []; | ||||
|  | ||||
| 		if (is_array($src) && array_key_exists('rules', $src) && is_array($src['rules'])) | ||||
| 		{ | ||||
| 			$rawRules = $src['rules']; | ||||
| 		} | ||||
| 		elseif (is_object($src) && isset($src->rules) && is_array($src->rules)) | ||||
| 		{ | ||||
| 			$rawRules = $src->rules; | ||||
| 		} | ||||
|  | ||||
| 		if (empty($rawRules)) | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		// Bind the rules. | ||||
| 		if (isset($rawRules) && is_array($rawRules)) | ||||
| 		{ | ||||
| 			// We have to manually remove any empty value, since they will be converted to int, | ||||
| 			// and "Inherited" values will become "Denied". Joomla is doing this manually, too. | ||||
| 			$rules = []; | ||||
|  | ||||
| 			foreach ($rawRules as $action => $ids) | ||||
| 			{ | ||||
| 				// Build the rules array. | ||||
| 				$rules[$action] = []; | ||||
|  | ||||
| 				foreach ($ids as $id => $p) | ||||
| 				{ | ||||
| 					if ($p !== '') | ||||
| 					{ | ||||
| 						$rules[$action][$id] = ($p == '1' || $p == 'true') ? true : false; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			$model->setRules($rules); | ||||
| 		} | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	public function onBeforeDelete(DataModel &$model, $oid) | ||||
| 	{ | ||||
| 		if (!$model->isAssetsTracked()) | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		$k = $model->getKeyName(); | ||||
|  | ||||
| 		// If the table is not loaded, let's try to load it with the id | ||||
| 		if (!$model->$k) | ||||
| 		{ | ||||
| 			$model->load($oid); | ||||
| 		} | ||||
|  | ||||
| 		// If I have an invalid assetName I have to stop | ||||
| 		$name = $model->getAssetName(); | ||||
|  | ||||
| 		// Do NOT touch JTable here -- we are loading the core asset table which is a JTable, not a FOF Table | ||||
| 		$asset = Table::getInstance('Asset'); | ||||
|  | ||||
| 		if ($asset->loadByName($name)) | ||||
| 		{ | ||||
| 			// Since we are using JTable, there is no way to mock it and test for failures :( | ||||
| 			// @codeCoverageIgnoreStart | ||||
| 			if (!$asset->delete()) | ||||
| 			{ | ||||
| 				throw new Exception($asset->getError()); | ||||
| 			} | ||||
| 			// @codeCoverageIgnoreEnd | ||||
| 		} | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										100
									
								
								libraries/fof30/Model/DataModel/Behaviour/ContentHistory.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								libraries/fof30/Model/DataModel/Behaviour/ContentHistory.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use Joomla\CMS\Component\ComponentHelper; | ||||
| use Joomla\CMS\Helper\ContentHistoryHelper; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to add Joomla! content history support | ||||
|  * | ||||
|  * @since    2.1 | ||||
|  */ | ||||
| class ContentHistory extends Observer | ||||
| { | ||||
| 	/** @var  ContentHistoryHelper */ | ||||
| 	protected $historyHelper; | ||||
|  | ||||
| 	/** | ||||
| 	 * The event which runs after storing (saving) data to the database | ||||
| 	 * | ||||
| 	 * @param   DataModel  &$model  The model which calls this event | ||||
| 	 * | ||||
| 	 * @return  boolean  True to allow saving without an error | ||||
| 	 */ | ||||
| 	public function onAfterSave(&$model) | ||||
| 	{ | ||||
| 		$aliasParts = explode('.', $model->getContentType()); | ||||
| 		$model->checkContentType(); | ||||
|  | ||||
| 		if (ComponentHelper::getParams($aliasParts[0])->get('save_history', 0)) | ||||
| 		{ | ||||
| 			if (!$this->historyHelper) | ||||
| 			{ | ||||
| 				$this->historyHelper = new ContentHistoryHelper($model->getContentType()); | ||||
| 			} | ||||
|  | ||||
| 			$this->historyHelper->store($model); | ||||
| 		} | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * The event which runs before deleting a record | ||||
| 	 * | ||||
| 	 * @param   DataModel &$model  The model which calls this event | ||||
| 	 * @param   integer    $oid    The PK value of the record to delete | ||||
| 	 * | ||||
| 	 * @return  boolean  True to allow the deletion | ||||
| 	 */ | ||||
| 	public function onBeforeDelete(&$model, $oid) | ||||
| 	{ | ||||
| 		$aliasParts = explode('.', $model->getContentType()); | ||||
|  | ||||
| 		if (ComponentHelper::getParams($aliasParts[0])->get('save_history', 0)) | ||||
| 		{ | ||||
| 			if (!$this->historyHelper) | ||||
| 			{ | ||||
| 				$this->historyHelper = new ContentHistoryHelper($model->getContentType()); | ||||
| 			} | ||||
|  | ||||
| 			$this->historyHelper->deleteHistory($model); | ||||
| 		} | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * This event runs after publishing a record in a model | ||||
| 	 * | ||||
| 	 * @param   DataModel  &$model  The model which calls this event | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterPublish(&$model) | ||||
| 	{ | ||||
| 		$model->updateUcmContent(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * This event runs after unpublishing a record in a model | ||||
| 	 * | ||||
| 	 * @param   DataModel  &$model  The model which calls this event | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterUnpublish(&$model) | ||||
| 	{ | ||||
| 		$model->updateUcmContent(); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										73
									
								
								libraries/fof30/Model/DataModel/Behaviour/Created.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								libraries/fof30/Model/DataModel/Behaviour/Created.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use stdClass; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to updated the created_by and created_on fields on newly created records. | ||||
|  * | ||||
|  * This behaviour is added to DataModel by default. If you want to remove it you need to do | ||||
|  * $this->behavioursDispatcher->removeBehaviour('Created'); | ||||
|  * | ||||
|  * @since  3.0 | ||||
|  */ | ||||
| class Created extends Observer | ||||
| { | ||||
| 	/** | ||||
| 	 * Add the created_on and created_by fields in the fieldsSkipChecks list of the model. We expect them to be empty | ||||
| 	 * so that we can fill them in through this behaviour. | ||||
| 	 * | ||||
| 	 * @param   DataModel  $model | ||||
| 	 */ | ||||
| 	public function onBeforeCheck(&$model) | ||||
| 	{ | ||||
| 		$model->addSkipCheckField('created_on'); | ||||
| 		$model->addSkipCheckField('created_by'); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param   DataModel  $model | ||||
| 	 * @param   stdClass  $dataObject | ||||
| 	 */ | ||||
| 	public function onBeforeCreate(&$model, &$dataObject) | ||||
| 	{ | ||||
| 		// Handle the created_on field | ||||
| 		if ($model->hasField('created_on')) | ||||
| 		{ | ||||
| 			$nullDate   = $model->isNullableField('created_on') ? null : $model->getDbo()->getNullDate(); | ||||
| 			$created_on = $model->getFieldValue('created_on'); | ||||
|  | ||||
| 			if (empty($created_on) || ($created_on == $nullDate)) | ||||
| 			{ | ||||
| 				$model->setFieldValue('created_on', $model->getContainer()->platform->getDate()->toSql(false, $model->getDbo())); | ||||
|  | ||||
| 				$createdOnField              = $model->getFieldAlias('created_on'); | ||||
| 				$dataObject->$createdOnField = $model->getFieldValue('created_on'); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Handle the created_by field | ||||
| 		if ($model->hasField('created_by')) | ||||
| 		{ | ||||
| 			$created_by = $model->getFieldValue('created_by'); | ||||
|  | ||||
| 			if (empty($created_by)) | ||||
| 			{ | ||||
| 				$model->setFieldValue('created_by', $model->getContainer()->platform->getUser()->id); | ||||
|  | ||||
| 				$createdByField              = $model->getFieldAlias('created_by'); | ||||
| 				$dataObject->$createdByField = $model->getFieldValue('created_by'); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										36
									
								
								libraries/fof30/Model/DataModel/Behaviour/EmptyNonZero.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								libraries/fof30/Model/DataModel/Behaviour/EmptyNonZero.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use JDatabaseQuery; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to let the Filters behaviour know that zero value is a valid filter value | ||||
|  * | ||||
|  * @since    2.1 | ||||
|  */ | ||||
| class EmptyNonZero extends Observer | ||||
| { | ||||
| 	/** | ||||
| 	 * This event runs after we have built the query used to fetch a record | ||||
| 	 * list in a model. It is used to apply automatic query filters. | ||||
| 	 * | ||||
| 	 * @param   DataModel      &$model  The model which calls this event | ||||
| 	 * @param   JDatabaseQuery &$query  The query we are manipulating | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterBuildQuery(&$model, &$query) | ||||
| 	{ | ||||
| 		$model->setBehaviorParam('filterZero', 1); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										75
									
								
								libraries/fof30/Model/DataModel/Behaviour/Enabled.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								libraries/fof30/Model/DataModel/Behaviour/Enabled.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use JDatabaseQuery; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to filter access to items based on the enabled status | ||||
|  * | ||||
|  * @since    2.1 | ||||
|  */ | ||||
| class Enabled extends Observer | ||||
| { | ||||
| 	/** | ||||
| 	 * This event runs before we have built the query used to fetch a record | ||||
| 	 * list in a model. It is used to apply automatic query filters. | ||||
| 	 * | ||||
| 	 * @param   DataModel      &$model  The model which calls this event | ||||
| 	 * @param   JDatabaseQuery &$query  The query we are manipulating | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onBeforeBuildQuery(&$model, &$query) | ||||
| 	{ | ||||
| 		// Make sure the field actually exists | ||||
| 		if (!$model->hasField('enabled')) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$fieldName = $model->getFieldAlias('enabled'); | ||||
| 		$db        = $model->getDbo(); | ||||
|  | ||||
| 		$model->whereRaw($db->qn($fieldName) . ' = ' . $db->q(1)); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * The event runs after DataModel has retrieved a single item from the database. It is used to apply automatic | ||||
| 	 * filters. | ||||
| 	 * | ||||
| 	 * @param   DataModel &$model  The model which was called | ||||
| 	 * @param   Array     &$keys   The keys used to locate the record which was loaded | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterLoad(&$model, &$keys) | ||||
| 	{ | ||||
| 		// Make sure we have a DataModel | ||||
| 		if (!($model instanceof DataModel)) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Make sure the field actually exists | ||||
| 		if (!$model->hasField('enabled')) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Filter by enabled status | ||||
| 		if (!$model->getFieldValue('enabled', 0)) | ||||
| 		{ | ||||
| 			$model->reset(true); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										133
									
								
								libraries/fof30/Model/DataModel/Behaviour/Filters.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								libraries/fof30/Model/DataModel/Behaviour/Filters.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,133 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use JDatabaseQuery; | ||||
| use Joomla\Registry\Registry; | ||||
|  | ||||
| class Filters extends Observer | ||||
| { | ||||
| 	/** | ||||
| 	 * This event runs after we have built the query used to fetch a record | ||||
| 	 * list in a model. It is used to apply automatic query filters. | ||||
| 	 * | ||||
| 	 * @param   DataModel  &         $model  The model which calls this event | ||||
| 	 * @param   JDatabaseQuery      &$query  The query we are manipulating | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterBuildQuery(&$model, &$query) | ||||
| 	{ | ||||
| 		$tableKey = $model->getIdFieldName(); | ||||
| 		$db       = $model->getDbo(); | ||||
|  | ||||
| 		$fields     = $model->getTableFields(); | ||||
| 		$blacklist  = $model->getBlacklistFilters(); | ||||
| 		$filterZero = $model->getBehaviorParam('filterZero', null); | ||||
| 		$tableAlias = $model->getBehaviorParam('tableAlias', null); | ||||
|  | ||||
| 		foreach ($fields as $fieldname => $fieldmeta) | ||||
| 		{ | ||||
| 			if (in_array($fieldname, $blacklist)) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			$fieldInfo = (object) [ | ||||
| 				'name'       => $fieldname, | ||||
| 				'type'       => $fieldmeta->Type, | ||||
| 				'filterZero' => $filterZero, | ||||
| 				'tableAlias' => $tableAlias, | ||||
| 			]; | ||||
|  | ||||
| 			$filterName  = $fieldInfo->name; | ||||
| 			$filterState = $model->getState($filterName, null); | ||||
|  | ||||
| 			// Special primary key handling: if ignore request is set we'll also look for an 'id' state variable if a | ||||
| 			// state variable by the same name as the key doesn't exist. If ignore request is not set in the model we | ||||
| 			// do not filter by 'id' since this interferes with going from an edit page to a browse page (the list is | ||||
| 			// filtered by id without user controls to unset it). | ||||
| 			if ($fieldInfo->name == $tableKey) | ||||
| 			{ | ||||
| 				$filterState = $model->getState($filterName, null); | ||||
|  | ||||
| 				if (!$model->getIgnoreRequest()) | ||||
| 				{ | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				if (empty($filterState)) | ||||
| 				{ | ||||
| 					$filterState = $model->getState('id', null); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			$field = DataModel\Filter\AbstractFilter::getField($fieldInfo, ['dbo' => $db]); | ||||
|  | ||||
| 			if (!is_object($field) || !($field instanceof DataModel\Filter\AbstractFilter)) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			if ((is_array($filterState) && ( | ||||
| 						array_key_exists('value', $filterState) || | ||||
| 						array_key_exists('from', $filterState) || | ||||
| 						array_key_exists('to', $filterState) | ||||
| 					)) || is_object($filterState)) | ||||
| 			{ | ||||
| 				$options = class_exists('JRegistry') ? new Registry($filterState) : new Registry($filterState); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				$options = class_exists('JRegistry') ? new Registry() : new Registry(); | ||||
| 				$options->set('value', $filterState); | ||||
| 			} | ||||
|  | ||||
| 			$methods = $field->getSearchMethods(); | ||||
| 			$method  = $options->get('method', $field->getDefaultSearchMethod()); | ||||
|  | ||||
| 			if (!in_array($method, $methods)) | ||||
| 			{ | ||||
| 				$method = 'exact'; | ||||
| 			} | ||||
|  | ||||
| 			switch ($method) | ||||
| 			{ | ||||
| 				case 'between': | ||||
| 				case 'outside': | ||||
| 				case 'range' : | ||||
| 					$sql = $field->$method($options->get('from', null), $options->get('to', null), $options->get('include', false)); | ||||
| 					break; | ||||
|  | ||||
| 				case 'interval': | ||||
| 				case 'modulo': | ||||
| 					$sql = $field->$method($options->get('value', null), $options->get('interval')); | ||||
| 					break; | ||||
|  | ||||
| 				case 'search': | ||||
| 					$sql = $field->$method($options->get('value', null), $options->get('operator', '=')); | ||||
| 					break; | ||||
|  | ||||
| 				case 'exact': | ||||
| 				case 'partial': | ||||
| 				default: | ||||
| 					$sql = $field->$method($options->get('value', null)); | ||||
| 					break; | ||||
| 			} | ||||
|  | ||||
| 			if ($sql) | ||||
| 			{ | ||||
| 				$query->where($sql); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										171
									
								
								libraries/fof30/Model/DataModel/Behaviour/Language.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								libraries/fof30/Model/DataModel/Behaviour/Language.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,171 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use JDatabaseQuery; | ||||
| use Joomla\CMS\Application\SiteApplication; | ||||
| use Joomla\CMS\Factory; | ||||
| use Joomla\CMS\Plugin\PluginHelper; | ||||
| use Joomla\Registry\Registry; | ||||
| use PlgSystemLanguageFilter; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to filter front-end access to items | ||||
|  * based on the language. | ||||
|  * | ||||
|  * @since    2.1 | ||||
|  */ | ||||
| class Language extends Observer | ||||
| { | ||||
| 	/** @var  PlgSystemLanguageFilter */ | ||||
| 	protected $lang_filter_plugin; | ||||
|  | ||||
| 	/** | ||||
| 	 * This event runs before we have built the query used to fetch a record | ||||
| 	 * list in a model. It is used to blacklist the language filter | ||||
| 	 * | ||||
| 	 * @param   DataModel       &$model  The model which calls this event | ||||
| 	 * @param   JDatabaseQuery  &$query  The model which calls this event | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onBeforeBuildQuery(&$model, &$query) | ||||
| 	{ | ||||
| 		if ($model->getContainer()->platform->isFrontend()) | ||||
| 		{ | ||||
| 			$model->blacklistFilters('language'); | ||||
| 		} | ||||
|  | ||||
| 		// Make sure the field actually exists AND we're not in CLI | ||||
| 		if (!$model->hasField('language') || $model->getContainer()->platform->isCli()) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		/** @var SiteApplication $app */ | ||||
| 		$app               = Factory::getApplication(); | ||||
| 		$hasLanguageFilter = method_exists($app, 'getLanguageFilter'); | ||||
|  | ||||
| 		if ($hasLanguageFilter) | ||||
| 		{ | ||||
| 			$hasLanguageFilter = $app->getLanguageFilter(); | ||||
| 		} | ||||
|  | ||||
| 		if (!$hasLanguageFilter) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Ask Joomla for the plugin only if we don't already have it. Useful for tests | ||||
| 		if (!$this->lang_filter_plugin) | ||||
| 		{ | ||||
| 			$this->lang_filter_plugin = PluginHelper::getPlugin('system', 'languagefilter'); | ||||
| 		} | ||||
|  | ||||
| 		$lang_filter_params = class_exists('JRegistry') ? new Registry($this->lang_filter_plugin->params) : new Registry($this->lang_filter_plugin->params); | ||||
|  | ||||
| 		$languages = ['*']; | ||||
|  | ||||
| 		if ($lang_filter_params->get('remove_default_prefix')) | ||||
| 		{ | ||||
| 			// Get default site language | ||||
| 			$platform    = $model->getContainer()->platform; | ||||
| 			$lg          = $platform->getLanguage(); | ||||
| 			$languages[] = $lg->getTag(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			// We have to use JInput since the language fragment is not set in the $_REQUEST, thus we won't have it in our model | ||||
| 			// TODO Double check the previous assumption | ||||
| 			$languages[] = Factory::getApplication()->input->getCmd('language', '*'); | ||||
| 		} | ||||
|  | ||||
| 		// Filter out double languages | ||||
| 		$languages = array_unique($languages); | ||||
|  | ||||
| 		// And filter the query output by these languages | ||||
| 		$db        = $model->getDbo(); | ||||
| 		$languages = array_map([$db, 'quote'], $languages); | ||||
| 		$fieldName = $model->getFieldAlias('language'); | ||||
|  | ||||
| 		$model->whereRaw($db->qn($fieldName) . ' IN(' . implode(', ', $languages) . ')'); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * The event runs after DataModel has retrieved a single item from the database. It is used to apply automatic | ||||
| 	 * filters. | ||||
| 	 * | ||||
| 	 * @param   DataModel &$model  The model which was called | ||||
| 	 * @param   Array     &$keys   The keys used to locate the record which was loaded | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterLoad(&$model, &$keys) | ||||
| 	{ | ||||
| 		// Make sure we have a DataModel | ||||
| 		if (!($model instanceof DataModel)) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Make sure the field actually exists AND we're not in CLI | ||||
| 		if (!$model->hasField('language') || $model->getContainer()->platform->isCli()) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Make sure it is a multilingual site and get a list of languages | ||||
| 		/** @var SiteApplication $app */ | ||||
| 		$app               = Factory::getApplication(); | ||||
| 		$hasLanguageFilter = method_exists($app, 'getLanguageFilter'); | ||||
|  | ||||
| 		if ($hasLanguageFilter) | ||||
| 		{ | ||||
| 			$hasLanguageFilter = $app->getLanguageFilter(); | ||||
| 		} | ||||
|  | ||||
| 		if (!$hasLanguageFilter) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Ask Joomla for the plugin only if we don't already have it. Useful for tests | ||||
| 		if (!$this->lang_filter_plugin) | ||||
| 		{ | ||||
| 			$this->lang_filter_plugin = PluginHelper::getPlugin('system', 'languagefilter'); | ||||
| 		} | ||||
|  | ||||
| 		$lang_filter_params = class_exists('JRegistry') ? new Registry($this->lang_filter_plugin->params) : new Registry($this->lang_filter_plugin->params); | ||||
|  | ||||
| 		$languages = ['*']; | ||||
|  | ||||
| 		if ($lang_filter_params->get('remove_default_prefix')) | ||||
| 		{ | ||||
| 			// Get default site language | ||||
| 			$lg          = $model->getContainer()->platform->getLanguage(); | ||||
| 			$languages[] = $lg->getTag(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			$languages[] = Factory::getApplication()->input->getCmd('language', '*'); | ||||
| 		} | ||||
|  | ||||
| 		// Filter out double languages | ||||
| 		$languages = array_unique($languages); | ||||
|  | ||||
| 		// Filter by language | ||||
| 		if (!in_array($model->getFieldValue('language'), $languages)) | ||||
| 		{ | ||||
| 			$model->reset(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										71
									
								
								libraries/fof30/Model/DataModel/Behaviour/Modified.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								libraries/fof30/Model/DataModel/Behaviour/Modified.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use stdClass; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to updated the modified_by and modified_on fields on newly created records. | ||||
|  * | ||||
|  * This behaviour is added to DataModel by default. If you want to remove it you need to do | ||||
|  * $this->behavioursDispatcher->removeBehaviour('Modified'); | ||||
|  * | ||||
|  * @since  3.0 | ||||
|  */ | ||||
| class Modified extends Observer | ||||
| { | ||||
| 	/** | ||||
| 	 * Add the modified_on and modified_by fields in the fieldsSkipChecks list of the model. We expect them to be empty | ||||
| 	 * so that we can fill them in through this behaviour. | ||||
| 	 * | ||||
| 	 * @param   DataModel  $model | ||||
| 	 */ | ||||
| 	public function onBeforeCheck(&$model) | ||||
| 	{ | ||||
| 		$model->addSkipCheckField('modified_on'); | ||||
| 		$model->addSkipCheckField('modified_by'); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param   DataModel  $model | ||||
| 	 * @param   stdClass  $dataObject | ||||
| 	 */ | ||||
| 	public function onBeforeUpdate(&$model, &$dataObject) | ||||
| 	{ | ||||
| 		// Make sure we're not modifying a locked record | ||||
| 		$userId   = $model->getContainer()->platform->getUser()->id; | ||||
| 		$isLocked = $model->isLocked($userId); | ||||
|  | ||||
| 		if ($isLocked) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Handle the modified_on field | ||||
| 		if ($model->hasField('modified_on')) | ||||
| 		{ | ||||
| 			$model->setFieldValue('modified_on', $model->getContainer()->platform->getDate()->toSql(false, $model->getDbo())); | ||||
|  | ||||
| 			$modifiedOnField              = $model->getFieldAlias('modified_on'); | ||||
| 			$dataObject->$modifiedOnField = $model->getFieldValue('modified_on'); | ||||
| 		} | ||||
|  | ||||
| 		// Handle the modified_by field | ||||
| 		if ($model->hasField('modified_by')) | ||||
| 		{ | ||||
| 			$model->setFieldValue('modified_by', $userId); | ||||
|  | ||||
| 			$modifiedByField              = $model->getFieldAlias('modified_by'); | ||||
| 			$dataObject->$modifiedByField = $model->getFieldValue('modified_by'); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										82
									
								
								libraries/fof30/Model/DataModel/Behaviour/Own.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								libraries/fof30/Model/DataModel/Behaviour/Own.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use JDatabaseQuery; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to filter access to items owned by the currently logged in user only | ||||
|  * | ||||
|  * @since    2.1 | ||||
|  */ | ||||
| class Own extends Observer | ||||
| { | ||||
| 	/** | ||||
| 	 * This event runs after we have built the query used to fetch a record | ||||
| 	 * list in a model. It is used to apply automatic query filters. | ||||
| 	 * | ||||
| 	 * @param   DataModel      &$model  The model which calls this event | ||||
| 	 * @param   JDatabaseQuery &$query  The query we are manipulating | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterBuildQuery(&$model, &$query) | ||||
| 	{ | ||||
| 		// Make sure the field actually exists | ||||
| 		if (!$model->hasField('created_by')) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Get the current user's id | ||||
| 		$user_id = $model->getContainer()->platform->getUser()->id; | ||||
|  | ||||
| 		// And filter the query output by the user id | ||||
| 		$db = $model->getContainer()->platform->getDbo(); | ||||
|  | ||||
| 		$query->where($db->qn($model->getFieldAlias('created_by')) . ' = ' . $db->q($user_id)); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * The event runs after DataModel has retrieved a single item from the database. It is used to apply automatic | ||||
| 	 * filters. | ||||
| 	 * | ||||
| 	 * @param   DataModel &$model  The model which was called | ||||
| 	 * @param   Array     &$keys   The keys used to locate the record which was loaded | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterLoad(&$model, &$keys) | ||||
| 	{ | ||||
| 		// Make sure we have a DataModel | ||||
| 		if (!($model instanceof DataModel)) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Make sure the field actually exists | ||||
| 		if (!$model->hasField('created_by')) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Get the user | ||||
| 		$user_id    = $model->getContainer()->platform->getUser()->id; | ||||
| 		$recordUser = $model->getFieldValue('created_by', null); | ||||
|  | ||||
| 		// Filter by authorised access levels | ||||
| 		if ($recordUser != $user_id) | ||||
| 		{ | ||||
| 			$model->reset(true); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,66 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use Joomla\CMS\Application\SiteApplication; | ||||
| use Joomla\CMS\Factory; | ||||
| use Joomla\Registry\Registry; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to populate the state with the front-end page parameters | ||||
|  * | ||||
|  * @since    2.1 | ||||
|  */ | ||||
| class PageParametersToState extends Observer | ||||
| { | ||||
| 	public function onAfterConstruct(DataModel &$model) | ||||
| 	{ | ||||
| 		// This only applies to the front-end | ||||
| 		if (!$model->getContainer()->platform->isFrontend()) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Get the page parameters | ||||
| 		/** @var SiteApplication $app */ | ||||
| 		$app = Factory::getApplication(); | ||||
| 		/** @var Registry|Registry $params */ | ||||
| 		$params = $app->getParams(); | ||||
|  | ||||
| 		// Extract the page parameter keys | ||||
| 		$asArray = $params->toArray(); | ||||
|  | ||||
| 		if (empty($asArray)) | ||||
| 		{ | ||||
| 			// There are no keys; no point in going on. | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$keys = array_keys($asArray); | ||||
| 		unset($asArray); | ||||
|  | ||||
| 		// Loop all page parameter keys | ||||
| 		foreach ($keys as $key) | ||||
| 		{ | ||||
| 			// This is the current model state | ||||
| 			$currentState = $model->getState($key); | ||||
| 			// This is the explicitly requested state in the input | ||||
| 			$explicitInput = $model->input->get($key, null, 'raw'); | ||||
|  | ||||
| 			// If the current state is empty and there's no explicit input we'll use the page parameters instead | ||||
| 			if (is_null($currentState) && is_null($explicitInput)) | ||||
| 			{ | ||||
| 				$model->setState($key, $params->get($key)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,85 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use JDatabaseQuery; | ||||
| use Joomla\Registry\Registry; | ||||
|  | ||||
| class RelationFilters extends Observer | ||||
| { | ||||
| 	/** | ||||
| 	 * This event runs after we have built the query used to fetch a record list in a model. It is used to apply | ||||
| 	 * automatic query filters based on model relations. | ||||
| 	 * | ||||
| 	 * @param   DataModel  &          $model  The model which calls this event | ||||
| 	 * @param   JDatabaseQuery      & $query  The query we are manipulating | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterBuildQuery(&$model, &$query) | ||||
| 	{ | ||||
| 		$relationFilters = $model->getRelationFilters(); | ||||
|  | ||||
| 		foreach ($relationFilters as $filterState) | ||||
| 		{ | ||||
| 			$relationName = $filterState['relation']; | ||||
|  | ||||
| 			$tableAlias = $model->getBehaviorParam('tableAlias', null); | ||||
| 			$subQuery   = $model->getRelations()->getCountSubquery($relationName, $tableAlias); | ||||
|  | ||||
| 			// Callback method needs different handling | ||||
| 			if (isset($filterState['method']) && ($filterState['method'] == 'callback')) | ||||
| 			{ | ||||
| 				call_user_func_array($filterState['value'], [&$subQuery]); | ||||
| 				$filterState['method']   = 'search'; | ||||
| 				$filterState['operator'] = '>='; | ||||
| 				$filterState['value']    = '1'; | ||||
| 			} | ||||
|  | ||||
| 			$options = class_exists('JRegistry') ? new Registry($filterState) : new Registry($filterState); | ||||
|  | ||||
| 			$filter  = new DataModel\Filter\Relation($model->getDbo(), $relationName, $subQuery); | ||||
| 			$methods = $filter->getSearchMethods(); | ||||
| 			$method  = $options->get('method', $filter->getDefaultSearchMethod()); | ||||
|  | ||||
| 			if (!in_array($method, $methods)) | ||||
| 			{ | ||||
| 				$method = 'exact'; | ||||
| 			} | ||||
|  | ||||
| 			switch ($method) | ||||
| 			{ | ||||
| 				case 'between': | ||||
| 				case 'outside': | ||||
| 					$sql = $filter->$method($options->get('from', null), $options->get('to')); | ||||
| 					break; | ||||
|  | ||||
| 				case 'interval': | ||||
| 					$sql = $filter->$method($options->get('value', null), $options->get('interval')); | ||||
| 					break; | ||||
|  | ||||
| 				case 'search': | ||||
| 					$sql = $filter->$method($options->get('value', null), $options->get('operator', '=')); | ||||
| 					break; | ||||
|  | ||||
| 				default: | ||||
| 					$sql = $filter->$method($options->get('value', null)); | ||||
| 					break; | ||||
| 			} | ||||
|  | ||||
| 			if ($sql) | ||||
| 			{ | ||||
| 				$query->where($sql); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										171
									
								
								libraries/fof30/Model/DataModel/Behaviour/Tags.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								libraries/fof30/Model/DataModel/Behaviour/Tags.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,171 @@ | ||||
| <?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\Behaviour; | ||||
|  | ||||
| defined('_JEXEC') || die; | ||||
|  | ||||
| use Exception; | ||||
| use FOF30\Event\Observable; | ||||
| use FOF30\Event\Observer; | ||||
| use FOF30\Model\DataModel; | ||||
| use Joomla\CMS\Helper\TagsHelper; | ||||
| use stdClass; | ||||
|  | ||||
| /** | ||||
|  * FOF model behavior class to add Joomla! Tags support | ||||
|  * | ||||
|  * @since    2.1 | ||||
|  */ | ||||
| class Tags extends Observer | ||||
| { | ||||
| 	/** @var TagsHelper */ | ||||
| 	protected $tagsHelper; | ||||
|  | ||||
| 	public function __construct(Observable &$subject) | ||||
| 	{ | ||||
| 		parent::__construct($subject); | ||||
|  | ||||
| 		$this->tagsHelper = new TagsHelper(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * This event runs after unpublishing a record in a model | ||||
| 	 * | ||||
| 	 * @param   DataModel  &$model       The model which calls this event | ||||
| 	 * @param   stdClass  & $dataObject  The data to bind to the form | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onBeforeCreate(&$model, &$dataObject) | ||||
| 	{ | ||||
| 		$tagField = $model->getBehaviorParam('tagFieldName', 'tags'); | ||||
|  | ||||
| 		unset($dataObject->$tagField); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * This event runs after unpublishing a record in a model | ||||
| 	 * | ||||
| 	 * @param   DataModel  &$model       The model which calls this event | ||||
| 	 * @param   stdClass  & $dataObject  The data to bind to the form | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onBeforeUpdate(&$model, &$dataObject) | ||||
| 	{ | ||||
| 		$tagField = $model->getBehaviorParam('tagFieldName', 'tags'); | ||||
|  | ||||
| 		unset($dataObject->$tagField); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * The event which runs after binding data to the table | ||||
| 	 * | ||||
| 	 * @param   DataModel    &$model  The model which calls this event | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 * | ||||
| 	 * @throws  Exception  Error message if failed to store tags | ||||
| 	 */ | ||||
| 	public function onAfterSave(&$model) | ||||
| 	{ | ||||
| 		$tagField = $model->getBehaviorParam('tagFieldName', 'tags'); | ||||
|  | ||||
| 		// Avoid to update on other method (e.g. publish, ...) | ||||
| 		if (!in_array($model->getContainer()->input->getCmd('task'), ['apply', 'save', 'savenew'])) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$oldTags = $this->tagsHelper->getTagIds($model->getId(), $model->getContentType()); | ||||
| 		$newTags = $model->$tagField ? implode(',', $model->$tagField) : null; | ||||
|  | ||||
| 		// If no changes, we stop here | ||||
| 		if ($oldTags == $newTags) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Check if the content type exists, and create it if it does not | ||||
| 		$model->checkContentType(); | ||||
|  | ||||
| 		$this->tagsHelper->typeAlias = $model->getContentType(); | ||||
|  | ||||
| 		if (!$this->tagsHelper->postStoreProcess($model, $model->$tagField)) | ||||
| 		{ | ||||
| 			throw new Exception('Error storing tags'); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * The event which runs after deleting a record | ||||
| 	 * | ||||
| 	 * @param   DataModel &$model  The model which calls this event | ||||
| 	 * @param   integer    $oid    The PK value of the record which was deleted | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 * | ||||
| 	 * @throws  Exception  Error message if failed to delete tags | ||||
| 	 */ | ||||
| 	public function onAfterDelete(&$model, $oid) | ||||
| 	{ | ||||
| 		$this->tagsHelper->typeAlias = $model->getContentType(); | ||||
|  | ||||
| 		if (!$this->tagsHelper->deleteTagData($model, $oid)) | ||||
| 		{ | ||||
| 			throw new Exception('Error deleting Tags'); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * This event runs after unpublishing a record in a model | ||||
| 	 * | ||||
| 	 * @param   DataModel  &$model  The model which calls this event | ||||
| 	 * @param   mixed       $data   An associative array or object to bind to the DataModel instance. | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterBind(&$model, &$data) | ||||
| 	{ | ||||
| 		$tagField = $model->getBehaviorParam('tagFieldName', 'tags'); | ||||
|  | ||||
| 		if ($model->$tagField) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$type = $model->getContentType(); | ||||
|  | ||||
| 		$model->addKnownField($tagField); | ||||
| 		$model->$tagField = $this->tagsHelper->getTagIds($model->getId(), $type); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * This event runs after publishing a record in a model | ||||
| 	 * | ||||
| 	 * @param   DataModel  &$model  The model which calls this event | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterPublish(&$model) | ||||
| 	{ | ||||
| 		$model->updateUcmContent(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * This event runs after unpublishing a record in a model | ||||
| 	 * | ||||
| 	 * @param   DataModel  &$model  The model which calls this event | ||||
| 	 * | ||||
| 	 * @return  void | ||||
| 	 */ | ||||
| 	public function onAfterUnpublish(&$model) | ||||
| 	{ | ||||
| 		$model->updateUcmContent(); | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user