Spade

Mini Shell

Directory:~$ /home/lmsyaran/public_html/joomla4/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ /home/lmsyaran/public_html/joomla4/Model.tar

AdminModel.php000064400000035421151155743370007306 0ustar00<?php
/**
 * @package     OSL
 * @subpackage  Controller
 *
 * @copyright   Copyright (C) 2016 Ossolution Team, Inc. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

namespace OSL\Model;

use Exception;

use Joomla\Registry\Registry, Joomla\String\StringHelper, JFactory,
	JPluginHelper, JLanguageMultilang, JTable, JApplicationHelper;

use OSL\Container\Container,
	OSL\Input\Input;

/**
 * Admin model class. It will handle tasks such as add, update, delete,
publish, unpublish...items
 *
 * @package        OSF
 * @subpackage     Model
 * @since          1.0
 */
class AdminModel extends Model
{
	/**
	 * Context, used to get user session data and also trigger plugin
	 *
	 * @var string
	 */
	protected $context;

	/**
	 * The prefix to use with controller messages.
	 *
	 * @var string
	 */
	protected $languagePrefix = null;

	/**
	 * This model trigger events or not. By default, set it to No to improve
performance
	 *
	 * @var boolean
	 */
	protected $triggerEvents = false;

	/**
	 * The event to trigger after deleting the data.
	 *
	 * @var string
	 */
	protected $eventAfterDelete = null;

	/**
	 * The event to trigger after saving the data.
	 *
	 * @var string
	 */
	protected $eventAfterSave = null;

	/**
	 * The event to trigger before deleting the data.
	 *
	 * @var string
	 */
	protected $eventBeforeDelete = null;

	/**
	 * The event to trigger before saving the data.
	 *
	 * @var string
	 */
	protected $eventBeforeSave = null;

	/**
	 * The event to trigger after changing the published state of the data.
	 *
	 * @var string
	 */
	protected $eventChangeState = null;

	/**
	 * Name of plugin group which will be loaded to process the triggered
event.
	 * Default is component name
	 *
	 * @var string
	 */
	protected $pluginGroup = null;

	/**
	 * Data for the item
	 *
	 * @var object
	 */
	protected $data = null;

	/**
	 * Constructor.
	 *
	 * @param mixed $config An object store model configuration
	 *
	 * @see OSFModel
	 */
	public function __construct(Container $container, $config = [])
	{
		parent::__construct($container, $config);

		/**@var Registry $config * */

		$this->context = $this->container->option . '.' .
$this->name;

		//Insert the default model states for admin
		$this->state->insert('id', 'int',
0)->insert('cid', 'array', []);

		if ($this->triggerEvents)
		{
			$name = ucfirst($this->name);

			if (isset($config['plugin_group']))
			{
				$this->pluginGroup = $config['plugin_group'];
			}
			elseif (empty($this->pluginGroup))
			{
				//Plugin group should default to component name
				$this->pluginGroup = substr($this->container->option, 4);
			}

			//Initialize the events
			if (isset($config['event_after_delete']))
			{
				$this->eventAfterDelete = $config['event_after_delete'];
			}
			elseif (empty($this->eventAfterDelete))
			{
				$this->eventAfterDelete = 'on' . $name .
'AfterDelete';
			}

			if (isset($config['event_after_save']))
			{
				$this->eventAfterSave = $config['event_after_save'];
			}
			elseif (empty($this->eventAfterSave))
			{
				$this->eventAfterSave = 'on' . $name .
'AfterSave';
			}

			if (isset($config['event_before_delete']))
			{
				$this->eventBeforeDelete =
$config['event_before_delete'];
			}
			elseif (empty($this->eventBeforeDelete))
			{
				$this->eventBeforeDelete = 'on' . $name .
'BeforeDelete';
			}

			if (isset($config['event_before_save']))
			{
				$this->eventBeforeSave = $config['event_before_save'];
			}
			elseif (empty($this->eventBeforeSave))
			{
				$this->eventBeforeSave = 'on' . $name .
'BeforeSave';
			}

			if (isset($config['event_change_state']))
			{
				$this->eventChangeState = $config['event_change_state'];
			}
			elseif (empty($this->eventChangeState))
			{
				$this->eventChangeState = 'on' . $name .
'ChangeState';
			}
		}

		if (empty($this->languagePrefix))
		{
			$this->languagePrefix = $this->container->languagePrefix;
		}
	}

	/**
	 * Method to get the record data
	 *
	 * @return object
	 */
	public function getData()
	{
		if (empty($this->data))
		{
			if (count($this->state->cid))
			{
				$this->state->id = (int) $this->state->cid[0];
			}

			if ($this->state->id)
			{
				$this->loadData();
			}
			else
			{
				$this->initData();
			}
		}

		return $this->data;
	}

	/**
	 * Method to store a record
	 *
	 * @param Input $input
	 * @param array $ignore
	 *
	 * @return bool
	 * @throws Exception
	 */
	public function store($input, $ignore = [])
	{
		if ($this->triggerEvents)
		{
			JPluginHelper::importPlugin($this->pluginGroup);
		}

		$row   = $this->getTable();
		$isNew = true;
		$id    = $input->getInt('id', 0);

		if ($id)
		{
			$isNew = false;
			$row->load($id);
		}

		// Pre-process the input data
		$this->beforeStore($row, $input, $isNew);

		if ($this->container->user->authorise('core.admin',
'com_pmform'))
		{
			$data = $input->getData(\OSL\Input\Input::INPUT_ALLOWRAW);
		}
		else
		{
			$data = $input->getData();
		}

		$row->bind($data, $ignore);
		$this->prepareTable($row, $input->get('task'));
		$row->check();

		if ($this->triggerEvents)
		{
			$this->container->app->triggerEvent($this->eventBeforeSave,
[$row, $data, $isNew]);
		}

		$row->store();

		if ($this->triggerEvents)
		{
			$this->container->app->triggerEvent($this->eventAfterSave,
[$row, $data, $isNew]);
		}

		$input->set('id', $row->id);

		// Post process after the record stored into database
		$this->afterStore($row, $input, $isNew);
	}

	/**
	 * Method to delete one or more records.
	 *
	 * @param array $cid
	 *
	 * @throws Exception
	 */
	public function delete($cid = [])
	{
		if (count($cid))
		{
			if ($this->triggerEvents)
			{
				JPluginHelper::importPlugin($this->pluginGroup);
			}

			// Before delete
			$this->beforeDelete($cid);

			$row = $this->getTable();

			foreach ($cid as $id)
			{
				if ($row->load($id))
				{
					if ($this->triggerEvents)
					{
						$result =
$this->container->app->triggerEvent($this->eventBeforeDelete,
[$this->context, $row]);

						if (in_array(false, $result, true))
						{
							throw new Exception($row->getError());
						}
					}

					if (!$row->delete())
					{
						throw new Exception($row->getError());
					}

					if ($this->triggerEvents)
					{
						$this->container->app->triggerEvent($this->eventAfterDelete,
[$this->context, $row]);
					}
				}
				else
				{
					throw new Exception($row->getError());
				}
			}

			// Post process after records has been deleted from main table
			$this->afterDelete($cid);
			$this->cleanCache();
		}
	}

	/**
	 * Method to change the published state of one or more records.
	 *
	 * @param array $pks   A list of the primary keys to change.
	 * @param int   $value The value of the published state.
	 *
	 * @throws Exception
	 */
	public function publish($pks, $value = 1)
	{
		$row = $this->getTable();
		$pks = (array) $pks;

		$this->beforePublish($pks, $value);

		// Attempt to change the state of the records.
		if (!$row->publish($pks, $value,
$this->container->user->get('id')))
		{
			throw new Exception($row->getError());
		}

		$this->afterPublish($pks, $value);

		if ($this->triggerEvents)
		{
			// Trigger the eventChangeState event.
			JPluginHelper::importPlugin($this->pluginGroup);
			$this->container->app->triggerEvent($this->eventChangeState,
[$this->context, $pks, $value]);
		}

		// Clear the component's cache
		$this->cleanCache();
	}

	/**
	 * Saves the manually set order of records.
	 *
	 * @param array $pks   An array of primary key ids.
	 *
	 * @param array $order An array contain ordering value of item
corresponding with $pks array
	 *
	 * @return mixed
	 *
	 * @throws Exception
	 */
	public function saveorder($pks = null, $order = null)
	{
		$row        = $this->getTable();
		$conditions = [];

		// Update ordering values
		foreach ($pks as $i => $pk)
		{
			$row->load((int) $pk);

			if ($row->ordering != $order[$i])
			{
				$row->ordering = $order[$i];
				$row->store();

				// Remember to reorder within position and client_id
				$condition = $this->getReorderConditions($row);
				$found     = false;

				foreach ($conditions as $cond)
				{
					if ($cond[1] == $condition)
					{
						$found = true;
						break;
					}
				}

				if (!$found)
				{
					$conditions[] = [$row->id, $condition];
				}
			}
		}

		// Execute reorder for each category.
		foreach ($conditions as $cond)
		{
			$row->load($cond[0]);
			$row->reorder($cond[1]);
		}

		// Clear the component's cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Load the record from database
	 *
	 */
	protected function loadData()
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true);
		$query->select('*')
			->from($this->table)
			->where('id = ' . (int) $this->state->id);
		$db->setQuery($query);
		$this->data = $db->loadObject();
	}

	/**
	 * Init the record dara object
	 */
	protected function initData()
	{
		$this->data = $this->getTable();

		if (property_exists($this->data, 'published'))
		{
			$this->data->published = 1;
		}
	}

	/**
	 * Method to change the title & alias, usually used on save2copy
method
	 *
	 * @param        $row   the object being saved
	 *
	 * @param string $alias The alias.
	 *
	 * @param string $title The title.
	 *
	 * @return array Contains the modified title and alias.
	 */
	protected function generateNewTitle($row, $alias, $title)
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true);
		$query->select('COUNT(*)')->from($this->table);
		$conditions = $this->getReorderConditions($row);

		while (true)
		{
			$query->where('alias=' . $db->quote($alias));

			if (count($conditions))
			{
				$query->where($conditions);
			}

			$db->setQuery($query);
			$found = (int) $db->loadResult();

			if ($found)
			{
				$title = StringHelper::increment($title);
				$alias = StringHelper::increment($alias, 'dash');
				$query->clear('where');
			}
			else
			{
				break;
			}
		}

		return [$title, $alias];
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param JTable $row A JTable object.
	 *
	 * @return array An array of conditions to add to ordering queries.
	 *
	 */
	protected function getReorderConditions($row)
	{
		$conditions = [];

		if (property_exists($row, 'catid'))
		{
			$conditions[] = 'catid = ' . (int) $row->catid;
		}

		return $conditions;
	}

	/**
	 * Prepare and sanitise the table data prior to saving.
	 *
	 * @param JTable $row A reference to a JTable object.
	 *
	 * @return void
	 *
	 */
	protected function prepareTable($row, $task)
	{
		$user = $this->container->user;

		if (property_exists($row, 'title'))
		{
			$titleField = 'title';
		}
		elseif (property_exists($row, 'name'))
		{
			$titleField = 'name';
		}

		if (($task == 'save2copy') && $titleField)
		{
			if (property_exists($row, 'alias'))
			{
				//Need to generate new title and alias
				list ($title, $alias) = $this->generateNewTitle($row,
$row->alias, $row->{$titleField});
				$row->{$titleField} = $title;
				$row->alias         = $alias;
			}
			else
			{
				$row->{$titleField} =
StringHelper::increment($row->{$titleField});
			}
		}

		if (property_exists($row, 'title'))
		{
			$row->title = htmlspecialchars_decode($row->title, ENT_QUOTES);
		}

		if (property_exists($row, 'name'))
		{
			$row->name = htmlspecialchars_decode($row->name, ENT_QUOTES);
		}

		if (property_exists($row, 'alias'))
		{
			if (empty($row->alias))
			{
				$row->alias = $row->{$titleField};
			}

			$row->alias = JApplicationHelper::stringURLSafe($row->alias);

			// Handle alias for extra languages
			if (JLanguageMultilang::isEnabled())
			{
				// Build alias alias for other languages
				$languages = \OSL\Utils\Helper::getLanguages();

				if (count($languages))
				{
					foreach ($languages as $language)
					{
						$sef = $language->sef;

						if (!$row->{'alias_' . $sef})
						{
							$row->{'alias_' . $sef} =
JApplicationHelper::stringURLSafe($row->{$titleField . '_' .
$sef});
						}
						else
						{
							$row->{'alias_' . $sef} =
JApplicationHelper::stringURLSafe($row->{'alias_' . $sef});
						}
					}
				}
			}
		}

		if (empty($row->id))
		{
			// Set ordering to the last item if not set
			if (property_exists($row, 'ordering') &&
empty($row->ordering))
			{
				$db         = $this->getDbo();
				$query      = $db->getQuery(true)
					->select('MAX(ordering)')
					->from($db->quoteName($this->table));
				$conditions = $this->getReorderConditions($row);

				if (count($conditions))
				{
					$query->where($conditions);
				}

				$db->setQuery($query);
				$max           = $db->loadResult();
				$row->ordering = $max + 1;
			}

			if (property_exists($row, 'created_date') &&
!$row->created_date)
			{
				$row->created_date = JFactory::getDate()->toSql();
			}

			if (property_exists($row, 'created_by') &&
!$row->created_by)
			{
				$row->created_by = $user->get('id');
			}
		}

		if (property_exists($row, 'modified_date') &&
!$row->modified_date)
		{
			$row->modified_date = JFactory::getDate()->toSql();
		}

		if (property_exists($row, 'modified_by') &&
!$row->modified_by)
		{
			$row->modified_by = $user->get('id');
		}

		if (property_exists($row, 'params') &&
is_array($row->params))
		{
			$row->params = json_encode($row->params);
		}
	}

	/**
	 * Give a chance for child class to pre-process the data
	 *
	 * @param $row
	 * @param $input
	 * @param $isNew bool
	 */
	protected function beforeStore($row, $input, $isNew)
	{

	}

	/**
	 * Give a chance for child class to post-process the data
	 *
	 * @param $row
	 * @param $input
	 * @param $isNew bool
	 */
	protected function afterStore($row, $input, $isNew)
	{

	}

	/**
	 * Give a chance for child class tp pre-process the delete. For example,
delete the relation records
	 *
	 * @param array $cid Ids of deleted record
	 */
	protected function beforeDelete($cid)
	{

	}

	/**
	 * Give a chance for child class tp post-process the delete. For example,
delete the relation records
	 *
	 * @param array $cid Ids of deleted record
	 */
	protected function afterDelete($cid)
	{

	}

	/**
	 * Give a chance for child class to pre-process the publish.
	 *
	 * @param array $cid
	 * @param int   $state
	 */
	protected function beforePublish($cid, $state)
	{

	}

	/**
	 * Give a chance for child class to post-process the publish.
	 *
	 * @param array $cid
	 * @param int   $state
	 */
	protected function afterPublish($cid, $state)
	{

	}
}BaseDatabaseModel.php000064400000033524151155743370010557 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\MVC\Model;

defined('JPATH_PLATFORM') or die;

use Joomla\Utilities\ArrayHelper;

/**
 * Base class for a database aware Joomla Model
 *
 * Acts as a Factory class for application specific objects and provides
many supporting API functions.
 *
 * @since  2.5.5
 */
abstract class BaseDatabaseModel extends \JObject
{
	/**
	 * Indicates if the internal state has been set
	 *
	 * @var    boolean
	 * @since  3.0
	 */
	protected $__state_set = null;

	/**
	 * Database Connector
	 *
	 * @var    \JDatabaseDriver
	 * @since  3.0
	 */
	protected $_db;

	/**
	 * The model (base) name
	 *
	 * @var    string
	 * @since  3.0
	 */
	protected $name;

	/**
	 * The URL option for the component.
	 *
	 * @var    string
	 * @since  3.0
	 */
	protected $option = null;

	/**
	 * A state object
	 *
	 * @var    \JObject
	 * @since  3.0
	 */
	protected $state;

	/**
	 * The event to trigger when cleaning cache.
	 *
	 * @var    string
	 * @since  3.0
	 */
	protected $event_clean_cache = null;

	/**
	 * Add a directory where \JModelLegacy should search for models. You may
	 * either pass a string or an array of directories.
	 *
	 * @param   mixed   $path    A path or array[sting] of paths to search.
	 * @param   string  $prefix  A prefix for models.
	 *
	 * @return  array  An array with directory elements. If prefix is equal to
'', all directories are returned.
	 *
	 * @since   3.0
	 */
	public static function addIncludePath($path = '', $prefix =
'')
	{
		static $paths;

		if (!isset($paths))
		{
			$paths = array();
		}

		if (!isset($paths[$prefix]))
		{
			$paths[$prefix] = array();
		}

		if (!isset($paths['']))
		{
			$paths[''] = array();
		}

		if (!empty($path))
		{
			jimport('joomla.filesystem.path');

			foreach ((array) $path as $includePath)
			{
				if (!in_array($includePath, $paths[$prefix]))
				{
					array_unshift($paths[$prefix], \JPath::clean($includePath));
				}

				if (!in_array($includePath, $paths['']))
				{
					array_unshift($paths[''], \JPath::clean($includePath));
				}
			}
		}

		return $paths[$prefix];
	}

	/**
	 * Adds to the stack of model table paths in LIFO order.
	 *
	 * @param   mixed  $path  The directory as a string or directories as an
array to add.
	 *
	 * @return  void
	 *
	 * @since   3.0
	 */
	public static function addTablePath($path)
	{
		\JTable::addIncludePath($path);
	}

	/**
	 * Create the filename for a resource
	 *
	 * @param   string  $type   The resource type to create the filename for.
	 * @param   array   $parts  An associative array of filename information.
	 *
	 * @return  string  The filename
	 *
	 * @since   3.0
	 */
	protected static function _createFileName($type, $parts = array())
	{
		$filename = '';

		switch ($type)
		{
			case 'model':
				$filename = strtolower($parts['name']) . '.php';
				break;
		}

		return $filename;
	}

	/**
	 * Returns a Model object, always creating it
	 *
	 * @param   string  $type    The model type to instantiate
	 * @param   string  $prefix  Prefix for the model class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  \JModelLegacy|boolean   A \JModelLegacy instance or false on
failure
	 *
	 * @since   3.0
	 */
	public static function getInstance($type, $prefix = '', $config
= array())
	{
		$type = preg_replace('/[^A-Z0-9_\.-]/i', '', $type);
		$modelClass = $prefix . ucfirst($type);

		if (!class_exists($modelClass))
		{
			jimport('joomla.filesystem.path');
			$path = \JPath::find(self::addIncludePath(null, $prefix),
self::_createFileName('model', array('name' =>
$type)));

			if (!$path)
			{
				$path = \JPath::find(self::addIncludePath(null, ''),
self::_createFileName('model', array('name' =>
$type)));
			}

			if (!$path)
			{
				return false;
			}

			require_once $path;

			if (!class_exists($modelClass))
			{
				\JLog::add(\JText::sprintf('JLIB_APPLICATION_ERROR_MODELCLASS_NOT_FOUND',
$modelClass), \JLog::WARNING, 'jerror');

				return false;
			}
		}

		return new $modelClass($config);
	}

	/**
	 * Constructor
	 *
	 * @param   array  $config  An array of configuration options (name,
state, dbo, table_path, ignore_request).
	 *
	 * @since   3.0
	 * @throws  \Exception
	 */
	public function __construct($config = array())
	{
		// Guess the option from the class name (Option)Model(View).
		if (empty($this->option))
		{
			$r = null;

			if (!preg_match('/(.*)Model/i', get_class($this), $r))
			{
				throw new
\Exception(\JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'),
500);
			}

			$this->option = 'com_' . strtolower($r[1]);
		}

		// Set the view name
		if (empty($this->name))
		{
			if (array_key_exists('name', $config))
			{
				$this->name = $config['name'];
			}
			else
			{
				$this->name = $this->getName();
			}
		}

		// Set the model state
		if (array_key_exists('state', $config))
		{
			$this->state = $config['state'];
		}
		else
		{
			$this->state = new \JObject;
		}

		// Set the model dbo
		if (array_key_exists('dbo', $config))
		{
			$this->_db = $config['dbo'];
		}
		else
		{
			$this->_db = \JFactory::getDbo();
		}

		// Set the default view search path
		if (array_key_exists('table_path', $config))
		{
			$this->addTablePath($config['table_path']);
		}
		// @codeCoverageIgnoreStart
		elseif (defined('JPATH_COMPONENT_ADMINISTRATOR'))
		{
			$this->addTablePath(JPATH_COMPONENT_ADMINISTRATOR .
'/tables');
			$this->addTablePath(JPATH_COMPONENT_ADMINISTRATOR .
'/table');
		}

		// @codeCoverageIgnoreEnd

		// Set the internal state marker - used to ignore setting state from the
request
		if (!empty($config['ignore_request']))
		{
			$this->__state_set = true;
		}

		// Set the clean cache event
		if (isset($config['event_clean_cache']))
		{
			$this->event_clean_cache = $config['event_clean_cache'];
		}
		elseif (empty($this->event_clean_cache))
		{
			$this->event_clean_cache = 'onContentCleanCache';
		}
	}

	/**
	 * Gets an array of objects from the results of database query.
	 *
	 * @param   string   $query       The query.
	 * @param   integer  $limitstart  Offset.
	 * @param   integer  $limit       The number of records.
	 *
	 * @return  object[]  An array of results.
	 *
	 * @since   3.0
	 * @throws  \RuntimeException
	 */
	protected function _getList($query, $limitstart = 0, $limit = 0)
	{
		$this->getDbo()->setQuery($query, $limitstart, $limit);

		return $this->getDbo()->loadObjectList();
	}

	/**
	 * Returns a record count for the query.
	 *
	 * Note: Current implementation of this method assumes that getListQuery()
returns a set of unique rows,
	 * thus it uses SELECT COUNT(*) to count the rows. In cases that
getListQuery() uses DISTINCT
	 * then either this method must be overridden by a custom implementation
at the derived Model Class
	 * or a GROUP BY clause should be used to make the set unique.
	 *
	 * @param   \JDatabaseQuery|string  $query  The query.
	 *
	 * @return  integer  Number of rows for query.
	 *
	 * @since   3.0
	 */
	protected function _getListCount($query)
	{
		// Use fast COUNT(*) on \JDatabaseQuery objects if there is no GROUP BY
or HAVING clause:
		if ($query instanceof \JDatabaseQuery
			&& $query->type == 'select'
			&& $query->group === null
			&& $query->union === null
			&& $query->unionAll === null
			&& $query->having === null)
		{
			$query = clone $query;
			$query->clear('select')->clear('order')->clear('limit')->clear('offset')->select('COUNT(*)');

			$this->getDbo()->setQuery($query);

			return (int) $this->getDbo()->loadResult();
		}

		// Otherwise fall back to inefficient way of counting all results.

		// Remove the limit and offset part if it's a \JDatabaseQuery object
		if ($query instanceof \JDatabaseQuery)
		{
			$query = clone $query;
			$query->clear('limit')->clear('offset');
		}

		$this->getDbo()->setQuery($query);
		$this->getDbo()->execute();

		return (int) $this->getDbo()->getNumRows();
	}

	/**
	 * Method to load and return a model object.
	 *
	 * @param   string  $name    The name of the view
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration settings to pass to
\JTable::getInstance
	 *
	 * @return  \JTable|boolean  Table object or boolean false if failed
	 *
	 * @since   3.0
	 * @see     \JTable::getInstance()
	 */
	protected function _createTable($name, $prefix = 'Table',
$config = array())
	{
		// Clean the model name
		$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
		$prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);

		// Make sure we are returning a DBO object
		if (!array_key_exists('dbo', $config))
		{
			$config['dbo'] = $this->getDbo();
		}

		return \JTable::getInstance($name, $prefix, $config);
	}

	/**
	 * Method to get the database driver object
	 *
	 * @return  \JDatabaseDriver
	 *
	 * @since   3.0
	 */
	public function getDbo()
	{
		return $this->_db;
	}

	/**
	 * Method to get the model name
	 *
	 * The model name. By default parsed using the classname or it can be set
	 * by passing a $config['name'] in the class constructor
	 *
	 * @return  string  The name of the model
	 *
	 * @since   3.0
	 * @throws  \Exception
	 */
	public function getName()
	{
		if (empty($this->name))
		{
			$r = null;

			if (!preg_match('/Model(.*)/i', get_class($this), $r))
			{
				throw new
\Exception(\JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'),
500);
			}

			$this->name = strtolower($r[1]);
		}

		return $this->name;
	}

	/**
	 * Method to get model state variables
	 *
	 * @param   string  $property  Optional parameter name
	 * @param   mixed   $default   Optional default value
	 *
	 * @return  mixed  The property where specified, the state object where
omitted
	 *
	 * @since   3.0
	 */
	public function getState($property = null, $default = null)
	{
		if (!$this->__state_set)
		{
			// Protected method to auto-populate the model state.
			$this->populateState();

			// Set the model state set flag to true.
			$this->__state_set = true;
		}

		return $property === null ? $this->state :
$this->state->get($property, $default);
	}

	/**
	 * Method to get a table object, load it if necessary.
	 *
	 * @param   string  $name     The table name. Optional.
	 * @param   string  $prefix   The class prefix. Optional.
	 * @param   array   $options  Configuration array for model. Optional.
	 *
	 * @return  \JTable  A \JTable object
	 *
	 * @since   3.0
	 * @throws  \Exception
	 */
	public function getTable($name = '', $prefix =
'Table', $options = array())
	{
		if (empty($name))
		{
			$name = $this->getName();
		}

		if ($table = $this->_createTable($name, $prefix, $options))
		{
			return $table;
		}

		throw new
\Exception(\JText::sprintf('JLIB_APPLICATION_ERROR_TABLE_NAME_NOT_SUPPORTED',
$name), 0);
	}

	/**
	 * Method to load a row for editing from the version history table.
	 *
	 * @param   integer  $versionId  Key to the version history table.
	 * @param   \JTable  &$table     Content table object being loaded.
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 *
	 * @since   3.2
	 */
	public function loadHistory($versionId, \JTable &$table)
	{
		// Only attempt to check the row in if it exists, otherwise do an early
exit.
		if (!$versionId)
		{
			return false;
		}

		// Get an instance of the row to checkout.
		$historyTable = \JTable::getInstance('Contenthistory');

		if (!$historyTable->load($versionId))
		{
			$this->setError($historyTable->getError());

			return false;
		}

		$rowArray =
ArrayHelper::fromObject(json_decode($historyTable->version_data));
		$typeId   =
\JTable::getInstance('Contenttype')->getTypeId($this->typeAlias);

		if ($historyTable->ucm_type_id != $typeId)
		{
			$this->setError(\JText::_('JLIB_APPLICATION_ERROR_HISTORY_ID_MISMATCH'));

			$key = $table->getKeyName();

			if (isset($rowArray[$key]))
			{
				$table->checkIn($rowArray[$key]);
			}

			return false;
		}

		$this->setState('save_date', $historyTable->save_date);
		$this->setState('version_note',
$historyTable->version_note);

		return $table->bind($rowArray);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * This method should only be called once per instantiation and is
designed
	 * to be called on the first call to the getState() method unless the
model
	 * configuration flag to ignore the request is set.
	 *
	 * @return  void
	 *
	 * @note    Calling getState in this method will result in recursion.
	 * @since   3.0
	 */
	protected function populateState()
	{
	}

	/**
	 * Method to set the database driver object
	 *
	 * @param   \JDatabaseDriver  $db  A \JDatabaseDriver based object
	 *
	 * @return  void
	 *
	 * @since   3.0
	 */
	public function setDbo($db)
	{
		$this->_db = $db;
	}

	/**
	 * Method to set model state variables
	 *
	 * @param   string  $property  The name of the property.
	 * @param   mixed   $value     The value of the property to set or null.
	 *
	 * @return  mixed  The previous value of the property or null if not set.
	 *
	 * @since   3.0
	 */
	public function setState($property, $value = null)
	{
		return $this->state->set($property, $value);
	}

	/**
	 * Clean the cache
	 *
	 * @param   string   $group     The cache group
	 * @param   integer  $clientId  The ID of the client
	 *
	 * @return  void
	 *
	 * @since   3.0
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		$conf = \JFactory::getConfig();

		$options = array(
			'defaultgroup' => $group ?: (isset($this->option) ?
$this->option :
\JFactory::getApplication()->input->get('option')),
			'cachebase' => $clientId ? JPATH_ADMINISTRATOR .
'/cache' : $conf->get('cache_path', JPATH_SITE .
'/cache'),
			'result' => true,
		);

		try
		{
			/** @var \JCacheControllerCallback $cache */
			$cache = \JCache::getInstance('callback', $options);
			$cache->clean();
		}
		catch (\JCacheException $exception)
		{
			$options['result'] = false;
		}

		// Trigger the onContentCleanCache event.
		\JEventDispatcher::getInstance()->trigger($this->event_clean_cache,
$options);
	}
}
FormModel.php000064400000023107151155743370007157 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\MVC\Model;

defined('JPATH_PLATFORM') or die;

use Joomla\Utilities\ArrayHelper;

/**
 * Prototype form model.
 *
 * @see    \JForm
 * @see    \JFormField
 * @see    \JFormRule
 * @since  1.6
 */
abstract class FormModel extends BaseDatabaseModel
{
	/**
	 * Array of form objects.
	 *
	 * @var    \JForm[]
	 * @since  1.6
	 */
	protected $_forms = array();

	/**
	 * Maps events to plugin groups.
	 *
	 * @var    array
	 * @since  3.6
	 */
	protected $events_map = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration
settings.
	 *
	 * @see     \JModelLegacy
	 * @since   3.6
	 */
	public function __construct($config = array())
	{
		$config['events_map'] = isset($config['events_map'])
? $config['events_map'] : array();

		$this->events_map = array_merge(
			array(
				'validate' => 'content',
			),
			$config['events_map']
		);

		parent::__construct($config);
	}

	/**
	 * Method to checkin a row.
	 *
	 * @param   integer  $pk  The numeric id of the primary key.
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 *
	 * @since   1.6
	 */
	public function checkin($pk = null)
	{
		// Only attempt to check the row in if it exists.
		if ($pk)
		{
			$user = \JFactory::getUser();

			// Get an instance of the row to checkin.
			$table = $this->getTable();

			if (!$table->load($pk))
			{
				$this->setError($table->getError());

				return false;
			}

			$checkedOutField = $table->getColumnAlias('checked_out');
			$checkedOutTimeField =
$table->getColumnAlias('checked_out_time');

			// If there is no checked_out or checked_out_time field, just return
true.
			if (!property_exists($table, $checkedOutField) ||
!property_exists($table, $checkedOutTimeField))
			{
				return true;
			}

			// Check if this is the user having previously checked out the row.
			if ($table->{$checkedOutField} > 0 &&
$table->{$checkedOutField} != $user->get('id') &&
!$user->authorise('core.manage', 'com_checkin'))
			{
				$this->setError(\JText::_('JLIB_APPLICATION_ERROR_CHECKIN_USER_MISMATCH'));

				return false;
			}

			// Attempt to check the row in.
			if (!$table->checkIn($pk))
			{
				$this->setError($table->getError());

				return false;
			}
		}

		return true;
	}

	/**
	 * Method to check-out a row for editing.
	 *
	 * @param   integer  $pk  The numeric id of the primary key.
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 *
	 * @since   1.6
	 */
	public function checkout($pk = null)
	{
		// Only attempt to check the row in if it exists.
		if ($pk)
		{
			// Get an instance of the row to checkout.
			$table = $this->getTable();

			if (!$table->load($pk))
			{
				$this->setError($table->getError());

				return false;
			}

			$checkedOutField = $table->getColumnAlias('checked_out');
			$checkedOutTimeField =
$table->getColumnAlias('checked_out_time');

			// If there is no checked_out or checked_out_time field, just return
true.
			if (!property_exists($table, $checkedOutField) ||
!property_exists($table, $checkedOutTimeField))
			{
				return true;
			}

			$user = \JFactory::getUser();

			// Check if this is the user having previously checked out the row.
			if ($table->{$checkedOutField} > 0 &&
$table->{$checkedOutField} != $user->get('id'))
			{
				$this->setError(\JText::_('JLIB_APPLICATION_ERROR_CHECKOUT_USER_MISMATCH'));

				return false;
			}

			// Attempt to check the row out.
			if (!$table->checkOut($user->get('id'), $pk))
			{
				$this->setError($table->getError());

				return false;
			}
		}

		return true;
	}

	/**
	 * Abstract method for getting the form from the model.
	 *
	 * @param   array    $data      Data for the form.
	 * @param   boolean  $loadData  True if the form is to load its own data
(default case), false if not.
	 *
	 * @return  \JForm|boolean  A \JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	abstract public function getForm($data = array(), $loadData = true);

	/**
	 * Method to get a form object.
	 *
	 * @param   string   $name     The name of the form.
	 * @param   string   $source   The form source. Can be XML string if file
flag is set to false.
	 * @param   array    $options  Optional array of options for the form
creation.
	 * @param   boolean  $clear    Optional argument to force load a new form.
	 * @param   string   $xpath    An optional xpath to search for the fields.
	 *
	 * @return  \JForm|boolean  \JForm object on success, false on error.
	 *
	 * @see     \JForm
	 * @since   1.6
	 */
	protected function loadForm($name, $source = null, $options = array(),
$clear = false, $xpath = false)
	{
		// Handle the optional arguments.
		$options['control'] = ArrayHelper::getValue((array) $options,
'control', false);

		// Create a signature hash. But make sure, that loading the data does not
create a new instance
		$sigoptions = $options;

		if (isset($sigoptions['load_data']))
		{
			unset($sigoptions['load_data']);
		}

		$hash = md5($source . serialize($sigoptions));

		// Check if we can use a previously loaded form.
		if (!$clear && isset($this->_forms[$hash]))
		{
			return $this->_forms[$hash];
		}

		// Get the form.
		\JForm::addFormPath(JPATH_COMPONENT . '/models/forms');
		\JForm::addFieldPath(JPATH_COMPONENT . '/models/fields');
		\JForm::addFormPath(JPATH_COMPONENT . '/model/form');
		\JForm::addFieldPath(JPATH_COMPONENT . '/model/field');

		try
		{
			$form = \JForm::getInstance($name, $source, $options, false, $xpath);

			if (isset($options['load_data']) &&
$options['load_data'])
			{
				// Get the data for the form.
				$data = $this->loadFormData();
			}
			else
			{
				$data = array();
			}

			// Allow for additional modification of the form, and events to be
triggered.
			// We pass the data because plugins may require it.
			$this->preprocessForm($form, $data);

			// Load the data into the form after the plugins have operated.
			$form->bind($data);
		}
		catch (\Exception $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Store the form for later.
		$this->_forms[$hash] = $form;

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  array  The default data is an empty array.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		return array();
	}

	/**
	 * Method to allow derived classes to preprocess the data.
	 *
	 * @param   string  $context  The context identifier.
	 * @param   mixed   &$data    The data to be processed. It gets
altered directly.
	 * @param   string  $group    The name of the plugin group to import
(defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   3.1
	 */
	protected function preprocessData($context, &$data, $group =
'content')
	{
		// Get the dispatcher and load the users plugins.
		$dispatcher = \JEventDispatcher::getInstance();
		\JPluginHelper::importPlugin($group);

		// Trigger the data preparation event.
		$results = $dispatcher->trigger('onContentPrepareData',
array($context, &$data));

		// Check for errors encountered while preparing the data.
		if (count($results) > 0 && in_array(false, $results, true))
		{
			$this->setError($dispatcher->getError());
		}
	}

	/**
	 * Method to allow derived classes to preprocess the form.
	 *
	 * @param   \JForm  $form   A \JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import
(defaults to "content").
	 *
	 * @return  void
	 *
	 * @see     \JFormField
	 * @since   1.6
	 * @throws  \Exception if there is an error in the form event.
	 */
	protected function preprocessForm(\JForm $form, $data, $group =
'content')
	{
		// Import the appropriate plugin group.
		\JPluginHelper::importPlugin($group);

		// Get the dispatcher.
		$dispatcher = \JEventDispatcher::getInstance();

		// Trigger the form preparation event.
		$results = $dispatcher->trigger('onContentPrepareForm',
array($form, $data));

		// Check for errors encountered while preparing the form.
		if (count($results) && in_array(false, $results, true))
		{
			// Get the last error.
			$error = $dispatcher->getError();

			if (!($error instanceof \Exception))
			{
				throw new \Exception($error);
			}
		}
	}

	/**
	 * Method to validate the form data.
	 *
	 * @param   \JForm  $form   The form to validate against.
	 * @param   array   $data   The data to validate.
	 * @param   string  $group  The name of the field group to validate.
	 *
	 * @return  array|boolean  Array of filtered data if valid, false
otherwise.
	 *
	 * @see     \JFormRule
	 * @see     \JFilterInput
	 * @since   1.6
	 */
	public function validate($form, $data, $group = null)
	{
		// Include the plugins for the delete events.
		\JPluginHelper::importPlugin($this->events_map['validate']);

		$dispatcher = \JEventDispatcher::getInstance();
		$dispatcher->trigger('onUserBeforeDataValidation',
array($form, &$data));

		// Filter and validate the form data.
		$data = $form->filter($data);
		$return = $form->validate($data, $group);

		// Check for an error.
		if ($return instanceof \Exception)
		{
			$this->setError($return->getMessage());

			return false;
		}

		// Check the validation results.
		if ($return === false)
		{
			// Get the validation messages from the form.
			foreach ($form->getErrors() as $message)
			{
				$this->setError($message);
			}

			return false;
		}

		// Tags B/C break at 3.1.2
		if (!isset($data['tags']) &&
isset($data['metadata']['tags']))
		{
			$data['tags'] = $data['metadata']['tags'];
		}

		return $data;
	}
}
ItemModel.php000064400000002035151155743370007147 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\MVC\Model;

defined('JPATH_PLATFORM') or die;

/**
 * Prototype item model.
 *
 * @since  1.6
 */
abstract class ItemModel extends BaseDatabaseModel
{
	/**
	 * An item.
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $_item = null;

	/**
	 * Model context string.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $_context = 'group.type';

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		return md5($id);
	}
}
ListModel.php000064400000022613151155743370007170 0ustar00<?php
/**
 * @package     OSL
 * @subpackage  Controller
 *
 * @copyright   Copyright (C) 2016 Ossolution Team, Inc. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

namespace OSL\Model;

use JDatabaseQuery, JPagination;

use OSL\Container\Container;

/**
 * Model class for handling lists of items.
 *
 * @package     OSF
 * @subpackage  Model
 * @since       1.0
 */
class ListModel extends Model
{
	/**
	 * The query object of the model
	 *
	 * @var JDatabaseQuery
	 */
	protected $query;
	/**
	 * List total
	 *
	 * @var integer
	 */
	protected $total;

	/**
	 * Model list data
	 *
	 * @var array
	 */
	protected $data;

	/**
	 * Pagination object
	 *
	 * @var JPagination
	 */
	protected $pagination;

	/**
	 * Name of state field name, usually be tbl.state or tbl.published
	 *
	 * @var string
	 */
	protected $stateField;

	/**
	 * List of fields which will be used for searching data from database
table
	 *
	 * @var array
	 */
	protected $searchFields = array();

	/**
	 * Clear join clause for getTotal method
	 *
	 * @var bool
	 */
	protected $clearJoin = true;

	/**
	 * Instantiate the model.
	 *
	 * @param mixed $config Model configuration data, could be an array or an
OSFConfig object
	 *
	 */
	public function __construct(Container $container, $config = array())
	{
		parent::__construct($container, $config);

		$this->query = $this->db->getQuery(true);

		$fields = array_keys($this->db->getTableColumns($this->table));

		if (in_array('ordering', $fields))
		{
			$defaultOrdering = 'tbl.ordering';
		}
		else
		{
			$defaultOrdering = 'tbl.id';
		}

		if (in_array('published', $fields))
		{
			$this->stateField = 'tbl.published';
		}
		else
		{
			$this->stateField = 'tbl.state';
		}

		if (isset($config['clear_join']))
		{
			$this->clearJoin = $config['clear_join'];
		}

		$this->state->insert('limit', 'int',
$this->container->appConfig->get('list_limit'))
			->insert('limitstart', 'int', 0)
			->insert('filter_order', 'cmd',
$defaultOrdering)
			->insert('filter_order_Dir', 'word',
'asc')
			->insert('filter_search', 'string')
			->insert('filter_state', 'string')
			->insert('filter_access', 'int', 0)
			->insert('filter_language', 'string');

		if (isset($config['search_fields']))
		{
			$this->searchFields = (array) $config['search_fields'];
		}
		else
		{
			// Build the search field array automatically, basically, we should
search based on name, title, description if these fields are available
			if (in_array('name', $fields))
			{
				$this->searchFields[] = 'tbl.name';
			}

			if (in_array('title', $fields))
			{
				$this->searchFields[] = 'tbl.title';
			}

			if (in_array('alias', $fields))
			{
				$this->searchFields[] = 'tbl.alias';
			}
		}

		if (isset($config['remember_states']))
		{
			$this->rememberStates = $config['remember_states'];
		}
		elseif
($this->container->app->isClient('administrator'))
		{
			$this->rememberStates = true;
		}
	}

	/**
	 * Get a list of items
	 *
	 * @return array
	 */
	public function getData()
	{
		if (empty($this->data))
		{
			$db    = $this->getDbo();
			$query = $this->buildListQuery();

			$this->beforeQueryData($query);

			// Adjust the limitStart state property
			$limit = $this->state->limit;

			if ($limit)
			{
				$offset = $this->state->limitstart;
				$total  = $this->getTotal();

				//If the offset is higher than the total recalculate the offset
				if ($offset !== 0 && $total !== 0)
				{
					if ($offset >= $total)
					{
						$offset                  = floor(($total - 1) / $limit) * $limit;
						$this->state->limitstart = $offset;
					}
				}
			}

			$db->setQuery($query, $this->state->limitstart,
$this->state->limit);
			$this->data = $db->loadObjectList();

			$this->beforeReturnData($this->data);

			// Store the query so that it can be used in getTotal method if needed
			$this->query = $query;
		}

		return $this->data;
	}

	/**
	 * Get total record. Child class should override this method if needed
	 *
	 * @return integer Number of records
	 *
	 */
	public function getTotal()
	{
		if (empty($this->total))
		{
			$db    = $this->getDbo();
			$query = $this->buildTotalQuery();
			$this->beforeQueryTotal($query);
			$db->setQuery($query);
			$this->total = (int) $db->loadResult();
		}

		return $this->total;
	}

	/**
	 * Get pagination object
	 *
	 * @return JPagination
	 */
	public function getPagination()
	{
		// Lets load the content if it doesn't already exist
		if (empty($this->pagination))
		{
			jimport('joomla.html.pagination');

			$this->pagination = new JPagination($this->getTotal(),
$this->state->limitstart, $this->state->limit);
		}

		return $this->pagination;
	}


	/**
	 * Build the query object which is used to get list of records from
database
	 *
	 * @return JDatabaseQuery
	 */
	protected function buildListQuery()
	{
		$query = $this->query;

		$this->buildQueryColumns($query)
			->buildQueryFrom($query)
			->buildQueryJoins($query)
			->buildQueryWhere($query)
			->buildQueryGroup($query)
			->buildQueryHaving($query)
			->buildQueryOrder($query);

		return $query;
	}

	/**
	 * Build query object use to get total records from database
	 *
	 * @return JDatabaseQuery
	 */
	protected function buildTotalQuery()
	{
		$query = clone $this->query;
		$query->clear('select')
			->clear('group')
			->clear('having')
			->clear('order')
			->clear('limit')
			->select('COUNT(*)');

		// Clear join clause if needed
		if ($this->clearJoin)
		{
			$query->clear('join');
		}

		return $query;
	}

	/**
	 * Builds SELECT columns list for the query
	 *
	 * @param JDatabaseQuery $query
	 *
	 * @return $this
	 */
	protected function buildQueryColumns(JDatabaseQuery $query)
	{
		$query->select(array('tbl.*'));

		return $this;
	}

	/**
	 * Builds FROM tables list for the query
	 *
	 * @param JDatabaseQuery $query
	 *
	 * @return $this
	 */
	protected function buildQueryFrom(JDatabaseQuery $query)
	{
		$query->from($this->table . ' AS tbl');

		return $this;
	}

	/**
	 * Builds JOINS clauses for the query
	 *
	 * @param JDatabaseQuery $query
	 *
	 * @return $this
	 */
	protected function buildQueryJoins(JDatabaseQuery $query)
	{
		return $this;
	}

	/**
	 * Builds a WHERE clause for the query
	 *
	 * @param JDatabaseQuery $query
	 *
	 * @return $this
	 */
	protected function buildQueryWhere(JDatabaseQuery $query)
	{
		$user  = $this->container->user;
		$db    = $this->getDbo();
		$state = $this->state;

		if ($state->filter_state == 'P')
		{
			$query->where($this->stateField . ' = 1');
		}
		elseif ($state->filter_state == 'U')
		{
			$query->where($this->stateField . ' = 0');
		}

		if ($state->filter_access)
		{
			$query->where('tbl.access = ' . (int)
$state->filter_access);

			if (!$user->authorise('core.admin'))
			{
				$query->where('tbl.access IN (' . implode(',',
$user->getAuthorisedViewLevels()) . ')');
			}
		}

		if ($state->filter_search)
		{
			//Remove blank space from searching
			$state->filter_search = trim($state->filter_search);

			if (stripos($state->filter_search, 'id:') === 0)
			{
				$query->where('tbl.id = ' . (int)
substr($state->filter_search, 3));
			}
			else
			{
				$search = $db->quote('%' .
$db->escape($state->filter_search, true) . '%', false);

				if (is_array($this->searchFields))
				{
					$whereOr = array();

					foreach ($this->searchFields as $searchField)
					{
						$whereOr[] = " LOWER($searchField) LIKE " . $search;
					}

					$query->where('(' . implode(' OR ', $whereOr) .
') ');
				}
			}
		}

		if ($state->filter_language && $state->filter_language !=
'*')
		{
			$query->where('tbl.language IN (' .
$db->quote($state->filter_language) . ',' .
$db->quote('*') . ', "")');
		}

		return $this;
	}

	/**
	 * Builds a GROUP BY clause for the query
	 *
	 * @param JDatabaseQuery $query
	 *
	 * @return $this
	 */
	protected function buildQueryGroup(JDatabaseQuery $query)
	{
		return $this;
	}

	/**
	 * Builds a HAVING clause for the query
	 *
	 * @param JDatabaseQuery $query
	 *
	 * @return $this
	 */
	protected function buildQueryHaving(JDatabaseQuery $query)
	{
		return $this;
	}

	/**
	 * Builds a generic ORDER BY clasue based on the model's state
	 *
	 * @param JDatabaseQuery $query
	 *
	 * @return $this
	 */
	protected function buildQueryOrder(JDatabaseQuery $query)
	{
		$sort      = $this->state->filter_order;
		$direction = strtoupper($this->state->filter_order_Dir);

		if ($sort)
		{
			$query->order($sort . ' ' . $direction);
		}

		return $this;
	}

	/**
	 * This method give child class a chance to adjust the query before it is
run to return list of records
	 *
	 * @param JDatabaseQuery $query
	 */
	protected function beforeQueryData(JDatabaseQuery $query)
	{

	}

	/**
	 * This method give child class a chance to adjust the query object before
it is run to return total records
	 *
	 * @param JDatabaseQuery $query
	 */
	protected function beforeQueryTotal(JDatabaseQuery $query)
	{

	}

	/**
	 * This method give child class to adjust the return data in getData
method without having to override the
	 * whole method
	 *
	 * @param array $rows
	 */
	protected function beforeReturnData($rows)
	{

	}
}
Model.php000064400000017257151156057320006336 0ustar00<?php
/**
 * @package     OSL
 * @subpackage  Controller
 *
 * @copyright   Copyright (C) 2016 Ossolution Team, Inc. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

namespace OSL\Model;

use Exception;
use JDatabaseDriver, JText, JTable, JCache;
use OSL\Container\Container;
use OSL\Input\Input;

class Model
{

	/**
	 * The model name
	 *
	 * @var string
	 */
	protected $name;

	/**
	 * Model state
	 *
	 * @var State
	 */
	protected $state;

	/**
	 * The database driver.
	 *
	 * @var JDatabaseDriver
	 */
	protected $db;

	/**
	 * The name of the database table
	 *
	 * @var string
	 */
	protected $table;

	/**
	 * Ignore request or not. If set to Yes, model states won't be set
when it is created
	 *
	 * @var boolean
	 */
	protected $ignoreRequest = false;

	/**
	 * Remember model states value in session
	 *
	 * @var boolean
	 */
	protected $rememberStates = false;

	/**
	 * Constructor
	 *
	 * @param mixed $config Model configuration data, could be an array or an
OSFConfig object
	 *
	 * @throws Exception
	 */
	public function __construct(Container $container, $config = [])
	{
		$this->container = $container;

		if (isset($config['name']))
		{
			$this->name = $config['name'];
		}
		else
		{
			$r = null;

			if (!preg_match('/(.*)\\\\Model\\\\(.*)/i', get_class($this),
$r))
			{
				throw new
Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'),
500);
			}

			$this->name = $r[2];
		}

		if (isset($config['db']))
		{
			$this->db = $config['db'];
		}
		else
		{
			$this->db = $container->get('db');
		}

		if (isset($config['state']))
		{
			$this->state = $config['state'];
		}
		else
		{
			$this->state = new State();
		}

		if (isset($config['table']))
		{
			$this->table = $config['table'];
		}
		else
		{
			$this->table = $container->tablePrefix .
strtolower($container->inflector->pluralize($this->name));
		}

		if (isset($config['ignore_request']))
		{
			$this->ignoreRequest = $config['ignore_request'];
		}

		if (isset($config['remember_states']))
		{
			$this->rememberStates = $config['remember_states'];
		}

		$this->initialize();
	}

	/**
	 * Populate model state from input
	 */
	public function populateState()
	{
		if ($this->ignoreRequest)
		{
			return;
		}

		$input = $this->container->input;

		$data = $input->getData();

		// Try to get the state properties data from user session
		if ($this->rememberStates)
		{
			$properties = $this->state->getProperties();

			if (count($properties))
			{
				$context = $this->container->option . '.' .
$input->get('view', $this->container->defaultView) .
'.';

				foreach ($properties as $property)
				{
					$newState = $this->getUserStateFromRequest($input, $context .
$property, $property);

					if ($newState != null)
					{
						$data[$property] = $newState;
					}
				}
			}
		}

		$this->setState($data);
	}

	/**
	 * Get JTable object for the model
	 *
	 * @param string $name
	 *
	 * @return JTable
	 */
	public function getTable($name = '')
	{
		if (!$name)
		{
			$name =
$this->container->inflector->singularize($this->name);
		}


		return $this->container->factory->createTable($name,
$this->getDbo());
	}

	/**
	 * Set the model state properties
	 *
	 * @param string|array The    name of the property, an array
	 *
	 * @param mixed $value The value of the property
	 *
	 * @return Model
	 */
	public function setState($property, $value = null)
	{
		$changed = false;

		if (is_array($property))
		{
			foreach ($property as $key => $value)
			{
				if (isset($this->state->$key) && $this->state->$key
!= $value)
				{
					$changed = true;
					break;
				}
			}

			$this->state->setData($property);
		}
		else
		{
			if (isset($this->state->$property) &&
$this->state->$property != $value)
			{
				$changed = true;
			}

			$this->state->$property = $value;
		}

		if ($changed)
		{
			// Reset the data
			$this->data  = null;
			$this->total = null;
		}

		return $this;
	}

	/**
	 * Get the model state properties
	 *
	 * If no property name is given then the function will return an
associative array of all properties.
	 *
	 * @param string $property The name of the property
	 *
	 * @param string $default  The default value
	 *
	 * @return mixed <string, State>
	 */
	public function getState($property = null, $default = null)
	{
		$result = $default;

		if (is_null($property))
		{
			$result = $this->state;
		}
		else
		{
			if (isset($this->state->$property))
			{
				$result = $this->state->$property;
			}
		}

		return $result;
	}

	/**
	 * Reset all cached data and reset the model state to it's default
	 *
	 * @param boolean $default If TRUE use defaults when resetting. Default is
TRUE
	 *
	 * @return $this
	 */
	public function reset($default = true)
	{
		$this->data  = null;
		$this->total = null;
		$this->state->reset($default);
		$this->query = $this->db->getQuery(true);

		return $this;
	}

	/**
	 * Get the dbo
	 *
	 * @return JDatabaseDriver
	 */
	public function getDbo()
	{
		return $this->db;
	}

	/**
	 * Get name of the model
	 *
	 * @return string
	 */
	public function getName()
	{
		return $this->name;
	}

	/**
	 * This blank method give child class a chance to init the class further
after being constructed
	 */
	protected function initialize()
	{

	}

	/**
	 * Supports a simple form Fluent Interfaces.
	 * Allows you to set states by
	 * using the state name as the method name.
	 *
	 * For example :
$model->filter_order('name')->filter_order_Dir('DESC')->limit(10)->getData();
	 *
	 * @param string $method Method name
	 *
	 * @param array  $args   Array containing all the arguments for the
original call
	 *
	 * @return $this
	 */
	public function __call($method, $args)
	{
		if (isset($this->state->$method))
		{
			$this->state->set($method, $args[0]);

			return $this;
		}

		return null;
	}

	/**
	 * Gets the value of a user state variable.
	 *
	 * @param Input  $input   The input object
	 * @param string $key     The key of the user state variable.
	 * @param string $request The name of the variable passed in a request.
	 * @param string $default The default value for the variable if not found.
Optional.
	 * @param string $type    Filter for the variable, for valid values see
{@link JFilterInput::clean()}. Optional.
	 *
	 * @return  object  The request user state.
	 */
	protected function getUserStateFromRequest($input, $key, $request,
$default = null, $type = 'none')
	{
		$app = $this->container->app;

		$currentState = $app->getUserState($key, $default);
		$newState     = $input->get($request, null, $type);

		// Save the new value only if it was set in this request.
		if ($newState !== null)
		{
			$app->setUserState($key, $newState);
		}
		else
		{
			$newState = $currentState;
		}

		return $newState;
	}

	/**
	 * Clean the cache
	 *
	 * @param string  $group     The cache group
	 * @param integer $client_id The ID of the client
	 *
	 * @return  void
	 *
	 */
	protected function cleanCache($group = null, $client_id = 0)
	{
		$conf = $this->container->appConfig;

		$options = [
			'defaultgroup' => ($group) ? $group :
$this->container->option,
			'cachebase'    => ($client_id) ? JPATH_ADMINISTRATOR .
'/cache' : $conf->get('cache_path', JPATH_SITE .
'/cache')];

		$cache = JCache::getInstance('callback', $options);
		$cache->clean();

		// Trigger the onContentCleanCache event.
		if (!empty($this->eventCleanCache))
		{
			$this->container->app->triggerEvent($this->eventCleanCache,
$options);
		}
	}
}State.php000064400000013446151156057320006352 0ustar00<?php
/**
 * @package     OSL
 * @subpackage  Model
 *
 * @copyright   Copyright (C) 2016 Ossolution Team, Inc. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

namespace OSL\Model;

use JFilterInput;

class State
{

	/**
	 * The state data container
	 *
	 * @var array
	 */
	protected $data = array();

	/**
	 * Set data for a state
	 *
	 * @param string $name The name of state
	 * @param mixed  $value
	 *
	 * @return $this
	 */
	public function set($name, $value)
	{
		if (isset($this->data[$name]))
		{
			$this->data[$name]->value = $value;
		}

		return $this;
	}

	/**
	 * Retrieve data for a state
	 *
	 * @param string $name    Name of the state
	 *
	 * @param mixed  $default Default value if no data has been set for that
state
	 *
	 * @return mixed The state value
	 */
	public function get($name, $default = null)
	{
		$result = $default;

		if (isset($this->data[$name]))
		{
			$result = $this->data[$name]->value;
		}

		return $result;
	}

	/**
	 * Insert a new state
	 *
	 * @param string $name    The name of the state
	 *
	 * @param mixed  $filter  The name of filter which will be used to
sanitize the state value using JFilterInput
	 *
	 * @param mixed  $default The default value of the state
	 *
	 * @return State
	 */
	public function insert($name, $filter, $default = null)
	{
		$state             = new \stdClass();
		$state->name       = $name;
		$state->filter     = $filter;
		$state->value      = $default;
		$state->default    = $default;
		$this->data[$name] = $state;

		return $this;
	}

	/**
	 * Remove an existing state
	 *
	 * @param string $name The name of the state which will be removed
	 *
	 * @return $this
	 */
	public function remove($name)
	{
		if (isset($this->data[$name]))
		{
			unset($this->data[$name]);
		}

		return $this;
	}

	/**
	 * Reset all state data and revert to the default state
	 *
	 * @param boolean $default If TRUE use defaults when resetting. If FALSE
then null value will be used.Default is TRUE
	 *
	 * @return $this
	 */
	public function reset($default = true)
	{
		foreach ($this->data as $state)
		{
			$state->value = $default ? $state->default : null;
		}

		return $this;
	}

	/**
	 * Set the state data
	 *
	 * This function will only filter values if we have a value. If the value
	 * is an empty string it will be filtered to NULL.
	 *
	 * @param array $data An associative array of state values by name
	 *
	 * @return $this
	 */
	public function setData(array $data)
	{
		$filterInput = JFilterInput::getInstance();

		// Special code for handle ajax ordering in Joomla 3
		if (!empty($data['filter_full_ordering']))
		{
			$parts                    = explode(' ',
$data['filter_full_ordering']);
			$sort                     = $parts[0];
			$direction                = isset($parts[1]) ? $parts[1] :
'';
			$data['filter_order']     = $sort;
			$data['filter_order_Dir'] = $direction;
		}

		// Filter data
		foreach ($data as $key => $value)
		{
			if (isset($this->data[$key]))
			{
				$filter = $this->data[$key]->filter;

				// Only filter if we have a value
				if ($value !== null)
				{
					if ($value !== '')
					{
						// Check for a callback filter.
						if (strpos($filter, '::') !== false &&
is_callable(explode('::', $filter)))
						{
							$value = call_user_func(explode('::', $filter), $value);
						}

						// Filter using a callback function if specified.
						elseif (function_exists($filter))
						{
							$value = call_user_func($filter, $value);
						}

						// Filter using JFilterInput. All HTML code is filtered by default.
						else
						{
							$value = $filterInput->clean($value, $filter);
						}
					}
					else
					{
						$value = null;
					}

					$this->data[$key]->value = $value;
				}
			}
		}

		return $this;
	}

	/**
	 * Get the state data
	 *
	 * This function only returns states that have been been set.
	 *
	 * @return array An associative array of state values by name
	 */
	public function getData()
	{
		$data = array();

		foreach ($this->data as $name => $state)
		{
			$data[$name] = $state->value;
		}

		return $data;
	}

	/**
	 * Get list of state variables is being stored
	 */
	public function getProperties()
	{
		return array_keys($this->data);
	}

	/**
	 * Get default value of a state
	 *
	 * @param string $name
	 *
	 * @return mixed the default state value
	 */
	public function getDefault($name)
	{
		return $this->data[$name]->default;
	}

	/**
	 * Change default value (and therefore value) of an existing state
	 *
	 * @param $name
	 * @param $default
	 *
	 * @return $this
	 */
	public function setDefault($name, $default)
	{
		if (isset($this->data[$name]))
		{
			$this->data[$name]->default = $default;
			$this->data[$name]->value   = $default;
		}

		return $this;
	}

	/**
	 * Magic method to get state value
	 *
	 * @param string
	 *
	 * @return mixed
	 */
	public function __get($name)
	{
		return $this->get($name);
	}

	/**
	 * Set state value
	 *
	 * @param string $name  The user-specified state name.
	 *
	 * @param mixed  $value The user-specified state value.
	 *
	 * @return void
	 */
	public function __set($name, $value)
	{
		$this->set($name, $value);
	}

	/**
	 * Test existence of a state variable
	 *
	 * @param string $name The state name
	 *
	 * @return boolean
	 */
	public function __isset($name)
	{
		return isset($this->data[$name]);
	}

	/**
	 * Unset a state value
	 *
	 * @param string $name The state name.
	 *
	 * @return void
	 */
	public function __unset($name)
	{
		if (isset($this->data[$name]))
		{
			$this->data[$name]->value = $this->data[$name]->default;
		}
	}
}AbstractModel.php000064400000000613151160003150007771 0ustar00<?php


namespace Nextend\Framework\Model;


use Nextend\Framework\Pattern\MVCHelperTrait;

abstract class AbstractModel {

    use MVCHelperTrait;

    /**
     * AbstractModel constructor.
     *
     * @param MVCHelperTrait $helper
     */
    public function __construct($helper) {

        $this->setMVCHelper($helper);
        $this->init();
    }

    protected function init() {

    }
}AbstractModelTable.php000064400000001047151160003150010743
0ustar00<?php

namespace Nextend\Framework\Model;


use Nextend\Framework\Database\AbstractPlatformConnectorTable;

abstract class AbstractModelTable extends AbstractModel {

    /**
     * @var AbstractPlatformConnectorTable
     */
    protected $table;

    protected function init() {

        $this->table = $this->createConnectorTable();
    }

    /**
     * @return AbstractPlatformConnectorTable
     */
    protected abstract function createConnectorTable();

    public function getTableName() {
        return $this->table->getTableName();
    }
}ApplicationSection.php000064400000004575151160003150011050
0ustar00<?php

namespace Nextend\Framework\Model;

class ApplicationSection {

    private $application = 'system';

    /**
     * Quick cache implementation to prevent duplicate queries. It might
have bugs.
     *
     * @var array
     */
    protected $cache = array();

    public function __construct($application) {
        $this->application = $application;
    }

    public function getById($id, $section) {
        return Section::getById($id, $section);
    }

    public function setById($id, $value) {
        $this->cache = array();

        return Section::setById($id, $value);
    }

    public function get($section, $referenceKey = null, $default = null) {

        if (isset($this->cache[$section . '///' .
$referenceKey])) {
            return $this->cache[$section . '///' .
$referenceKey];
        }

        $attributes = array(
            "application" => $this->application,
            "section"     => $section
        );

        if ($referenceKey !== null) {
            $attributes['referencekey'] = $referenceKey;
        }
        $result =
Section::$tableSectionStorage->findByAttributes($attributes);
        if (is_array($result)) {
            $this->cache[$section . '///' . $referenceKey] =
$result['value'];

            return $result['value'];
        }

        return $default;
    }

    public function getAll($section, $referenceKey = null) {
        return Section::getAll($this->application, $section,
$referenceKey);
    }

    public function set($section, $referenceKey, $value) {
        if (isset($this->cache[$section . '///' .
$referenceKey])) {
            unset($this->cache[$section . '///' .
$referenceKey]);
        }

        Section::set($this->application, $section, $referenceKey,
$value);
    }

    public function add($section, $referenceKey, $value) {
        if (isset($this->cache[$section . '///' .
$referenceKey])) {
            unset($this->cache[$section . '///' .
$referenceKey]);
        }

        return Section::add($this->application, $section, $referenceKey,
$value);
    }

    public function delete($section, $referenceKey = null) {
        if (isset($this->cache[$section . '///' .
$referenceKey])) {
            unset($this->cache[$section . '///' .
$referenceKey]);
        }

        return Section::delete($this->application, $section,
$referenceKey);
    }

    public function deleteById($id) {
        return Section::deleteById($id);
    }
}Section.php000064400000011165151160003150006655 0ustar00<?php

namespace Nextend\Framework\Model;

use Nextend\Framework\Database\AbstractPlatformConnectorTable;
use Nextend\Framework\Database\Database;
use Nextend\Framework\Plugin;

class Section {

    /** @var AbstractPlatformConnectorTable */
    public static $tableSectionStorage;

    public function __construct() {

        self::$tableSectionStorage =
Database::getTable("nextend2_section_storage");
    }

    public static function get($application, $section, $referenceKey =
null) {
        $attributes = array(
            "application" => $application,
            "section"     => $section
        );

        if ($referenceKey !== null) {
            $attributes['referencekey'] = $referenceKey;
        }

        return
self::$tableSectionStorage->findByAttributes($attributes);
    }

    public static function getById($id, $section = null) {
        static $cache = array();
        if ($id === 0) {
            return null;
        }
        if (!isset($cache[$section])) {
            $cache[$section] = array();
        } else if (isset($cache[$section][$id])) {
            return $cache[$section][$id];
        }

        $cache[$section][$id] = null;
        if ($section) {
            Plugin::doAction($section, array(
                $id,
                &$cache[$section][$id]
            ));
            if ($cache[$section][$id]) {
                return $cache[$section][$id];
            }
        }

        $cache[$section][$id] =
self::$tableSectionStorage->findByAttributes(array(
            "id" => $id
        ));
        if ($section && $cache[$section][$id]['section']
!= $section) {
            $cache[$section][$id] = null;

            return $cache[$section][$id];
        }

        return $cache[$section][$id];
    }

    public static function getAll($application, $section, $referenceKey =
null) {
        $attributes = array(
            "application" => $application,
            "section"     => $section
        );

        if ($referenceKey !== null) {
            $attributes['referencekey'] = $referenceKey;
        }

        $rows =
self::$tableSectionStorage->findAllByAttributes($attributes, array(
            "id",
            "referencekey",
            "value",
            "system",
            "editable"
        ));

        Plugin::doAction($application . $section, array(
            $referenceKey,
            &$rows
        ));

        return $rows;
    }

    public static function add($application, $section, $referenceKey,
$value, $system = 0, $editable = 1) {
        $row = array(
            "application"  => $application,
            "section"      => $section,
            "referencekey" => '',
            "value"        => $value,
            "system"       => $system,
            "editable"     => $editable
        );

        if ($referenceKey !== null) {
            $row["referencekey"] = $referenceKey;
        }

        self::$tableSectionStorage->insert($row);

        return self::$tableSectionStorage->insertId();
    }


    public static function set($application, $section, $referenceKey,
$value, $system = 0, $editable = 1) {

        $result = self::getAll($application, $section, $referenceKey);

        if (empty($result)) {
            return self::add($application, $section, $referenceKey, $value,
$system, $editable);
        } else {
            $attributes = array(
                "application" => $application,
                "section"     => $section
            );

            if ($referenceKey !== null) {
                $attributes['referencekey'] = $referenceKey;
            }
            self::$tableSectionStorage->update(array('value'
=> $value), $attributes);

            return true;
        }
    }

    public static function setById($id, $value) {

        $result = self::getById($id);

        if ($result !== null && $result['editable']) {
            self::$tableSectionStorage->update(array('value'
=> $value), array(
                "id" => $id
            ));

            return true;
        }

        return false;
    }

    public static function delete($application, $section, $referenceKey =
null) {

        $attributes = array(
            "application" => $application,
            "section"     => $section,
            "system"      => 0
        );

        if ($referenceKey !== null) {
            $attributes['referencekey'] = $referenceKey;
        }

        self::$tableSectionStorage->deleteByAttributes($attributes);

        return true;
    }

    public static function deleteById($id) {

        self::$tableSectionStorage->deleteByAttributes(array(
            "id"     => $id,
            "system" => 0
        ));

        return true;
    }
}

new Section();StorageSectionManager.php000064400000000722151160003150011472
0ustar00<?php


namespace Nextend\Framework\Model;


class StorageSectionManager {

    /** @var ApplicationSection[] */
    private static $storageTypes = array();

    /**
     * @param $type
     *
     * @return ApplicationSection
     */
    public static function getStorage($type) {

        if (!isset(self::$storageTypes[$type])) {
            self::$storageTypes[$type] = new ApplicationSection($type);
        }

        return self::$storageTypes[$type];
    }
}index.html000064400000000054151160065270006543
0ustar00<html><body
bgcolor="#FFFFFF"></body></html>Load.php000064400000005626151160065270006150
0ustar00<?php
/**
 * @package    Joomla.Component.Builder
 *
 * @created    4th September, 2022
 * @author     Llewellyn van der Merwe <https://dev.vdm.io>
 * @git        Joomla Component Builder
<https://git.vdm.dev/joomla/Component-Builder>
 * @copyright  Copyright (C) 2015 Vast Development Method. All rights
reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace VDM\Joomla\Model;


use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Interfaces\ModelInterface;
use VDM\Joomla\Abstraction\Model;


/**
 * Power Model Load
 * 
 * @since 3.2.2
 */
final class Load extends Model implements ModelInterface
{
	/**
	 * Model the value
	 *          Example: $this->value(value, 'field_key',
'table_name');
	 *
	 * @param   mixed           $value    The value to model
	 * @param   string          $field    The field key
	 * @param   string|null     $table    The table
	 *
	 * @return  mixed
	 * @since 3.2.0
	 */
	public function value($value, string $field, ?string $table = null)
	{
		// set the table name
		if (empty($table))
		{
			$table = $this->getTable();
		}

		// check if this is a valid table (don't touch null)
		if ($value !== null && ($store = $this->table->get($table,
$field, 'store')) !== null)
		{
			// open the value based on the store method
			switch($store)
			{
				case 'base64':
					$value = base64_decode((string) $value);
				break;
				case 'json':
					$value = json_decode($value);
				break;
			}
		}

		return $value;
	}

	/**
	 * Validate before the value is modelled
	 *
	 * @param   mixed         $value   The field value
	 * @param   string|null   $field     The field key
	 * @param   string|null   $table   The table
	 *
	 * @return  bool
	 * @since 3.2.0
	 */
	protected function validateBefore(&$value, ?string $field = null,
?string $table = null): bool
	{
		// only strings or numbers allowed
		if (StringHelper::check($value) || is_numeric($value))
		{
			return true;
		}
		// check if we allow empty
		elseif ($this->getAllowEmpty() && empty($value))
		{
			return true;
		}
		// remove empty values
		return false;
	}

	/**
	 * Validate after the value is modelled
	 *
	 * @param   mixed         $value   The field value
	 * @param   string|null   $field     The field key
	 * @param   string|null   $table   The table
	 *
	 * @return  bool
	 * @since 3.2.0
	 */
	protected function validateAfter(&$value, ?string $field = null,
?string $table = null): bool
	{
		// only strings or numbers allowed
		if (StringHelper::check($value) || ArrayHelper::check($value, true)  ||
ObjectHelper::check($value) || is_numeric($value))
		{
			return true;
		}
		// check if we allow empty
		elseif ($this->getAllowEmpty() && empty($value))
		{
			return true;
		}
		// remove empty values
		return false;
	}
}

Upsert.php000064400000005577151160065270006560 0ustar00<?php
/**
 * @package    Joomla.Component.Builder
 *
 * @created    4th September, 2022
 * @author     Llewellyn van der Merwe <https://dev.vdm.io>
 * @git        Joomla Component Builder
<https://git.vdm.dev/joomla/Component-Builder>
 * @copyright  Copyright (C) 2015 Vast Development Method. All rights
reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace VDM\Joomla\Model;


use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Interfaces\ModelInterface;
use VDM\Joomla\Abstraction\Model;


/**
 * Power Model Update or Insert
 * 
 * @since 3.2.0
 */
final class Upsert extends Model implements ModelInterface
{
	/**
	 * Model the value
	 *          Example: $this->value(value, 'field_key',
'table_name');
	 *
	 * @param   mixed           $value    The value to model
	 * @param   string          $field    The field key
	 * @param   string|null     $table    The table
	 *
	 * @return  mixed
	 * @since 3.2.0
	 */
	public function value($value, string $field, ?string $table = null)
	{
		// set the table name
		if (empty($table))
		{
			$table = $this->getTable();
		}

		// check if this is a valid table
		if (($store = $this->table->get($table, $field, 'store'))
!== null)
		{
			// open the value based on the store method
			switch($store)
			{
				case 'base64':
					$value = base64_encode((string) $value);
				break;
				case 'json':
					$value = json_encode($value,  JSON_FORCE_OBJECT);
				break;
			}
		}

		return $value;
	}

	/**
	 * Validate before the value is modelled
	 *
	 * @param   mixed         $value   The field value
	 * @param   string|null   $field     The field key
	 * @param   string|null   $table   The table
	 *
	 * @return  bool
	 * @since 3.2.0
	 */
	protected function validateBefore(&$value, ?string $field = null,
?string $table = null): bool
	{
		// check values
		if (StringHelper::check($value) || ArrayHelper::check($value, true)  ||
ObjectHelper::check($value) || is_numeric($value))
		{
			return true;
		}
		// check if we allow empty
		elseif ($this->getAllowEmpty() && empty($value))
		{
			return true;
		}
		// remove empty values
		return false;
	}

	/**
	 * Validate after the value is modelled
	 *
	 * @param   mixed         $value   The field value
	 * @param   string|null   $field     The field key
	 * @param   string|null   $table   The table
	 *
	 * @return  bool
	 * @since 3.2.0
	 */
	protected function validateAfter(&$value, ?string $field = null,
?string $table = null): bool
	{
		// only strings or numbers allowed
		if (StringHelper::check($value) || is_numeric($value))
		{
			return true;
		}
		// check if we allow empty
		elseif ($this->getAllowEmpty() && empty($value))
		{
			return true;
		}
		// remove empty values
		return false;
	}
}