Spade

Mini Shell

Directory:~$ /home/lmsyaran/public_html/joomla5/administrator/components/com_fabrik/models/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ /home/lmsyaran/public_html/joomla5/administrator/components/com_fabrik/models/group.php

<?php
/**
 * Fabrik Admin Group Model
 *
 * @package     Joomla.Administrator
 * @subpackage  Fabrik
 * @copyright   Copyright (C) 2005-2020  Media A-Team, Inc. - All rights
reserved.
 * @license     GNU/GPL http://www.gnu.org/copyleft/gpl.html
 * @since       1.6
 */

// No direct access
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Factory;
use Joomla\Utilities\ArrayHelper;

require_once 'fabmodeladmin.php';

/**
 * Fabrik Admin Group Model
 *
 * @package     Joomla.Administrator
 * @subpackage  Fabrik
 * @since       3.0
 */
class FabrikAdminModelGroup extends FabModelAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var  string
	 */
	protected $text_prefix = 'COM_FABRIK_GROUP';

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param   string $type   The table type to instantiate
	 * @param   string $prefix A prefix for the table class name. Optional.
	 * @param   array  $config Configuration array for model. Optional.
	 *
	 * @return  Table    A database object
	 */
	public function getTable($type = 'Group', $prefix =
'FabrikTable', $config = array())
	{
		$config['dbo'] = FabrikWorker::getDbo(true);

		return FabTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @param   array $data     Data for the form.
	 * @param   bool  $loadData True if the form is to load its own data
(default case), false if not.
	 *
	 * @return  mixed    A Form object on success, false on failure
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_fabrik.group',
'group', array('control' => 'jform',
'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed    The data for the form.
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data =
$this->app->getUserState('com_fabrik.edit.group.data',
array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		return $data;
	}

	/**
	 * Take an array of forms ids and return the corresponding group ids
	 * used in list publish code
	 *
	 * @param   array $ids form ids
	 *
	 * @return  string
	 */
	public function swapFormToGroupIds($ids = array())
	{
		if (empty($ids))
		{
			return array();
		}

		$ids   = ArrayHelper::toInteger($ids);
		$db    = FabrikWorker::getDbo(true);
		$query = $db->getQuery(true);
		$query->select('group_id')->from('#__fabrik_formgroup')->where('form_id
IN (' . implode(',', $ids) . ')');
		$db->setQuery($query);
		$res = $db->loadColumn();

		return $res;
	}

	/**
	 * Does the group have a primary key element
	 *
	 * @param   array $data jform posted data
	 *
	 * @return  bool
	 */
	protected function checkRepeatAndPK($data)
	{
		/** @var FabrikFEModelGroup $groupModel */
		$groupModel =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('Group',
'FabrikFEModel');
		$groupModel->setId($data['id']);
		$listModel     = $groupModel->getListModel();
		$pk            =
FabrikString::safeColName($listModel->getPrimaryKey());
		$elementModels = $groupModel->getMyElements();

		foreach ($elementModels as $elementModel)
		{
			if (FabrikString::safeColName($elementModel->getFullName(false,
false)) == $pk)
			{
				return false;
			}
		}

		return true;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array $data The form data.
	 *
	 * @return  boolean  True on success, False on error.
	 */
	public function save($data)
	{
		if ($data['id'] == 0)
		{
			$data['created_by']       =
$this->user->get('id');
			$data['created_by_alias'] =
$this->user->get('username');
			$data['created']          = Factory::getDate()->toSql();
		} elseif (FabrikWorker::isNullDate($data['created'])) {
			$data['created'] = null;
		}
		$makeJoin   = false;
		$unMakeJoin = false;

		if ($this->checkRepeatAndPK($data))
		{
			$makeJoin = ($data['params']['repeat_group_button']
== 1);

			if ($makeJoin)
			{
				$data['is_join'] = 1;
			}
			elseif ($data['is_join'] == 1)
			{
				/*
				 * $$$ rob - this was destroying legitimate joins on saving the group
				 * see http://fabrikar.com/forums/showthread.php?t=29385
				 * commenting out for now until Hugh can take another look at what ever
he was trying to solve
				 * in commit #ee697dd
				 *
				$unMakeJoin = true;
				$data['is_join'] = 0;
				*/
			}
		}
		else
		{
			if (($data['params']['repeat_group_button'] == 1))
			{
				$data['params']['repeat_group_button'] = 0;
				$this->app->enqueueMessage('You can not set the group
containing the list primary key to be repeatable',
'notice');
			}
		}

		$data['params'] = json_encode($data['params']);
		$return         = parent::save($data);
		$data['id']     = $this->getState($this->getName() .
'.id');

		if ($return)
		{
			$this->makeFormGroup($data);

			if ($makeJoin)
			{
				/**
				 * $$$ rob added this check as otherwise toggling group from repeat
				 * to norepeat back to repeat incorrectly created a 2nd join
				 */
				if (!$this->joinedGroupExists($data['id']))
				{
					$return = $this->makeJoinedGroup($data);
				}
				else
				{
					$this->checkFKIndex($data);
				}

				// Update for the is_join change
				if ($return)
				{
					$return = parent::save($data);
				}

			}
			else
			{
				// $data['is_join'] =  0; // NO! none repeat joined groups
were getting unset here - not right!
				if ($unMakeJoin)
				{
					$this->unMakeJoinedGroup($data);
				}

				$return = parent::save($data);
			}
		}

		parent::cleanCache('com_fabrik');

		return $return;
	}

	/**
	 * Check if a group id has an associated join already created
	 *
	 * @param   int $id group id
	 *
	 * @return  boolean
	 */
	protected function joinedGroupExists($id)
	{
		$item = FabTable::getInstance('Group',
'FabrikTable');
		$item->load($id);

		return $item->join_id == '' ? false : true;
	}

	/**
	 * Clears old form group entries if found and adds new ones
	 *
	 * @param   array $data jform data
	 *
	 * @return void
	 */
	protected function makeFormGroup($data)
	{
		if ($data['form'] == '')
		{
			return;
		}

		$formId = (int) $data['form'];
		$id     = (int) $data['id'];
		$item   = FabTable::getInstance('FormGroup',
'FabrikTable');
		$item->load(array('form_id' => $formId,
'group_id' => $id));

		if ($item->id == '')
		{
			// Get max group order
			$db    = FabrikWorker::getDbo(true);
			$query = $db->getQuery(true);
			$query->select('MAX(ordering)')->from('#__fabrik_formgroup')->where('form_id
= ' . $formId);
			$db->setQuery($query);
			$next           = (int) $db->loadResult() + 1;
			$item->ordering = $next;
			$item->form_id  = $formId;
			$item->group_id = $id;
			$item->store();
		}
	}

	/**
	 * Check if an index exists on the parent_id for a repeat table.
	 * We forgot to index the parent_id until 32/2015, which could have an
ipact on getData()
	 * query performance.  Only called from the save() method.
	 *
	 * @param   array $data jForm data
	 */
	private function checkFKIndex($data)
	{
		$groupModel =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('Group',
'FabrikFEModel');
		$groupModel->setId($data['id']);
		$listModel = $groupModel->getListModel();
		$item      = FabTable::getInstance('Group',
'FabrikTable');
		$item->load($data['id']);
		$join = $this->getTable('join');
		$join->load(array('id' => $item->join_id));
		$fkFieldName = $join->get('table_join') . '___' .
$join->get('table_join_key');
		$fields      =
$listModel->getDBFields($join->get('join_from_table'),
'Field');
		$pkField     = FArrayHelper::getValue($fields,
$join->get('table_key'), false);

		switch ($pkField->BaseType)
		{
			case 'VARCHAR':
				$pkSize = (int) $pkField->BaseLength < 10 ?
$pkField->BaseLength : 10;
				break;
			case 'INT':
			case 'DATETIME':
			default:
				$pkSize = '';
				break;
		}

		$listModel->addIndex($fkFieldName, 'parent_fk',
'INDEX', $pkSize);
	}

	/**
	 * A group has been set to be repeatable but is not part of a join
	 * so we want to:
	 * Create a new db table for the groups elements ( + check if its not
already there)
	 *
	 * @param   array &$data jForm data
	 *
	 * @throws Exception
	 *
	 * @return  bool
	 */
	public function makeJoinedGroup(&$data)
	{
		/** @var FabrikFEModelGroup $groupModel */
		$groupModel =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('Group',
'FabrikFEModel');
		$groupModel->setId($data['id']);
		$listModel          = $groupModel->getListModel();
		$db                 = $listModel->getDb();
		$list               = $listModel->getTable();
		$elements           = (array) $groupModel->getMyElements();
		$names              = array();
		$fields             = $listModel->getDBFields(null,
'Field');
		$names['id']        = "id INT(11) NOT NULL AUTO_INCREMENT
PRIMARY KEY";
		$names['parent_id'] = "parent_id INT(11)";

		foreach ($elements as $element)
		{
			$fName = $element->getElement()->name;
			/**
			 * if we are making a repeat group from the primary group then we
don't want to
			 * overwrite the repeat group tables id definition with that of the main
tables
			 */
			if (!array_key_exists($fName, $names))
			{
				$str   = FabrikString::safeColName($fName);
				$field = FArrayHelper::getValue($fields, $fName);

				if (is_object($field))
				{
					$str .= " " . $field->Type . " ";

					if ($field->Null == 'NO')
					{
						$str .= "NOT NULL ";
					}

					$names[$fName] = $str;
				}
				else
				{
					$names[$fName] = $db->quoteName($fName) . ' ' .
$element->getFieldDescription();
				}
			}
		}

		$db->setQuery('show tables');
		$newTableName   = $list->db_table_name . '_' .
$data['id'] . '_repeat';
		$existingTables = $db->loadColumn();

		if (!in_array($newTableName, $existingTables))
		{
			// No existing repeat group table found so lets create it
			$query = 'CREATE TABLE IF NOT EXISTS ' .
$db->qn($newTableName) . ' (' . implode(',', $names)
. ')';
			$db->setQuery($query);
			$db->execute();

			// Create id and parent_id elements
			$listModel->makeIdElement($data['id']);
			$listModel->makeFkElement($data['id']);
		}
		else
		{
			if (trim($list->db_table_name) == '')
			{
				// New group not attached to a form
				throw new
Exception(Text::_('COM_FABRIK_GROUP_CANT_MAKE_JOIN_NO_DB_TABLE'));
			}

			// Repeat table already created - lets check its structure matches the
group elements
			$db->setQuery('DESCRIBE ' . $db->qn($newTableName));
			$existingFields = $db->loadObjectList('Field');
			$newFields      = array_diff(array_keys($names),
array_keys($existingFields));

			if (!empty($newFields))
			{
				$lastField = array_pop($existingFields);
				$lastField = $lastField->Field;

				foreach ($newFields as $newField)
				{
					$info = $names[$newField];
					$db->setQuery('ALTER TABLE ' . $db->qn($newTableName)
. ' ADD COLUMN ' . $info . ' AFTER ' . $lastField);
					$db->execute();
				}
			}
		}
		// Create the join as well

		$jData = array('list_id' => $list->id,
'element_id' => 0, 'join_from_table' =>
$list->db_table_name, 'table_join' => $newTableName,
			'table_key' =>
FabrikString::shortColName($list->db_primary_key),
'table_join_key' => 'parent_id',
'join_type' => 'left',
			'group_id' => $data['id']);

		// Load the matching join if found.
		$join = $this->getTable('join');
		$join->load($jData);
		$opts            = new stdClass;
		$opts->type      = 'group';
		$jData['params'] = json_encode($opts);
		$join->bind($jData);

		// Update or save a new join
		$join->store();
		$data['is_join'] = 1;

		$listModel->addIndex($newTableName . '___parent_id',
'parent_fk', 'INDEX', '');

		return true;
	}

	/**
	 * Repeat has been turned off for a group, so we need to remove the join.
	 * For now, leave the repeat table intact, just remove the join
	 * and the 'id' and 'parent_id' elements.
	 *
	 * @param   array &$data jForm data
	 *
	 * @return boolean
	 */
	public function unMakeJoinedGroup(&$data)
	{
		if (empty($data['id']))
		{
			return false;
		}

		$db    = FabrikWorker::getDbo(true);
		$query = $db->getQuery(true);
		$query->delete('#__fabrik_joins')->where('group_id =
' . $data['id']);
		$db->setQuery($query);
		$return = $db->execute();

		$query = $db->getQuery(true);
		$query->select('id')->from('#__fabrik_elements')
			->where('group_id  = ' . $data['id'] . ' AND
name IN ("id", "parent_id")');
		$db->setQuery($query);
		$elementIds   = $db->loadColumn();
		// FabrikModelElement does not exsist !! Maybe this is never used ?? Does
not work in J!4
		$elementModel = BaseDatabaseModel::getInstance('Element',
'FabrikModel');
		$return       = $return && $elementModel->delete($elementIds);

		return $return;
	}

	/**
	 * Method to delete one or more records.
	 *
	 * @param   array &$pks           An array of record primary keys.
	 * @param   bool  $deleteElements delete elements?
	 *
	 * @return  bool  True if successful, false if an error occurs.
	 */
	public function delete(&$pks, $deleteElements = false)
	{
		if (empty($pks))
		{
			return true;
		}

		if (parent::delete($pks))
		{
			if ($this->deleteFormGroups($pks))
			{
				if ($deleteElements)
				{
					return $this->deleteElements($pks);
				}
				else
				{
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * Delete group elements
	 *
	 * @param   array $pks group ids to delete elements from
	 *
	 * @return  bool
	 */
	public function deleteElements($pks)
	{
		$db    = FabrikWorker::getDbo(true);
		$pks   = ArrayHelper::toInteger($pks);
		$query = $db->getQuery(true);
		$query->select('id')->from('#__fabrik_elements')->where('group_id
IN (' . implode(',', $pks) . ')');
		$db->setQuery($query);
		$elementIds   = $db->loadColumn();
		$elementModel = BaseDatabaseModel::getInstance('Element',
'FabrikAdminModel');

		return $elementModel->delete($elementIds);
	}

	/**
	 * Delete form groups
	 *
	 * @param   array $pks group ids
	 *
	 * @return  bool
	 */
	public function deleteFormGroups($pks)
	{
		$db    = FabrikWorker::getDbo(true);
		$pks   = ArrayHelper::toInteger($pks);
		$query = $db->getQuery(true);
		$query->delete('#__fabrik_formgroup')->where('group_id
IN (' . implode(',', $pks) . ')');
		$db->setQuery($query);

		return $db->execute();
	}
}