Spade
Mini Shell
| Directory:~$ /proc/self/root/home/lmsyaran/www/joomla5/plugins/fabrik_list/update_col/ |
| [Home] [System Details] [Kill Me] |
<?php
/**
* Add an action button to the list to update selected columns to a given
value
*
* @package Joomla.Plugin
* @subpackage Fabrik.list.updatecol
* @copyright Copyright (C) 2005-2020 Media A-Team, Inc. - All rights
reserved.
* @license GNU/GPL http://www.gnu.org/copyleft/gpl.html
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Language\Text;
use Joomla\CMS\Factory;
use Joomla\CMS\Mail\MailHelper;
use Fabrik\Helpers\Pdf;
use Fabrik\Helpers\Worker;
use Joomla\Utilities\ArrayHelper;
use Joomla\CMS\Date\Date;
use Fabrik\Helpers\Php;
// Require the abstract plugin class
require_once COM_FABRIK_FRONTEND . '/models/plugin-list.php';
/**
* Add an action button to the list to update selected columns to a given
value
*
* @package Joomla.Plugin
* @subpackage Fabrik.list.updatecol
* @since 3.0
*/
class PlgFabrik_ListUpdate_col extends PlgFabrik_List
{
/**
* Button prefix
*
* @var string
*/
protected $buttonPrefix = 'update_col';
/**
* Number of send email notifications
*
* @var int
*/
protected $sent = 0;
/**
* Number of NOT send email notifications
*
* @var int
*/
protected $notsent = 0;
/**
* Number rows updated
*
* @var int
*/
protected $row_count = 0;
/**
* Update message
*
* @var string
*/
protected $msg = null;
/**
* Element containing email notification addresses
*
* @var PlgFabrik_Element
*/
protected $emailElement = null;
/**
* Prep the button if needed
*
* @param array &$args Arguments
*
* @return bool;
*/
public function button(&$args)
{
parent::button($args);
return true;
}
/**
* Get the button label
*
* @return string
*/
protected function buttonLabel()
{
return Text::_($this->getParams()->get('button_label',
parent::buttonLabel()));
}
/**
* Get the parameter name that defines the plugins acl access
*
* @return string
*/
protected function getAclParam()
{
return 'updatecol_access';
}
/**
* Can the plug-in select list rows
*
* @return bool
*/
public function canSelectRows()
{
$access = $this->getParams()->get('updatecol_access');
$name = $this->_getButtonName();
return in_array($access, $this->user->getAuthorisedViewLevels());
}
/**
* Get the values to update the list with.
* Can be either/or preset values from plugin params, or user selected
from popup form.
* If both are specified, values from user selects override those from
plug-in parameters,
* so the plugin parameter pre-sets basically become defaults.
*
* @param JParameters $params Plugin parameters
*
* @since 3.0.7
*
* @return object|false
*/
protected function getUpdateCols($params)
{
$model = $this->getModel();
// get the pre-set updates
$update = json_decode($params->get('update_col_updates'));
if (is_null($update) ) $update = new stdClass();
$prompt = $params->get('update_col_prompt', false);
// if we allow user selected updates ...
if ($prompt)
{
$formModel = $model->getFormModel();
$value = $this->app->input->get('fabrik_update_col',
'', 'string');
$elementModel = $formModel->getElement($prompt, true);
$elementName = $elementModel->getFullName(false, false);
// Was this element already pre-set? Use array_search() rather than
in_array() as we'll need the index if it exists.
if (isset($update) && isset($update->coltoupdate) &&
is_array($update->coltoupdate))
{
$index = array_search($elementName, $update->coltoupdate);
}
else
{
$index = false;
}
if ($index === false)
{
// nope, wasn't preset, so just add it to the updates
$update->coltoupdate[] = $elementName;
$update->update_value[] = $value;
$update->update_eval[] = '0';
}
else
{
// yes it was preset, so use the $index to modify the existing value
$update->update_value[$index] = $value;
$update->update_eval[$index] = '0';
}
}
else if ($params->get('update_user_select', 0))
{
// get the values from the form inputs
$formModel = $model->getFormModel();
$qs = $this->app->input->get('fabrik_update_col',
'', 'string');
parse_str($qs, $output);
$key = 'list_' . $model->getRenderContext();
$values = FArrayHelper::getValue($output, 'fabrik___filter',
array());
$values = FArrayHelper::getValue($values, $key, array());
for ($i = 0; $i < count($values['elementid']); $i ++)
{
$id = $values['elementid'][$i];
// meh, nasty hack to handle autocomplete values, which currently
aren't working in this plugin
if (array_key_exists('auto-complete' . $id, $output))
{
$values['value'][$i] = $output['auto-complete' .
$id];
}
$elementModel = $formModel->getElement($id, true);
$elementName = $elementModel->getFullName(false, false);
// Was this element already pre-set? Use array_search() rather than
in_array() as we'll need the index if it exists.
if (isset($update) && isset($update->coltoupdate) &&
is_array($update->coltoupdate))
{
$index = array_search($elementName, $update->coltoupdate);
}
else
{
$index = false;
}
if ($index === false)
{
// nope, wasn't preset, so just add it to the updates
$update->coltoupdate[] = $elementName;
$update->update_value[] = $values['value'][$i];
$update->update_eval[] = '0';
}
else
{
// yes it was preset, so use the $index to modify the existing value
$update->update_value[$index] = $values['value'][$i];
$update->update_eval[$index] = '0';
}
}
}
// If no update input found return false to stop processing
if (empty($update->coltoupdate) &&
empty($update->update_value))
{
return false;
}
return $update;
}
/**
* Do the plug-in action
*
* @param array $opts Custom options
*
* @return bool
*/
public function process($opts = array())
{
$params = $this->getParams();
$model = $this->getModel();
$input = $this->app->input;
$update = $this->getUpdateCols($params);
$preEval = $params->get('update_pre_eval', '');
$postEval = $params->get('update_post_eval', '');
if (!$update && empty($postEval) && empty($preEval))
{
return false;
}
// $$$ rob moved here from bottom of func see
http://fabrikar.com/forums/showthread.php?t=15920&page=7
$dateCol = $params->get('update_date_element');
$userCol = $params->get('update_user_element');
$item = $model->getTable();
// Array_unique for left joined table data
$ids = array_unique($input->get('ids', array(),
'array'));
$ids = ArrayHelper::toInteger($ids);
$this->row_count = count($ids);
$ids = implode(',', $ids);
$model->reset();
$model->setPluginQueryWhere('update_col',
$item->db_primary_key . ' IN ( ' . $ids . ')');
$model->setLimits(0, 0);
$data = $model->getData();
// Needed to re-assign as getDate() messes the plugin params order
$this->params = $params;
if (!empty($preEval))
{
FabrikWorker::clearEval();
$res = Php::Eval(['code' => $preEval,
'vars'=>['data'=>$data, 'ids'=>$ids,
'update'=>$update],
'thisVars'=>['msg'=>&$this->msg]]);
Worker::logEval($res, 'Caught exception on eval in
updatecol::process() : %s');
if ($res === false)
{
return false;
}
}
if (!empty($dateCol))
{
$formModel = $model->getFormModel();
$dateEl = $formModel->getElement($dateCol);
$local = (bool)
$dateEl->getParams()->get('date_store_as_local', false);
if ($local)
{
$tz = new
\DateTimeZone($this->config->get('offset'));
$this->date->setTimezone($tz);
}
$this->_process($model, $dateCol, $this->date->toSql($local),
false);
}
if (!empty($userCol))
{
$this->_process($model, $userCol, (int)
$this->user->get('id'), false);
}
if ($params->get('update_email_after_update', '1')
== '0')
{
$this->sendEmails($ids);
}
if (!empty($update))
{
foreach ($update->coltoupdate as $i => $col)
{
//update-col (user select) uses element's list view filter
settings for input, which creates issues; fetch at least the
"Range" filter
$update->update_value[$i] = is_array($update->update_value[$i]) ?
$update->update_value[$i][0] : $update->update_value[$i];
$this->_process($model, $col, $update->update_value[$i],
$update->update_eval[$i]);
}
}
if ($params->get('update_email_after_update', '1')
== '1')
{
$this->sendEmails($ids);
}
if (empty($this->msg))
{
$this->msg = $params->get('update_message',
'');
}
if (empty($this->msg))
{
$this->msg =
Text::sprintf('PLG_LIST_UPDATE_COL_UPDATE_MESSAGE',
$this->row_count, $this->sent);
}
else
{
$this->msg = Text::sprintf($this->msg, $this->row_count,
$this->sent);
}
if (!empty($postEval))
{
FabrikWorker::clearEval();
$msg = Php::Eval(['code' => $postEval,
'vars'=>['data'=>$data,
'ids'=>$ids],
'thisVars'=>['msg'=>&$this->msg]]);
Worker::logEval($msg, 'Caught exception on eval in
updatecol::process() : %s');
if (!empty($msg))
{
$this->msg .= "\n" . $msg;
}
}
// Clean the cache.
$cache = Factory::getCache($input->get('option'));
$cache->clean();
return true;
}
/**
* Send notification emails
*
* @param string $ids csv list of row ids.
*
* @return void
*/
protected function sendEmails($ids)
{
$params = $this->getParams();
$model = $this->getModel();
// Ensure that yesno exports text and not bootstrap icon.
$model->setOutputFormat('csv');
$emailColID = $params->get('update_email_element',
'');
$emailTo = $params->get('update_email_to', '');
if (!empty($emailColID) || !empty($emailTo))
{
$w = new Worker;
$aids = explode(',', $ids);
$message = $params->get('update_email_msg');
$subject = $params->get('update_email_subject');
$eval = $params->get('eval', 0);
$from = $this->config->get('mailfrom');
$fromName = $this->config->get('fromname');
$emailWhich = $this->emailWhich();
foreach ($aids as $id)
{
$row = $model->getRow($id, true);
/**
* hugh - hack to work around this issue:
* https://github.com/Fabrik/fabrik/issues/1499
*/
$this->params = $params;
$to = trim($this->emailTo($row, $emailWhich));
$tos = explode(',', $to);
$cleanTo = true;
foreach ($tos as &$email)
{
$email = trim($email);
if (!(MailHelper::cleanAddress($email) &&
Worker::isEmail($email)))
{
$cleanTo = false;
}
}
if ($cleanTo)
{
if (count($tos) > 1)
{
$to = $tos;
}
$thisSubject = $w->parseMessageForPlaceholder($subject, $row);
$thisMessage = $w->parseMessageForPlaceholder($message, $row);
if ($eval)
{
FabrikWorker::clearEval();
$thisMessage = Php::Eval(['code' => $thisMessage,
'vars'=>['row'=>$row]]);
Worker::logEval($thisMessage, 'Caught exception on eval in
updatecol::process() : %s');
}
Pdf::fullPaths($thisMessage);
$res = Worker::sendMail(
$from,
$fromName,
$to,
$thisSubject,
$thisMessage,
true
);
if ($res)
{
$this->sent++;
}
else
{
$this->notsent++;
}
}
else
{
$this->notsent++;
}
}
}
}
/**
* Get the email selection mode
*
* @return string
*/
private function emailWhich()
{
$params = $this->getParams();
$emailColID = $params->get('update_email_element',
'');
if (!empty($emailColID))
{
$elementModel = $this->getEmailElement();
$emailElement = $elementModel->getElement(true);
$emailWhich = $emailElement->plugin == 'user' ?
'user' : 'field';
}
else
{
$emailWhich = 'to';
}
return $emailWhich;
}
/**
* Get list of user emails.
*
* @param string $ids CSV list of ids
*
* @return array
*/
private function getEmailUserIds($ids)
{
$elementModel = $this->getEmailElement();
$model = $this->getModel();
$item = $model->getTable();
$emailColumn = $elementModel->getFullName(false, false);
$tbl = array_shift(explode('.', $emailColumn));
$db = $this->_db;
$userIdsEmails = array();
$query = $db->getQuery(true);
$query->select('#__users.id AS id, #__users.email AS email')
->from('#__users')->join('LEFT', $tbl . '
ON #__users.id = ' . $emailColumn)
->where($item->db_primary_key . ' IN (' . $ids .
')');
$db->setQuery($query);
$results = $db->loadObjectList();
foreach ($results as $result)
{
$userIdsEmails[(int) $result->id] = $result->email;
}
return $userIdsEmails;
}
/**
* Get Email Element
*
* @return PlgFabrik_Element
*/
private function getEmailElement()
{
if (isset($this->emailElement))
{
return $this->emailElement;
}
$params = $this->getParams();
$emailColID = $params->get('update_email_element',
'');
return Worker::getPluginManager()->getElementPlugin($emailColID);
}
/**
* Get email address to send update notification to
*
* @param object $row Current record row
* @param string $emailWhich Mode for getting the user's email
*
* @return string Email address
*/
private function emailTo($row, $emailWhich)
{
$input = $this->app->input;
$params = $this->getParams();
$elementModel = $this->getEmailElement();
$emailField = $elementModel->getFullName(true, false);
if ($emailWhich == 'user')
{
$emailFieldRaw = $emailField . '_raw';
$userId = (int) $row->$emailFieldRaw;
$ids = array_unique($input->get('ids', array(),
'array'));
$ids = ArrayHelper::toInteger($ids);
$ids = implode(',', $ids);
$userIdsEmails = $this->getEmailUserIds($ids);
$to = FArrayHelper::getValue($userIdsEmails, $userId);
}
elseif ($emailWhich == 'field')
{
$to = $row->$emailField;
}
else
{
$to = $params->get('update_email_to', '');
if ($params->get('update_email_to_eval',
'0') === '1')
{
FabrikWorker::clearEval();
$to = Php::Eval(['code' => $to,
'vars'=>['row'=>$row]]);
Worker::logEval($to, 'Caught exception on eval in
updatecol::emailTo() : %s');
}
}
return $to;
}
/**
* Get the message generated in process()
*
* @param int $c Plugin render order
*
* @return string
*/
public function process_result($c)
{
return $this->msg;
}
/**
* Process the update column
*
* @param object &$model List model
* @param string $col Update column
* @param string $val Update val
*
* @return void
*/
private function _process(&$model, $col, $val, $eval = false)
{
$ids = $this->app->input->get('ids', array(),
'array');
if ($eval)
{
FabrikWorker::clearEval();
$val = Php::Eval(['code' => $val,
'vars'=>['model'=>$model]]);
Worker::logEval($val, 'Caught exception on eval in
updatecol::_process() : %s');
}
$model->updateRows($ids, $col, $val);
}
/**
* Return the javascript to create an instance of the class defined in
formJavascriptClass
*
* @param array $args Array [0] => string table's form id to
contain plugin
*
* @return bool
*/
public function onLoadJavascriptInstance($args)
{
parent::onLoadJavascriptInstance($args);
$params = $this->getParams();
$opts = $this->getElementJSOptions();
$opts->prompt = $params->get('update_col_prompt', false)
!== false;
$opts->promptMsg =
$params->get('update_user_select_message', '');
$opts->userSelect = (bool)
$params->get('update_user_select', 0);
$opts->form = $this->userSelectForm();
$opts->renderOrder = $this->renderOrder;
$opts = json_encode($opts);
$this->jsInstance = "new FbListUpdate_col($opts)";
return true;
}
/**
* Build the form which allows the user to select which elements to update
*
* @return string HTML Form
*/
protected function userSelectForm()
{
$params = $this->getParams();
$selectElements =
json_decode($params->get('update_user_select_elements',
"{}"));
/** @var FabrikFEModelList $model */
$model = $this->getModel();
Text::script('PLG_LIST_UPDATE_COL_UPDATE');
$options[] = '<option value="">' .
Text::_('COM_FABRIK_PLEASE_SELECT') .
'</option>';
$elementModels = $model->getElements(0, false, true);
foreach ($elementModels as $elementModel)
{
$element = $elementModel->getElement();
/**
* Added "User updateable elements" selection, so admin can
specify which elements
* can be chosen by the user.
*/
if (is_object($selectElements) &&
isset($selectElements->update_user_select_elements_list) &&
!in_array($element->id,
$selectElements->update_user_select_elements_list))
{
continue;
}
if ($elementModel->canUse($this, 'list') &&
$element->plugin !== 'internalid')
{
$elName = $elementModel->getFilterFullName();
$options[] = '<option value="' . $elName .
'" data-id="' . $element->id . '"
data-plugin="' . $element->plugin . '">'
. Text::_(strip_tags($element->label)) .
'</option>';
}
}
$listRef = $model->getRenderContext();
$prefix = 'fabrik___update_col[list_' . $listRef .
'][';
$elements = '<select class="form-select-sm key
update_col_elements" size="1" name="' . $prefix .
'key][]">' . implode("\n", $options) .
'</select>';
$addImg = 'plus';
$removeImg = 'remove';
$layout = $this->getLayout('form');
$layoutData = new stdClass;
$layoutData->listRef = $listRef;
$layoutData->renderOrder = $this->renderOrder;
$layoutData->addImg = FabrikHelperHTML::image($addImg,
'list', $model->getTmpl());
$layoutData->delImg = FabrikHelperHTML::image($removeImg,
'list', $model->getTmpl());
$layoutData->elements = $elements;
$layoutData->user_select_message =
$params->get('update_user_select_message', '');
return $layout->render($layoutData);
}
/**
* Get the name of the column to update
*
* @return string
*/
protected function _getColName()
{
$params = $this->getParams();
$col = $params->get('coltoupdate');
return $col . '-' . $this->renderOrder;
}
/**
* Load the AMD module class name
*
* @return string
*/
public function loadJavascriptClassName_result()
{
return 'FbListUpdateCol';
}
}