Spade
Mini Shell
| Directory:~$ /home/lmsyaran/public_html/joomla5/administrator/components/com_fabrik/models/ |
| [Home] [System Details] [Kill Me] |
<?php
/**
* Admin Element 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\Table\Table;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Date\Date;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormRule;
use Joomla\Utilities\ArrayHelper;
use Joomla\String\StringHelper;
use Joomla\CMS\Factory;
jimport('joomla.application.component.modeladmin');
require_once 'fabmodeladmin.php';
/**
* Admin Element Model
*
* @package Joomla.Administrator
* @subpackage Fabrik
* @since 3.0
*/
class FabrikAdminModelElement extends FabModelAdmin
{
/**
* The prefix to use with controller messages.
*
* @var string
*/
protected $text_prefix = 'COM_FABRIK_ELEMENT';
/**
* Validation plugin models for this element
*
* @since 3.0.6
*
* @var array
*/
protected $aValidations = null;
/**
* Core Joomla and Fabrik table names
*
* @var array
*/
/*
protected $core = array('#__assets',
'#__banner_clients', '#__banner_tracks',
'#__banners', '#__categories',
'#__contact_details', '#__content',
'#__content_frontpage', '#__content_rating',
'#__core_log_searches', '#__extensions',
'#__fabrik_connections', '#__fabrik_cron',
'#__fabrik_elements', '#__fabrik_form_sessions',
'#__fabrik_formgroup', '#__fabrik_forms',
'#__fabrik_groups',
'#__fabrik_joins', '#__fabrik_jsactions',
'#__fabrik_lists', '#__fabrik_log',
'#__fabrik_packages',
'#__fabrik_validations', '#__fabrik_visualizations',
'#__fb_contact_sample', '#__languages',
'#__menu', '#__menu_types', '#__messages',
'#__messages_cfg', '#__modules',
'#__modules_menu', '#__newsfeeds',
'#__redirect_links', '#__schemas',
'#__session', '#__template_styles',
'#__update_categories', '#__update_sites',
'#__update_sites_extensions', '#__updates',
'#__user_profiles', '#__user_usergroup_map',
'#__usergroups', '#__users',
'#__viewlevels', '#__weblinks');
*/
protected $core = array('#__assets',
'#__banner_clients', '#__banner_tracks',
'#__banners', '#__categories',
'#__contact_details', '#__content',
'#__content_frontpage', '#__content_rating',
'#__core_log_searches', '#__extensions',
'#__fabrik_connections', '#__fabrik_cron',
'#__fabrik_elements', '#__fabrik_form_sessions',
'#__fabrik_formgroup', '#__fabrik_forms',
'#__fabrik_groups',
'#__fabrik_joins', '#__fabrik_jsactions',
'#__fabrik_lists', '#__fabrik_log',
'#__fabrik_validations', '#__fabrik_visualizations',
'#__fb_contact_sample', '#__languages',
'#__menu', '#__menu_types', '#__messages',
'#__messages_cfg', '#__modules',
'#__modules_menu', '#__newsfeeds',
'#__redirect_links', '#__schemas',
'#__session', '#__template_styles',
'#__update_categories', '#__update_sites',
'#__update_sites_extensions', '#__updates',
'#__user_profiles', '#__user_usergroup_map',
'#__usergroups', '#__users',
'#__viewlevels', '#__weblinks');
/**
* Constructor.
* Ensure that we use the fabrik db model for the dbo
*
* @param array $config An optional associative array of configuration
settings.
*/
public function __construct($config = array())
{
$config['dbo'] = FabrikWorker::getDbo(true);
parent::__construct($config);
}
/**
* 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 = 'Element', $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.element',
'element', array('control' => 'jform',
'load_data' => $loadData));
if (empty($form))
{
return false;
}
$form->model = $this;
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.element.data',
array());
if (empty($data))
{
$data = $this->getItem();
}
return $data;
}
/**
* Get elements
*
* @deprecated since 3.1b2
*
* @return array
*/
public function getElements()
{
return array();
}
/**
* Toggle adding / removing the elment from the list view
*
* @param array &$pks primary keys
* @param var $value add (1) or remove (0) from list view
*
* @return bool
*/
public function addToListView(&$pks, $value = 1)
{
// Initialise variables.
// $dispatcher = JEventDispatcher::getInstance();
// $dispatcher = Factory::getApplication()->getDispatcher();
$item = $this->getTable();
$pks = (array) $pks;
// Include the content plugins for the change of state event.
PluginHelper::importPlugin('content');
// Access checks.
foreach ($pks as $i => $pk)
{
if ($item->load($pk))
{
if (!$this->canEditState($item))
{
// Prune items that you can't change.
unset($pks[$i]);
// JError::raiseWarning(403,
Text::_('JLIB_APPLICATION_ERROR_EDIT_STATE_NOT_PERMITTED'));
\Joomla\CMS\Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDIT_STATE_NOT_PERMITTED'),
'warning');
}
}
}
// Attempt to change the state of the records.
if (!$item->addToListView($pks, $value,
$this->user->get('id')))
{
$this->setError($item->getError());
return false;
}
$context = $this->option . '.' . $this->name;
// Trigger the onContentChangeState event.
// $result = $dispatcher->triggerEvent($this->event_change_state,
array($context, $pks, $value));
$result =
Factory::getApplication()->triggerEvent($this->event_change_state,
array($context, $pks, $value));
if (in_array(false, $result, true))
{
$this->setError($item->getError());
return false;
}
return true;
}
/**
* Get the js events that are used by the element
*
* @return array
*/
public function getJsEvents()
{
$db = FabrikWorker::getDbo(true);
$query = $db->getQuery(true);
$id = (int) $this->getItem()->id;
$query->select('*')->from('#__fabrik_jsactions')->where('element_id
= ' . $id)->order('id');
$db->setQuery($query);
$items = $db->loadObjectList();
for ($i = 0; $i < count($items); $i++)
{
$items[$i]->params = json_decode($items[$i]->params);
$items[$i]->params->js_e_value =
htmlspecialchars_decode($items[$i]->params->js_e_value);
}
return $items;
}
/**
* Load the actual validation plugins that the element uses
*
* @return array plugins
*/
public function getPlugins()
{
$item = $this->getItem();
$plugins = (array) FArrayHelper::getNestedValue($item->params,
'validations.plugin', array());
$published = (array) FArrayHelper::getNestedValue($item->params,
'validations.plugin_published', array());
$icons = (array) FArrayHelper::getNestedValue($item->params,
'validations.show_icon', array());
$must_validate = (array) FArrayHelper::getNestedValue($item->params,
'validations.must_validate', array());
$in = (array) FArrayHelper::getNestedValue($item->params,
'validations.validate_in', array());
$on = (array) FArrayHelper::getNestedValue($item->params,
'validations.validation_on', array());
$hidden = (array) FArrayHelper::getNestedValue($item->params,
'validations.validate_hidden', array());
$return = array();
for ($i = 0; $i < count($plugins); $i++)
{
$o = new stdClass;
$o->plugin = $plugins[$i];
$o->published = FArrayHelper::getValue($published, $i, 1);
$o->show_icon = FArrayHelper::getValue($icons, $i, 1);
$o->must_validate = FArrayHelper::getValue($must_validate, $i, 1);
$o->validate_in = FArrayHelper::getValue($in, $i,
'both');
$o->validation_on = FArrayHelper::getValue($on, $i,
'both');
$o->validate_hidden = FArrayHelper::getValue($hidden, $i, 1);
$return[] = $o;
}
return $return;
}
/**
* Get the js code to build the plugins etc
*
* @return string js code
*/
public function getJs()
{
$item = $this->getItem();
$opts = new stdClass;
$opts->plugin = $item->plugin;
$opts->parentid = (int) $item->parent_id;
$opts->jsevents = $this->getJsEvents();
$opts->id = (int) $item->id;
// $opts->deleteButton = FabrikWorker::j3() ? '<a
class="btn btn-danger"><i
class="icon-delete"></i> ' : '<a
class="removeButton">';
$opts->deleteButton = '<a class="btn
btn-danger"><i class="icon-delete"></i>
';
$opts->deleteButton .= Text::_('COM_FABRIK_DELETE') .
'</a>';
$opts = json_encode($opts);
Text::script('COM_FABRIK_PLEASE_SELECT');
Text::script('COM_FABRIK_JS_SELECT_EVENT');
Text::script('COM_FABRIK_JS_INLINE_JS_CODE');
Text::script('COM_FABRIK_JS_INLINE_COMMENT_WARNING');
Text::script('COM_FABRIK_JS_WHEN_ELEMENT');
Text::script('COM_FABRIK_JS_IS');
Text::script('COM_FABRIK_JS_NO_ACTION');
$js[] = "window.addEvent('domready', function () {";
$js[] = "\tvar opts = $opts;";
$plugins = json_encode($this->getPlugins());
$js[] = "\tFabrik.controller = new fabrikAdminElement($plugins,
opts, " . (int) $this->getItem()->id . ");";
$js[] = "})";
return implode("\n", $js);
}
/**
* Get html form fields for a plugin (filled with
* current element's plugin data
*
* @param string $plugin plugin name
*
* @return string html form fields
*/
public function getPluginHTML($plugin = null)
{
$app = $this->app;
$input = $app->input;
$str = '';
$item = $this->getItem();
/* J4 hack to update the bootstrap class from existing elements */
$item = $this->updBsClass($item);
if (empty($plugin))
{
$plugin = $item->plugin;
}
$input->set('view', 'element');
PluginHelper::importPlugin('fabrik_element', $plugin);
if ($plugin == '')
{
$str = '<div class="alert">' .
Text::_('COM_FABRIK_SELECT_A_PLUGIN') . '</div>';
}
else
{
try
{
$plugin = $this->pluginManager->getPlugIn($plugin,
'Element');
// $mode = FabrikWorker::j3() ? 'nav-tabs' : '';
$mode = 'nav-tabs';
$str =
$plugin->onRenderAdminSettings(ArrayHelper::fromObject($item), null,
$mode);
} catch (RuntimeException $e)
{
$str = '<div class="alert">' .
Text::_('COM_FABRIK_SELECT_A_PLUGIN') . '</div>';
}
}
return $str;
}
/**
* Method to look for old style boostrap classes and transform to new BS5
classes.
*
* @param mixed $data The data for the form
* @return mixed The data for the form.
*/
protected function updBsClass($item)
{
$classList = [
'input-mini' => 'col-sm-2',
'input-small' => 'col-sm-4',
'input-medium' => 'col-sm-6',
'input-large' => 'col-sm-8',
'input-xlarge' => 'col-sm-10',
'input-xxlarge' => 'col-sm-12',
'input-block-level' => 'col-sm-12',
];
if (property_exists($item, 'params') &&
array_key_exists('bootstrap_class', $item->params)) {
// check for old col-md and span classes
$bsClass = str_replace(['col-md-', 'span'],
'col-sm-', $item->params['bootstrap_class']);
if (array_key_exists($bsClass, $classList)) {
$bsClass = $classList[$bsClass];
}
// If after all that the class is empty, set a sensible default
if (empty($bsClass)) $bsClass = 'col-sm-6';
// We will just go ahead and update it, if it didn't change there
is no harm
$item->params['bootstrap_class'] = $bsClass;
}
return $item;
}
/**
* Prepare and sanitise the table data prior to saving.
*
* @param Table $table A reference to a Table object.
*
* @return void
*
* @since 12.2
*/
protected function prepareTable($table)
{
}
/**
* Method to validate the form data.
*
* @param Form $form The form to validate against.
* @param array $data The data to validate.
* @param string $group The name of the field group to validate.
*
* @see FormRule
* @see InputFilter
*
* @return mixed Array of filtered data if valid, false otherwise.
*/
public function validate($form, $data, $group = null)
{
$ok = parent::validate($form, $data);
$input = $this->app->input;
// Standard jForm validation failed so we shouldn't test further as
we can't be sure of the data
if (!$ok)
{
return false;
}
$db = FabrikWorker::getDbo(true);
$elementModel = $this->getElementPluginModel($data);
$nameChanged = $data['name'] !==
$elementModel->getElement()->name;
$elementModel->getElement()->bind($data);
$listModel = $elementModel->getListModel();
$isView = (bool)$listModel->isView();
if ($data['id'] == '')
{
// Have to forcefully set group id otherwise listmodel id is blank
$elementModel->getElement()->group_id =
$data['group_id'];
if ($listModel->canAddFields() === false &&
$listModel->noTable() === false)
{
if ($isView)
{
$this->app->enqueueMessage(Text::_('COM_FABRIK_LIST_VIEW_SCHEMA_NOT_ALTERED'));
}
else
{
$this->setError(Text::_('COM_FABRIK_ERR_CANT_ADD_FIELDS'));
}
}
if (!FabrikWorker::validElementName($data['name']))
{
$this->setError(Text::_('COM_FABRIK_RESERVED_NAME_USED'));
}
}
else
{
if ($listModel->canAlterFields() === false && $nameChanged
&& $listModel->noTable() === false)
{
if ($isView)
{
$this->app->enqueueMessage(Text::_('COM_FABRIK_LIST_VIEW_SCHEMA_NOT_ALTERED'));
}
else
{
$this->setError(Text::_('COM_FABRIK_ERR_CANT_ALTER_EXISTING_FIELDS'));
}
}
if ($nameChanged &&
!FabrikWorker::validElementName($data['name'], false))
{
$this->setError(Text::_('COM_FABRIK_RESERVED_NAME_USED'));
}
}
$listModel = $elementModel->getListModel();
$groupModel = $elementModel->getGroupModel();
/**
* Test for duplicate names
* un-linking produces this error
*/
if (!$input->get('unlink', false) && (int)
$data['id'] === 0)
{
/**
* @FIXME - if a repeat group is created through the Group settings, we
don't add the auto-created
* table to the #_fabrik_lists table, so the following query obviously
doesn't find it ... so we
* barf when creating element in the repeat group with a "duplicate
name", even though it's going
* to be on a separate table.
*/
$query = $db->getQuery(true);
$query->select('t.id')->from('#__fabrik_joins AS
j');
$query->join('INNER', '#__fabrik_lists AS t ON
j.table_join = t.db_table_name');
$query->where('group_id = ' . (int)
$data['group_id'] . ' AND element_id = 0');
$db->setQuery($query);
$sql = (string)$query;
$joinTblId = (int) $db->loadResult();
$ignore = array($data['id']);
if ($joinTblId === 0)
{
if ($listModel->fieldExists($data['name'], $ignore,
$groupModel))
{
$this->setError(Text::_('COM_FABRIK_ELEMENT_NAME_IN_USE'));
}
}
else
{
/** @var FabrikFEModelList $joinListModel */
$joinListModel =
Factory::getApplication()->bootComponent('com_fabrik')->getMVCFactory()->createModel('List',
'FabrikFEModel');
$joinListModel->setId($joinTblId);
$joinEls = $joinListModel->getElements();
foreach ($joinEls as $joinEl)
{
if ($joinEl->getElement()->name == $data['name'])
{
$ignore[] = $joinEl->getElement()->id;
}
}
if ($joinListModel->fieldExists($data['name'], $ignore,
$groupModel))
{
$this->setError(Text::_('COM_FABRIK_ELEMENT_NAME_IN_USE'));
}
}
}
// Strip <p> tag from label
$data['label'] =
StringHelper::str_ireplace(array('<p>',
'</p>'), '', $data['label']);
return count($this->getErrors()) == 0 ? $data : false;
}
/**
* Load the element plugin / model for the posted data
*
* @param array $data posted data
*
* @return object element model
*/
private function getElementPluginModel($data)
{
$id = $data['id'];
$elementModel =
$this->pluginManager->getPlugIn($data['plugin'],
'element');
/**
* $$$ rob f3 - need to bind the data in here otherwise validate fails on
dup name test (as no group_id set)
* $$$ rob 29/06/2011 removed as you can't then test name changes in
validate() so now bind should be done after
* getElementPluginModel is called.
* $elementModel->getElement()->bind($data);
*/
$elementModel->setId($id);
return $elementModel;
}
/**
* Method to save the form data.
*
* @param array $data The form data.
*
* @return boolean True on success, False on error.
*/
public function save($data)
{
$config = ComponentHelper::getParams('com_fabrik');
if ($config->get('fbConf_wysiwyg_label', 0) == 0)
{
// Ensure the data is in the same format as when saved by the wysiwyg
element e.g. < becomes <
$data['label'] = htmlspecialchars($data['label']);
}
jimport('joomla.utilities.date');
$input = $this->app->input;
$new = $data['id'] == 0 ? true : false;
$params = $data['params'];
$data['name'] =
FabrikString::iclean($data['name']);
$name = $data['name'];
$params['validations'] = FArrayHelper::getValue($data,
'validationrule', array());
$elementModel = $this->getElementPluginModel($data);
$elementModel->getElement()->bind($data);
$origId = $input->getInt('id');
$row = $elementModel->getElement();
if ($new)
{
// Can't have elements starting with _
$name = ltrim($name, '_');
$data['name'] = $name;
// Have to forcefully set group id otherwise list model id is blank
$elementModel->getElement()->group_id =
$data['group_id'];
}
$listModel = $elementModel->getListModel();
$item = $listModel->getTable();
// Are we updating the name of the primary key element?
if ($row->name ===
FabrikString::shortColName($item->db_primary_key))
{
if ($name !== $row->name)
{
// Yes we are so update the table
$item->db_primary_key = str_replace($row->name, $name,
$item->db_primary_key);
$item->store();
}
}
$jsons = array('sub_values', 'sub_labels',
'sub_initial_selection');
foreach ($jsons as $json)
{
if (array_key_exists($json, $data))
{
$data[$json] = json_encode($data[$json]);
}
}
// Only update the element name if we can alter existing columns,
otherwise the name and field name become out of sync
$data['name'] = ($listModel->canAlterFields() || $new ||
$listModel->noTable()) ? $name : $input->get('name_orig',
'');
$ar = array('published', 'use_in_page_title',
'show_in_list_summary', 'link_to_detail',
'can_order', 'filter_exact_match');
foreach ($ar as $a)
{
if (!array_key_exists($a, $data))
{
$data[$a] = 0;
}
}
/**
* $$$ rob - test for change in element type
* (eg if changing from db join to field we need to remove the join
* entry from the #__fabrik_joins table
*/
$elementModel->beforeSave($row);
// Unlink linked elements
if ($input->get('unlink') == 'on')
{
$data['parent_id'] = 0;
}
$dateNow = new Date;
if ($row->id != 0)
{
$data['modified'] = $dateNow->toSql();
$data['modified_by'] = $this->user->get('id');
if (FabrikWorker::isNullDate($data['created'])) {
$data['created'] = null;
}
}
else
{
$data['created'] = $dateNow->toSql();
$data['created_by'] =
$this->user->get('id');
$data['created_by_alias'] =
$this->user->get('username');
}
/**
* $$$ hugh
* This insane chunk of code is needed because the validation rule params
are not in sequential,
* completely indexed arrays. What we have is single item arrays, with
specific numeric
* keys, like foo-something[0], bar-otherthing[2], etc. And if you
json_encode an array with incomplete
* or out of sequence numeric indexes, it encodes it as an object instead
of an array. Which means the first
* validation plugin will encode as an array, as it's params are
single [0] index, and the rest as objects.
* This foobars things, as we then don't know if validation params
are arrays or objects!
*
* One option would be to modify every validation, and test every param
we use, and if necessary convert it,
* but that would be a major pain in the ass.
*
* So ... we need to fill in the blanks in the arrays, and ksort them.
But, we need to know the param names
* for each validation. But as they are just stuck in with the rest of
the element params, there is no easy
* way of knowing which are validation params and which are element
params.
*
* So ... we need to load the validation objects, then load the XML file
for each one, and iterate through
* the fieldsets! Well, that's the only way I could come up with
doing it. Hopefully Rob can come up with
* a quicker and simpler way of doing this!
*/
$validations =
FArrayHelper::getValue($params['validations'],
'plugin', array());
$num_validations = count($validations);
$validation_plugins = $this->getValidations($elementModel,
$validations);
$i=0;
foreach ($validation_plugins as $plugin)
{
$pluginName = $validations[$i];
$i++;
$plugin_form = $plugin->getJForm();
/*Trob: plugin->get is not longer working, didn't find an other
method, so fetching the pluginName from $validations
JForm::addFormPath(JPATH_SITE .
'/plugins/fabrik_validationrule/' .
$plugin->get('pluginName'));
$xmlFile = JPATH_SITE . '/plugins/fabrik_validationrule/' .
$plugin->get('pluginName') . '/forms/fields.xml';
*/
Form::addFormPath(JPATH_SITE .
'/plugins/fabrik_validationrule/' . $pluginName);
$xmlFile = JPATH_SITE . '/plugins/fabrik_validationrule/' .
$pluginName . '/forms/fields.xml';
$xml = $plugin->jform->loadFile($xmlFile, false);
foreach ($plugin_form->getFieldsets() as $fieldset)
{
foreach ($plugin_form->getFieldset($fieldset->name) as $field)
{
if (isset($params[$field->fieldname]))
{
if (is_array($params[$field->fieldname]))
{
for ($x = 0; $x < $num_validations; $x++)
{
if (!(array_key_exists($x, $params[$field->fieldname])))
{
$params[$field->fieldname][$x] = '';
}
}
ksort($params[$field->fieldname]);
}
}
}
}
}
$data['params'] = json_encode($params);
$row->params = $data['params'];
$cond = 'group_id = ' . (int) $row->group_id;
if ($new)
{
$data['ordering'] = $row->getNextOrder($cond);
}
$row->reorder($cond);
/**
* $$$ hugh - shouldn't updateChildIds() happen AFTER we save the
main row?
* Same place we do updateJavascript()?
*/
//$this->updateChildIds($row);
$elementModel->getElement()->bind($data);
$origName = $input->get('name_orig', '');
list($update, $q, $oldName, $newdesc, $origDesc) =
$listModel->shouldUpdateElement($elementModel, $origName);
if ($update && $input->get('task') !==
'save2copy')
{
$origPlugin = $input->get('plugin_orig');
$prefix = $this->config->get('dbprefix');
$tableName = $listModel->getTable()->db_table_name;
$hasPrefix = (strstr($tableName, $prefix) === false) ? false : true;
$tableName = str_replace($prefix, '#__', $tableName);
if (in_array($tableName, $this->core))
{
$this->app->enqueueMessage(Text::_('COM_FABRIK_WARNING_UPDATE_CORE_TABLE'),
'notice');
}
else
{
if ($hasPrefix)
{
$this->app->enqueueMessage(Text::_('COM_FABRIK_WARNING_UPDATE_TABLE_WITH_PREFIX'),
'notice');
}
}
$this->app->setUserState('com_fabrik.confirmUpdate', 1);
$this->app->setUserState('com_fabrik.plugin_orig',
$origPlugin);
$this->app->setUserState('com_fabrik.q', $q);
$this->app->setUserState('com_fabrik.newdesc',
$newdesc);
$this->app->setUserState('com_fabrik.origDesc',
$origDesc);
$this->app->setUserState('com_fabrik.origplugin',
$origPlugin);
$this->app->setUserState('com_fabrik.oldname',
$oldName);
$this->app->setUserState('com_fabrik.newname',
$data['name']);
$this->app->setUserState('com_fabrik.origtask',
$input->get('task'));
$this->app->setUserState('com_fabrik.plugin',
$data['plugin']);
$task = $input->get('task');
$url =
'index.php?option=com_fabrik&view=element&layout=confirmupdate&id='
. (int) $origId . '&origplugin=' . $origPlugin .
'&origtask='
. $task . '&plugin=' . $row->plugin;
$this->app->setUserState('com_fabrik.redirect', $url);
}
else
{
$this->app->setUserState('com_fabrik.confirmUpdate', 0);
}
if ((int) $listModel->getTable()->id !== 0)
{
$this->updateIndexes($elementModel, $listModel, $row);
}
$return = parent::save($data);
if ($return)
{
$this->updateJavascript($data);
$elementModel->setId($this->getState($this->getName() .
'.id'));
$row->id = $elementModel->getId();
$data['id'] = $row->id;
$this->createRepeatElement($elementModel, $row);
// If new, check if the element's db table is used by other tables
and if so add the element to each of those tables' groups
if ($new)
{
$this->addElementToOtherDbTables($elementModel, $row);
}
if (!$elementModel->onSave($data))
{
$this->setError(Text::_('COM_FABRIK_ERROR_SAVING_ELEMENT_PLUGIN_OPTIONS'));
return false;
}
$this->updateChildIds($row);
}
parent::cleanCache('com_fabrik');
return $return;
/**
* used for prefab
* return $elementModel;
*/
}
/**
* When saving an element, it may need to be added to other Fabrik lists
* If those lists point to the same database table.
*
* @param object $elementModel element
* @param object $row item
*
* @return void
*/
private function addElementToOtherDbTables($elementModel, $row)
{
$db = FabrikWorker::getDbo(true);
$list = $elementModel->getListModel()->getTable();
$origElid = $row->id;
$tmpgroupModel = $elementModel->getGroup();
$config = ComponentHelper::getParams('com_fabrik');
if ($tmpgroupModel->isJoin())
{
$dbName =
$tmpgroupModel->getJoinModel()->getJoin()->table_join;
}
else
{
$dbName = $list->db_table_name;
}
$query = $db->getQuery(true);
$query->select('DISTINCT(l.id) AS id, db_table_name, l.label,
l.form_id, l.label AS form_label, g.id AS group_id');
$query->from('#__fabrik_lists AS l');
$query->join('INNER', '#__fabrik_forms AS f ON
l.form_id = f.id');
$query->join('LEFT', '#__fabrik_formgroup AS fg ON f.id
= fg.form_id');
$query->join('LEFT', '#__fabrik_groups AS g ON
fg.group_id = g.id');
$query->where('db_table_name = ' . $db->q($dbName) .
' AND l.id != ' . (int) $list->id . ' AND is_join =
0');
$db->setQuery($query);
$otherTables = $db->loadObjectList('id');
/**
* $$$ rob 20/02/2012 if you have 2 lists, counters, regions and then you
join regions to countries to get a new group "countries -
[regions]"
* Then add elements to the regions list, the above query wont find the
group "countries - [regions]" to add the elements into
*/
$query->clear();
$query->select('DISTINCT(l.id) AS id, l.db_table_name, l.label,
l.form_id, l.label AS form_label, fg.group_id AS group_id')
->from('#__fabrik_joins AS j')->join('LEFT',
'#__fabrik_formgroup AS fg ON fg.group_id = j.group_id')
->join('LEFT', '#__fabrik_forms AS f ON fg.form_id =
f.id')->join('LEFT', '#__fabrik_lists AS l ON
l.form_id = f.id')
->where('j.table_join = ' . $db->quote($dbName) . '
AND j.list_id <> 0 AND j.element_id = 0 AND list_id <> ' .
(int) $list->id);
$db->setQuery($query);
$joinedLists = $db->loadObjectList('id');
$otherTables = array_merge($joinedLists, $otherTables);
if (!empty($otherTables))
{
/**
* $$$ hugh - we use $row after this, so we need to work on a copy,
otherwise
* (for instance) we redirect to the wrong copy of the element
*/
$rowCopy = clone ($row);
foreach ($otherTables as $listId => $t)
{
$rowCopy->id = 0;
$rowCopy->parent_id = $origElid;
$rowCopy->group_id = $t->group_id;
$rowCopy->name = str_replace('`', '',
$rowCopy->name);
if ($config->get('unpublish_clones', false))
{
$rowCopy->published = 0;
}
$rowCopy->store();
// Copy join records
$join = $this->getTable('join');
if ($join->load(array('element_id' => $origElid)))
{
$join->id = 0;
unset($join->id);
$join->element_id = $rowCopy->id;
$join->list_id = $listId;
$join->store();
}
}
}
}
/**
* Update child elements
*
* @param object &$row element
*
* @return mixed
*/
private function updateChildIds(&$row)
{
if ((int) $row->id === 0)
{
// New element so don't update child ids
return;
}
$ids = $this->getElementDescendents($row->id);
$ignore = array(
'_tbl',
'_tbl_key',
'_db',
'id',
'group_id',
'created',
'created_by',
'parent_id',
'ordering',
'published',
'checked_out_time',
'show_in_list_summary'
);
foreach ($ids as $id)
{
$plugin = $this->pluginManager->getElementPlugin($id);
$leave = $plugin->getFixedChildParameters();
$item = $plugin->getElement();
foreach ($row as $key => $val)
{
if (!in_array($key, $ignore))
{
if ($key == 'params')
{
$origParams = json_decode($item->params);
$newParams = json_decode($val);
foreach ($newParams as $pKey => $pVal)
{
if (!in_array($pKey, $leave))
{
$origParams->$pKey = $pVal;
}
}
$val = json_encode($origParams);
}
else
{
// $$$rob - i can't replicate bug #138 but this should fix
things anyway???
if ($key == 'name')
{
$val = str_replace("`", '', $val);
}
}
$item->$key = $val;
}
}
$item->store();
}
return true;
}
/**
* Update table indexes based on element settings
*
* @param object &$elementModel element model
* @param object &$listModel list model
* @param object &$row element item
*
* @return void
*/
private function updateIndexes(&$elementModel, &$listModel,
&$row)
{
if ($elementModel->getGroup()->isJoin())
{
return;
}
// Update table indexes
$fieldType = $elementModel->getFieldDescription();
// Int elements can't have a index size attribute
$size = StringHelper::stristr($fieldType, 'int') || $fieldType
== 'DATETIME' ? '' : '10';
if ($elementModel->getParams()->get('can_order'))
{
$listModel->addIndex($row->name, 'order',
'INDEX', $size);
}
else
{
$listModel->dropIndex($row->name, 'order',
'INDEX');
}
if ($row->filter_type != '')
{
$listModel->addIndex($row->name, 'filter',
'INDEX', $size);
}
else
{
$listModel->dropIndex($row->name, 'filter',
'INDEX');
}
}
/**
* Delete old javascript actions for the element
* & add new javascript actions
*
* @param array $data to save
*
* @return void
*/
protected function updateJavascript($data)
{
/**
* $$$ hugh - 2012/04/02
* updated to apply js changes to descendants as well. NOTE that this
means
* all descendants (i.e. children of children, etc.), not just direct
children.
*/
$input = $this->app->input;
$this_id = $this->getState($this->getName() . '.id');
$ids = $this->getElementDescendents($this_id);
$ids[] = $this_id;
$db = FabrikWorker::getDbo(true);
$query = $db->getQuery(true);
$query->delete('#__fabrik_jsactions')->where('element_id
IN (' . implode(',', $ids) . ')');
$db->setQuery($query);
$db->execute();
$jForm = $input->get('jform', array(),
'array');
$eEvent = FArrayHelper::getValue($jForm, 'js_e_event',
array());
$eTrigger = FArrayHelper::getValue($jForm, 'js_e_trigger',
array());
$eCond = FArrayHelper::getValue($jForm, 'js_e_condition',
array());
$eVal = FArrayHelper::getValue($jForm, 'js_e_value',
array());
$ePublished = FArrayHelper::getValue($jForm, 'js_published',
array());
$action = (array) FArrayHelper::getValue($jForm, 'action',
array());
foreach ($action as $c => $jsAction)
{
if ($jsAction === '')
{
continue;
}
$params = new stdClass;
$params->js_e_event = $eEvent[$c];
$params->js_e_trigger = $eTrigger[$c];
$params->js_e_condition = $eCond[$c];
$foo = str_replace('\\', '\\\\',
($eVal[$c]));
$params->js_e_value = htmlspecialchars($foo);
$params->js_published = $ePublished[$c];
$params = json_encode($params);
$code = $jForm['code'][$c];
$code = htmlspecialchars($code, ENT_QUOTES);
foreach ($ids as $id)
{
$query = $db->getQuery(true);
$query->insert('#__fabrik_jsactions');
$query->set('element_id = ' . (int) $id);
$query->set('action = ' . $db->quote($jsAction));
$query->set('code = ' . $db->quote($code));
$query->set('params = \'' . $params .
"'");
$db->setQuery($query);
$db->execute();
}
}
}
/**
* Take an array of group ids and return the corresponding element
* used in list publish code
*
* @param array $ids group ids
*
* @return array element ids
*/
public function swapGroupToElementIds($ids = array())
{
if (empty($ids))
{
return array();
}
$ids = ArrayHelper::toInteger($ids);
$db = FabrikWorker::getDbo(true);
$query = $db->getQuery(true);
$query->select('id')->from('#__fabrik_elements')->where('group_id
IN (' . implode(',', $ids) . ')');
return $db->setQuery($query)->loadColumn();
}
/**
* Potentially drop fields then remove element record
* Will also do the same for child elements
*
* @param array &$pks To delete
*
* @return boolean True if successful, false if an error occurs.
*/
public function delete(&$pks)
{
// Initialize variables
$elementIds = $this->app->input->get('elementIds',
array(), 'array');
foreach ($elementIds as $id)
{
if ((int) $id === 0)
{
continue;
}
$pluginModel = $this->pluginManager->getElementPlugin($id);
$pluginModel->onRemove();
$children = $pluginModel->getElementDescendents($id);
foreach ($children as $childId)
{
$childModel = $this->pluginManager->getElementPlugin($childId);
$childModel->onRemove();
}
// Enables the deletion of child elements
$pks = array_merge($pks, $children);
$element = $pluginModel->getElement();
if ($pluginModel->isRepeatElement())
{
$listModel = $pluginModel->getListModel();
$db = $listModel->getDb();
$tableName =
$db->qn($this->getRepeatElementTableName($pluginModel));
$db->setQuery('DROP TABLE ' . $tableName);
$db->execute();
}
$listModel = $pluginModel->getListModel();
$item = $listModel->getTable();
// $$$ hugh - might be a table-less form!
if (!empty($item->id))
{
$db = $listModel->getDb();
$db->setQuery('ALTER TABLE ' .
$db->qn($item->db_table_name) . ' DROP ' .
$db->qn($element->name));
$db->execute();
}
}
return parent::delete($pks);
}
/**
* Copy an element
*
* @return mixed true or warning
*/
public function copy()
{
$input = $this->app->input;
$cid = $input->get('cid', array(), 'array');
$cid = ArrayHelper::toInteger($cid);
$names = $input->get('name', array(), 'array');
$rule = $this->getTable('element');
foreach ($cid as $id => $groupid)
{
$rule->load((int) $id);
$name = FArrayHelper::getValue($names, $id, $rule->name);
$data = ArrayHelper::fromObject($rule);
$elementModel = $this->getElementPluginModel($data);
$elementModel->getElement()->bind($data);
$newRule = $elementModel->copyRow($id, $rule->label, $groupid,
$name);
if ($newRule === false)
{
return false;
}
$data = ArrayHelper::fromObject($newRule);
$elementModel = $this->getElementPluginModel($data);
$elementModel->getElement()->bind($data);
$listModel = $elementModel->getListModel();
$res = $listModel->shouldUpdateElement($elementModel);
$this->addElementToOtherDbTables($elementModel, $rule);
}
return true;
}
/**
* If repeated element we need to make a joined db table to store repeated
data in
*
* @param object $elementModel element model
* @param object $row element item
*
* @return void
*/
public function createRepeatElement($elementModel, $row)
{
if (!$elementModel->isJoin())
{
return;
}
$row->name = str_replace('`', '', $row->name);
$listModel = $elementModel->getListModel();
$groupModel = $elementModel->getGroupModel();
$tableName = $this->getRepeatElementTableName($elementModel, $row);
// Create db table!
$formModel = $elementModel->getForm();
$db = $listModel->getDb();
$desc = $elementModel->getFieldDescription();
$name = $db->qn($row->name);
$db
->setQuery(
'CREATE TABLE IF NOT EXISTS ' . $db->qn($tableName) .
' ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, parent_id INT(11),
'
. $name . ' ' . $desc . ', ' .
$db->qn('params') . ' TEXT );');
$db->execute();
// Remove previous join records if found
/*
if ((int) $row->id !== 0)
{
$jdb = FabrikWorker::getDbo(true);
$query = $jdb->getQuery(true);
$query->delete('#__fabrik_joins')->where('element_id
= ' . (int) $row->id);
$jdb->setQuery($query);
$jdb->execute();
}
*/
// Create or update fabrik join
if ($groupModel->isJoin())
{
$joinFromTable =
$groupModel->getJoinModel()->getJoin()->table_join;
}
else
{
$joinFromTable = $listModel->getTable()->db_table_name;
}
$data = array(
'list_id' => $listModel->getTable()->id,
'element_id' => $row->id,
'join_from_table' => $joinFromTable,
'table_join' => $tableName,
'table_key' => $row->name,
'table_join_key' => 'parent_id',
'join_type' => 'left'
);
$join = $this->getTable('join');
$join->load(array('element_id' =>
$data['element_id']));
$opts = new stdClass;
$opts->type = 'repeatElement';
$opts->pk = FabrikString::safeQuoteName($tableName .
'.id');
$data['params'] = json_encode($opts);
$join->bind($data);
$join->store();
// update the join for any children
$ids = $this->getElementDescendents($row->id);
foreach ($ids as $id)
{
$childElementModel = $this->pluginManager->getElementPlugin($id);
$data['list_id'] =
$childElementModel->getListModel()->getTable()->id;
$data['element_id'] = $id;
$join->load(array('element_id' =>
$data['element_id']));
$join->bind($data);
$join->store();
}
$fieldName = $tableName . '___parent_id';
$listModel->addIndex($fieldName, 'parent_fk',
'INDEX', '');
$fields = $listModel->getDBFields($tableName, 'Field');
$field = FArrayHelper::getValue($fields, $row->name, false);
switch ($field->BaseType)
{
case 'VARCHAR':
$size = (int) $field->BaseLength < 10 ? $field->BaseLength :
10;
break;
case 'INT':
case 'DATETIME':
default:
$size = '';
break;
}
$fieldName = $tableName . '___' . $row->name;
$listModel->addIndex($fieldName, 'repeat_el',
'INDEX', $size);
}
/**
* Get the name of the repeated elements table
*
* @param object $elementModel element model
* @param object $row element item
*
* @return string table name
*/
protected function getRepeatElementTableName($elementModel, $row = null)
{
$listModel = $elementModel->getListModel();
$groupModel = $elementModel->getGroupModel();
if (is_null($row))
{
$row = $elementModel->getElement();
}
if ($groupModel->isJoin())
{
$origTableName =
$groupModel->getJoinModel()->getJoin()->table_join;
}
else
{
$origTableName = $listModel->getTable()->db_table_name;
}
return $origTableName . '_repeat_' . str_replace('`',
'', $row->name);
}
/**
* Gets the element's parent element
*
* @return mixed 0 if no parent, object if exists.
*/
public function getParent()
{
$item = $this->getItem();
$item->parent_id = (int) $item->parent_id;
if ($item->parent_id === 0)
{
$parent = 0;
}
else
{
$db = FabrikWorker::getDbo(true);
$query = $db->getQuery(true);
$query->select('*')->from('#__fabrik_elements')->where('id
= ' . (int) $item->parent_id);
$db->setQuery($query);
$parent = $db->loadObject();
if (is_null($parent))
{
// Perhaps the parent element was deleted?
$parent = 0;
$item->parent_id = 0;
}
}
return $parent;
}
/**
* A protected method to get a set of ordering conditions.
*
* @param object $table A Table object.
*
* @return array An array of conditions to add to ordering queries.
*
* @since Fabrik 3.0b
*/
protected function getReorderConditions($table)
{
return array('group_id = ' . $table->group_id);
}
/**
* Recursively get all linked children of an element
*
* @param int $id element id
*
* @return array
*/
protected function getElementDescendents($id = 0)
{
if (empty($id))
{
$id = $this->getState($this->getName() . '.id');
}
$db = FabrikWorker::getDbo(true);
$query = $db->getQuery(true);
$query->select('id')->from('#__fabrik_elements')->where('parent_id
= ' . (int) $id);
$db->setQuery($query);
$kids = $db->loadObjectList();
$all_kids = array();
foreach ($kids as $kid)
{
$all_kids[] = $kid->id;
$all_kids = array_merge($this->getElementDescendents($kid->id),
$all_kids);
}
return $all_kids;
}
/**
* Loads in elements validation objects
* $$$ hugh - trying to fix issue on saving where we have to massage the
plugin
* params, which means knowing all the param names, but we can't call
the FE model
* version of this method 'cos ... well, it breaks.
*
* @param object $elementModel a front end element model
* @param array $usedPlugins an array of validation plugin names to
load
*
* @return array validation objects
*/
private function getValidations($elementModel, $usedPlugins = array())
{
if (isset($this->_aValidations))
{
return $this->_aValidations;
}
$pluginManager = FabrikWorker::getPluginManager();
$pluginManager->getPlugInGroup('validationrule');
$this->aValidations = array();
// $dispatcher = JEventDispatcher::getInstance();
$dispatcher = Factory::getApplication()->getDispatcher();
$ok =
PluginHelper::importPlugin('fabrik_validationrule');
foreach ($usedPlugins as $usedPlugin)
{
if ($usedPlugin !== '')
{
$class = 'plgFabrik_Validationrule' .
StringHelper::ucfirst($usedPlugin);
$conf = array();
$conf['name'] =
StringHelper::strtolower($usedPlugin);
$conf['type'] =
StringHelper::strtolower('fabrik_Validationrule');
$plugIn = new $class($dispatcher, $conf);
// $plugIn =
Factory::getApplication()->bootPlugin($conf['name'],
$conf['type']);
$oPlugin =
PluginHelper::getPlugin('fabrik_validationrule', $usedPlugin);
$plugIn->elementModel = $elementModel;
$this->aValidations[] = $plugIn;
}
}
return $this->aValidations;
}
}