736 lines
22 KiB
PHP
736 lines
22 KiB
PHP
<?php
|
|
|
|
use Doctrine\DBAL\Types\Type;
|
|
use KupShop\AdminBundle\Admin\Actions\ActionsLocator;
|
|
use KupShop\AdminBundle\Event\WindowTabsEvent;
|
|
use KupShop\AdminBundle\Util\ActivityLog;
|
|
use KupShop\AdminBundle\Util\WindowTabLocator;
|
|
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
|
use KupShop\KupShopBundle\Util\Logging\SentryLogger;
|
|
use Query\Operator;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
|
|
class Window extends Frame
|
|
{
|
|
use DatabaseCommunication;
|
|
|
|
public const RIGHT_DELETE = 'delete';
|
|
public const RIGHT_DUPLICATE = 'duplicate';
|
|
public const RIGHT_SAVE = 'save';
|
|
|
|
protected $nameField = 'name';
|
|
|
|
protected $fields = [];
|
|
protected $defaults = [];
|
|
protected $required = [];
|
|
protected $types = [];
|
|
protected $uniques;
|
|
protected $tableName;
|
|
|
|
// Type of item to display on web
|
|
protected $show_on_web;
|
|
|
|
protected $action;
|
|
protected $ID;
|
|
protected $type;
|
|
|
|
protected $tabs;
|
|
protected $custom_data;
|
|
|
|
protected $processedData;
|
|
|
|
public function getTemplate()
|
|
{
|
|
if (empty($this->template)) {
|
|
$name = lcfirst($this->getClassName());
|
|
|
|
return "window/{$name}.tpl";
|
|
}
|
|
|
|
return $this->template;
|
|
}
|
|
|
|
public function createSQLFields($tablename)
|
|
{
|
|
$defaults = [];
|
|
$required = [];
|
|
$fields = [];
|
|
$types = [];
|
|
|
|
$conn = $this->getDbalConnection();
|
|
$tm = $conn->getSchemaManager();
|
|
|
|
$columns = $tm->listTableColumns($tablename);
|
|
foreach ($columns as $column) {
|
|
$name = $column->getName();
|
|
$fields[] = $name;
|
|
$defaults[$name] = $column->getDefault();
|
|
$required[$name] = ($column->getNotNull() && is_null($defaults[$name]));
|
|
$types[$name] = $column->getType()->getName();
|
|
}
|
|
|
|
$this->defaults = array_merge($defaults, $this->defaults);
|
|
$this->required = array_merge($required, $this->required);
|
|
$this->fields = array_merge($fields, $this->fields);
|
|
$this->types = array_merge($types, $this->types);
|
|
}
|
|
|
|
protected function collectVariables()
|
|
{
|
|
$acn = $this->getAction();
|
|
|
|
if ($acn == 'erased') {
|
|
return self::get_vars();
|
|
}
|
|
|
|
return $this->get_vars();
|
|
}
|
|
|
|
public function get_vars()
|
|
{
|
|
$vars = parent::get_vars();
|
|
|
|
$acn = $this->getAction();
|
|
|
|
$pageVars = [
|
|
'acn' => $acn,
|
|
];
|
|
|
|
$ID = $this->getID();
|
|
|
|
if (($acn == 'edit' && !empty($ID)) || $acn == 'add') {
|
|
if ($acn == 'edit' || ($acn == 'add' && $this->isDuplicate() && !empty($ID))) {
|
|
$pageVars['data'] = $this->getObject();
|
|
|
|
if (getVal('Submit')) {
|
|
$data = $this->getProcessedData();
|
|
$pageVars['data'] = array_merge($pageVars['data'], $data);
|
|
}
|
|
|
|
if (!empty($this->isDuplicate())) {
|
|
$this->getFields();
|
|
$this->duplicateObject($pageVars['data']);
|
|
$pageVars['duplicate'] = true;
|
|
}
|
|
} elseif ($acn == 'add') {
|
|
$pageVars['data'] = $this->createObject();
|
|
}
|
|
}
|
|
|
|
$vars['type'] = $this->getType();
|
|
|
|
$flap = getVal('flap', null, 1);
|
|
$vars['header']['flap'] = empty($flap) ? 1 : $flap;
|
|
$vars['header']['flap_next'] = getVal('flap_next');
|
|
$vars['header']['force_resize'] = getVal('force_resize');
|
|
|
|
$vars['tabs'] = $this->getTabs();
|
|
|
|
$vars['body'] = $pageVars;
|
|
|
|
$vars['actionsLocator'] = ServiceContainer::getService(ActionsLocator::class);
|
|
|
|
return $vars;
|
|
}
|
|
|
|
protected function getType()
|
|
{
|
|
if (empty($this->type)) {
|
|
$type = getVal('s');
|
|
if (!$type) {
|
|
$type = lcfirst($this->getClassName());
|
|
} else {
|
|
$type = substr($type, 0, -4);
|
|
}
|
|
$this->type = $type;
|
|
}
|
|
|
|
return $this->type;
|
|
}
|
|
|
|
public function setType($type)
|
|
{
|
|
$this->type = $type;
|
|
}
|
|
|
|
public function translateType()
|
|
{
|
|
// try to translate type to czech/english
|
|
$type = $this->getType();
|
|
|
|
// preferred:
|
|
// e.g. $txt_str['deliveryPriceLists']['navigation'] = 'Ceníky dopravy'
|
|
if ($typeName = translate('navigation', $type, true)) {
|
|
return $typeName;
|
|
}
|
|
|
|
// e.g. $txt_str['navigation']['deliveryDelivery'] = 'Dopravy'
|
|
if ($typeName = translate($type, 'navigation', true)) {
|
|
return $typeName;
|
|
}
|
|
|
|
return $type;
|
|
}
|
|
|
|
protected function getFields()
|
|
{
|
|
if (empty($this->fields)) {
|
|
$this->createSQLFields($this->getTableName());
|
|
}
|
|
}
|
|
|
|
protected function getUniques($table = null)
|
|
{
|
|
if (!is_null($this->uniques)) {
|
|
return $this->uniques;
|
|
}
|
|
|
|
if (empty($table)) {
|
|
$table = $this->getTableName();
|
|
}
|
|
|
|
$conn = $this->getDbalConnection();
|
|
$tm = $conn->getSchemaManager();
|
|
|
|
$indexes = $tm->listTableIndexes($table);
|
|
|
|
$this->uniques = [$this->nameField => true];
|
|
foreach ($indexes as $index) {
|
|
if ($index->isUnique() == true && $index->getName() != 'PRIMARY') {
|
|
if (isset($index->getColumns()[1])) {
|
|
$this->uniques[$index->getColumns()[1]] = true;
|
|
} else {
|
|
$this->uniques[$index->getName()] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->uniques;
|
|
}
|
|
|
|
public function getData()
|
|
{
|
|
$data = getVal('data', null, []);
|
|
|
|
if (!empty($data)) {
|
|
$data['ID'] = getVal('ID');
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/** Process all POSTed data from form. Transform data to SQL fields array */
|
|
public function processFormData()
|
|
{
|
|
return $this->getData();
|
|
}
|
|
|
|
final public function getProcessedData()
|
|
{
|
|
if (isset($this->processedData)) {
|
|
return $this->processedData;
|
|
}
|
|
|
|
return $this->processedData = $this->processFormData();
|
|
}
|
|
|
|
public function setCustomData($data)
|
|
{
|
|
$this->updateSQL($this->getTableName(), [
|
|
'data' => empty($data) ? null : json_encode($data),
|
|
], ['id' => $this->getID()]);
|
|
|
|
// reset custom data cache
|
|
$this->custom_data = null;
|
|
}
|
|
|
|
public function getCustomData()
|
|
{
|
|
if (empty($this->custom_data)) {
|
|
$object = $this->getObject();
|
|
$this->unserializeCustomData($object);
|
|
$this->custom_data = $object['data'];
|
|
}
|
|
|
|
return $this->custom_data;
|
|
}
|
|
|
|
public function getTableName()
|
|
{
|
|
if (empty($this->tableName)) {
|
|
$this->tableName = strtolower($this->getClassName());
|
|
}
|
|
|
|
return $this->tableName;
|
|
}
|
|
|
|
private function duplicateObject(&$data)
|
|
{
|
|
$uniques = $this->getUniques();
|
|
foreach ($uniques as $key => $value) {
|
|
if (isset($data[$key])) {
|
|
if ($this->required[$key] == false) {
|
|
$data[$key] = null;
|
|
} else {
|
|
$data[$key] = stringCopy(trim($data[$key]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function createObject()
|
|
{
|
|
$data = $this->getData();
|
|
|
|
return array_merge($this->defaults, $data);
|
|
}
|
|
|
|
protected function getObject()
|
|
{
|
|
$object = $this->fetchObject($this->getTableName(), $this->getID());
|
|
if (!$object && $this->getAction() !== 'add') {
|
|
$errStr = sprintf(translate('errorNotFound', 'base'), $this->translateType(), $this->getID());
|
|
throw new NotFoundHttpException($errStr);
|
|
}
|
|
|
|
return $object;
|
|
}
|
|
|
|
public function getObjectData()
|
|
{
|
|
return $this->getObject();
|
|
}
|
|
|
|
// Vypisovani aktivit
|
|
protected function activityMessage($name, array $additionalData = [])
|
|
{
|
|
$acn = $this->getAction();
|
|
if ($acn == 'add') {
|
|
addActivityLog(ActivityLog::SEVERITY_NOTICE, ActivityLog::TYPE_CHANGE, sprintf(translate('activityAdded'), $name),
|
|
[
|
|
...ActivityLog::addObjectData([$this->getID() => $name], $this->getType()),
|
|
...$additionalData,
|
|
]);
|
|
} elseif ($acn == 'edit') {
|
|
addActivityLog(ActivityLog::SEVERITY_NOTICE, ActivityLog::TYPE_CHANGE, sprintf(translate('activityEdited'), $name),
|
|
[
|
|
...ActivityLog::addObjectData([$this->getID() => $name], $this->getType()),
|
|
...$additionalData,
|
|
]);
|
|
}
|
|
}
|
|
|
|
protected function getAdditionalActivityData(): array
|
|
{
|
|
return [];
|
|
}
|
|
|
|
public function handle()
|
|
{
|
|
try {
|
|
$acn = $this->getAction();
|
|
$ID = $this->getID();
|
|
|
|
if ($acn == 'add') {
|
|
$this->tryRights('ADD');
|
|
}
|
|
if ($acn == 'edit') {
|
|
$this->tryRights('EDIT');
|
|
}
|
|
|
|
if ((($acn == 'edit' && (strlen($ID) > 0)) || $acn == 'add') && getVal('Submit')) {
|
|
$data = $this->getProcessedData();
|
|
$missing = $this->checkRequired($data);
|
|
if (!$missing) {
|
|
$activityAdditionalData = $this->getAdditionalActivityData();
|
|
$SQL = $this->handleUpdate();
|
|
if ($SQL) {
|
|
if ((empty($this->getErrors()) && empty($this->getHTMLErrors())) || $acn == 'add') {
|
|
if (isset($data[$this->nameField])) {
|
|
$this->activityMessage($data[$this->nameField], $activityAdditionalData);
|
|
}
|
|
$this->returnOK();
|
|
}
|
|
} else {
|
|
$ErrStr = getTextString('status', 'scripterror');
|
|
$this->returnError($ErrStr);
|
|
}
|
|
} else {
|
|
$ErrStr = getTextString('base', 'errorNotAllValid');
|
|
$ErrStr .= join(',', $missing);
|
|
$this->addError($ErrStr);
|
|
}
|
|
} elseif ($acn == 'erase' && !empty($ID)) {
|
|
$this->tryRights('ERASE');
|
|
$this->handleDelete();
|
|
} else {
|
|
$this->handleTabs();
|
|
parent::handle();
|
|
}
|
|
} catch (Doctrine\DBAL\DBALException $e) {
|
|
$this->handleException($e);
|
|
}
|
|
}
|
|
|
|
public function handleException($e)
|
|
{
|
|
if (intval($e->getPrevious()->errorInfo[1]) === 1062) {
|
|
$ErrStr = 'Duplicitní ';
|
|
$badFields = $this->getBadValues($this->getTableName(), ['id' => $this->ID]);
|
|
foreach ($badFields as $value) {
|
|
$ErrStr .= '{'.$value.'} ';
|
|
}
|
|
|
|
if (!$badFields) {
|
|
$ErrStr = "Duplicitní záznam: \n".$e->getMessage();
|
|
}
|
|
|
|
$this->addError($ErrStr);
|
|
} elseif (intval($e->getPrevious()->getCode()) === 45000) {
|
|
$msg = $e->getPrevious()->getMessage();
|
|
$this->addError(mb_substr($msg, mb_strpos($msg, 'EAN')));
|
|
} elseif (in_array(intval($e->getPrevious()->getErrorCode()), [1205, 1213])) {
|
|
$this->addError('Chyba při zpracování požadavku. Zkuste to prosím znovu.');
|
|
$sentryLogger = ServiceContainer::getService(SentryLogger::class);
|
|
$data = json_encode($this->getAllSQLProcesses());
|
|
$sentryLogger->captureException(new Exception('Deadlock v administraci!', 1205, $e), ['extra' => ['processes' => $data]]);
|
|
} else {
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
// Kontroluje, jestli v datech z formulare jsou vsechny povinne polozky
|
|
public function checkRequired($data)
|
|
{
|
|
$this->getFields();
|
|
$required = [];
|
|
foreach ($data as $key => $value) {
|
|
if (!is_array($value)) {
|
|
$value = trim($value);
|
|
}
|
|
if (isset($this->required[$key])
|
|
&& $this->required[$key] == true
|
|
&& $value === ''
|
|
&& ((@$this->types[$key] != 'string' && @$this->types[$key] != 'simple_array' && @$this->types[$key] != 'text') || $key == $this->nameField)
|
|
) {
|
|
$required[] = $key;
|
|
}
|
|
}
|
|
|
|
return $required;
|
|
}
|
|
|
|
// Obecna funkce pro update & insert
|
|
public function handleUpdate()
|
|
{
|
|
$acn = $this->getAction();
|
|
$SQL = null;
|
|
|
|
if ($acn == 'add') {
|
|
$sqlFields = $this->getSQLFields();
|
|
$this->insertSQL($this->getTableName(), $sqlFields);
|
|
$SQL = true;
|
|
if (empty($ID)) {
|
|
if (isset($sqlFields['id'])) {
|
|
$this->setID($sqlFields['id']);
|
|
} else {
|
|
$this->setID(sqlInsertID());
|
|
}
|
|
}
|
|
} elseif ($acn == 'edit') {
|
|
$sqlFields = $this->getSQLFields();
|
|
$this->updateSQL($this->getTableName(), $sqlFields, ['id' => $this->getID()]);
|
|
|
|
if (isset($sqlFields['id'])) {
|
|
$this->setID($sqlFields['id']);
|
|
}
|
|
|
|
$SQL = true;
|
|
}
|
|
|
|
// reset custom data cache
|
|
$this->custom_data = null;
|
|
|
|
$this->handleTabs(true);
|
|
|
|
return $SQL;
|
|
}
|
|
|
|
public function forceUpdate()
|
|
{
|
|
try {
|
|
// get actual action
|
|
$action = $this->getAction();
|
|
|
|
// change action to edit
|
|
$this->action = 'edit';
|
|
// do update
|
|
$_REQUEST['Submit'] = 'OK';
|
|
$this->createSQLFields($this->getTableName());
|
|
$result = $this->handleUpdate();
|
|
// return action
|
|
$this->action = $action;
|
|
|
|
return $result;
|
|
} catch (Doctrine\DBAL\DBALException $e) {
|
|
$this->handleException($e);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function getIdFromDatabase($field)
|
|
{
|
|
$id = returnSQLResult('SELECT id FROM '.getTableName($this->getTableName())." WHERE {$field[0]}='{$field[1]}' ");
|
|
|
|
return $id;
|
|
}
|
|
|
|
public function getSQLFields($data = null, $fields = null, $defaults = null, $types = null)
|
|
{
|
|
if ($data == null) {
|
|
$data = $this->getProcessedData();
|
|
}
|
|
|
|
if ($fields == null) {
|
|
$fields = $this->fields;
|
|
}
|
|
|
|
if ($defaults == null) {
|
|
$defaults = $this->defaults;
|
|
}
|
|
|
|
if ($types == null) {
|
|
$types = $this->types;
|
|
}
|
|
|
|
$sqlField = [];
|
|
foreach ($fields as $row) {
|
|
if (array_key_exists($row, $data) && !is_array($data[$row])) {
|
|
if (!is_null($data[$row])) {
|
|
$data[$row] = trim($data[$row]);
|
|
}
|
|
|
|
if (array_key_exists($row, $types)) {
|
|
$type = $types[$row];
|
|
if (($type == Type::DECIMAL) || ($type == Type::FLOAT)) {
|
|
$this->preparePrice($data[$row]);
|
|
}
|
|
}
|
|
|
|
if (isset($data[$row]) && ($data[$row] === '') && (@$defaults[$row] === null) && @!$this->required[$row]) {
|
|
$sqlField[$row] = null;
|
|
} else {
|
|
$sqlField[$row] = $data[$row];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $sqlField;
|
|
}
|
|
|
|
// Smazani polozky
|
|
public function handleDelete()
|
|
{
|
|
if ($this->nameField) {
|
|
$name = sqlQueryBuilder()->select($this->nameField)->from($this->getTableName())
|
|
->andWhere(Operator::equals(['id' => $this->getID()]))
|
|
->execute()->fetchOne();
|
|
if ($logMessage = translate('activityDeleted', $this->getType(), true)) {
|
|
$logMessage = sprintf($logMessage, $name);
|
|
} else {
|
|
$logMessage = translate('activityDeleted', 'status'); // 'Deleted %s: %s'
|
|
$logMessage = sprintf($logMessage, $this->getType(), $name);
|
|
}
|
|
}
|
|
|
|
try {
|
|
$res = sqlQueryBuilder()->delete($this->getTableName())
|
|
->andWhere(Operator::equals(['id' => $this->getID()]))
|
|
->execute();
|
|
if ($res && !empty($logMessage)) {
|
|
addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_CHANGE, $logMessage);
|
|
}
|
|
} catch (Doctrine\DBAL\DBALException $e) {
|
|
switch (intval($e->getPrevious()->errorInfo[1])) {
|
|
case 1451:
|
|
$ErrStr = 'Tento objekt je použit a nelze ho smazat.';
|
|
$this->returnError($ErrStr);
|
|
break;
|
|
|
|
default:
|
|
$this->handleException($e);
|
|
}
|
|
}
|
|
|
|
throw new \KupShop\KupShopBundle\Exception\RedirectException("launch.php?s={$this->getName()}.php&acn=erased");
|
|
}
|
|
|
|
public function hasRights($name = null)
|
|
{
|
|
switch ($name) {
|
|
case self::RIGHT_DUPLICATE:
|
|
if ($this->getAction() == 'edit' && $this->getID() != null) {
|
|
return true;
|
|
}
|
|
break;
|
|
case self::RIGHT_SAVE:
|
|
// Kdyz mam READ a nemam EDIT, tak nezobrazim save button
|
|
if (UserRights::hasRights($this->getRightsType(), 'READ') && !UserRights::hasRights($this->getRightsType(), 'EDIT')) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
default:
|
|
return true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function getBadValues($table = null, $rowIdentifier = [])
|
|
{
|
|
if (!empty($table)) {
|
|
$uniques = $this->getUniques($table);
|
|
} else {
|
|
$table = $this->getTableName();
|
|
$uniques = [];
|
|
}
|
|
|
|
$where = '';
|
|
foreach ($rowIdentifier as $key => $value) {
|
|
$where .= " AND {$key}!=:{$key}";
|
|
}
|
|
|
|
$data = $this->getData();
|
|
$badFields = [];
|
|
foreach ($uniques as $key => $value) {
|
|
if ($value) {
|
|
if (isset($data[$key])) {
|
|
$SQL = returnSQLResult('SELECT COUNT(*) FROM '.getTableName($table)." WHERE {$key}=:{$key} {$where}",
|
|
array_merge($data, $rowIdentifier));
|
|
if ($SQL > 0) {
|
|
$badFields[] = $key;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $badFields;
|
|
}
|
|
|
|
public function redirect($params = [])
|
|
{
|
|
parent::redirect(array_merge(['ID' => $this->getID(), 'acn' => 'edit'], $params));
|
|
}
|
|
|
|
public function getShowOnWeb()
|
|
{
|
|
if ($this->show_on_web == null) {
|
|
return false;
|
|
}
|
|
|
|
if ($this->getID() === null) {
|
|
return null;
|
|
}
|
|
|
|
return ['type' => $this->show_on_web, 'id' => $this->getID()];
|
|
}
|
|
|
|
public function getNameField()
|
|
{
|
|
return $this->nameField;
|
|
}
|
|
|
|
public function handleTabs($update = false)
|
|
{
|
|
$tabs = $this->getTabs();
|
|
foreach ($tabs as $tab) {
|
|
$tab->setID($this->getID());
|
|
|
|
if ($update) {
|
|
$tab->handleUpdate();
|
|
// reset custom data cache
|
|
$this->custom_data = null;
|
|
} else {
|
|
$tab->handle();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return WindowTabs.
|
|
*/
|
|
protected function getTabs()
|
|
{
|
|
if (!is_null($this->tabs)) {
|
|
return $this->tabs;
|
|
}
|
|
|
|
$windowTabLocator = ServiceContainer::getService(WindowTabLocator::class, 0);
|
|
|
|
$dispatcher = ServiceContainer::getService('event_dispatcher');
|
|
$tabsEvent = new WindowTabsEvent();
|
|
$dispatcher->dispatch($tabsEvent, WindowTabsEvent::NAME_PREFIX.$this->getType());
|
|
|
|
$tabs = array_merge(
|
|
$windowTabLocator ? $windowTabLocator->getTabs($this->getType()) : [],
|
|
$tabsEvent->getTabs()
|
|
);
|
|
|
|
foreach ($tabs as &$tab) {
|
|
$tab->setWindow($this);
|
|
}
|
|
|
|
return $this->tabs = $tabs;
|
|
}
|
|
|
|
public function handleGetActionSnippet()
|
|
{
|
|
$actionName = getVal('action');
|
|
/** @var $massActionsLocator ActionsLocator */
|
|
$actionsLocator = ServiceContainer::getService(ActionsLocator::class);
|
|
$action = $actionsLocator->getServiceByActionClassName($actionName);
|
|
$smarty = createSmarty(true, true);
|
|
$smarty->assign($action->getVars());
|
|
$smarty->display($action->getTemplate());
|
|
exit;
|
|
}
|
|
|
|
public function handleExecuteAction()
|
|
{
|
|
$actionName = getVal('action');
|
|
/** @var $massActionsLocator ActionsLocator */
|
|
$actionsLocator = ServiceContainer::getService(ActionsLocator::class);
|
|
$action = $actionsLocator->getServiceByActionClassName($actionName);
|
|
$action->setWindow($this);
|
|
$data = $this->getData();
|
|
$result = $action->execute($data, getVal('config', $_POST, []), $this->getType());
|
|
if ($result->isSuccessful()) {
|
|
if ($result->getHTMLMessage()) {
|
|
$this->action = 'edit';
|
|
$this->addHTMLError($result->getHTMLMessage());
|
|
|
|
return;
|
|
}
|
|
|
|
$params = ['action' => null];
|
|
if ($result->getRedirect()) {
|
|
$params = array_merge($params, $result->getRedirect());
|
|
}
|
|
$this->returnOK(!empty($result->getMsg()) ? $result->getMsg() : ('Akce ['.$action->getName().'] byla provedena.'),
|
|
false,
|
|
$params);
|
|
} else {
|
|
$this->redirect(['acn' => 'edit',
|
|
'action' => null,
|
|
'ErrStr' => !empty($result->getMsg()) ? $result->getMsg() : ('Akce ['.$action->getName().'] se nezdařila.')]);
|
|
}
|
|
}
|
|
|
|
protected function getAllSQLProcesses()
|
|
{
|
|
return sqlQuery('SHOW FULL PROCESSLIST')->fetchAllAssociative();
|
|
}
|
|
}
|