382 lines
15 KiB
PHP
382 lines
15 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Class TTCrud
|
|
* @property string $headerTitle
|
|
* @property string $createText
|
|
* @property string|null $historyController
|
|
* @property array $columns
|
|
* @property array $additionalActions
|
|
* @property array $additionalJSVariables
|
|
* @property array $additionalHead
|
|
* @property array $infoMessages
|
|
* @property bool $onlyView
|
|
* @property array $defaultOrder
|
|
* @property array $autocompleteColumns
|
|
*/
|
|
class TTCrud extends mfBaseController {
|
|
public User $user;
|
|
private array $checkArray;
|
|
public ?array $postData;
|
|
/** @noinspection PhpMissingFieldTypeInspection */
|
|
public $model;
|
|
|
|
public function __construct($request) {
|
|
parent::__construct($request);
|
|
session_write_close();
|
|
}
|
|
|
|
protected function init() {
|
|
$className = get_class($this);
|
|
|
|
if (defined('TT_WAREHOUSE_LOGIN_OVERRIDE') && is_array(TT_WAREHOUSE_LOGIN_OVERRIDE)
|
|
&& in_array($className, TT_WAREHOUSE_LOGIN_OVERRIDE) && !mfLoginController::isLoggedIn())
|
|
$this->user = $this->loginOverride();
|
|
else {
|
|
$this->needlogin = true;
|
|
$this->user = new User();
|
|
$this->user->loadMe();
|
|
}
|
|
$this->layout()->set('me', $this->user);
|
|
|
|
$permissionAllowed = !empty($this->permissionCheck) && $this->user->can($this->permissionCheck);
|
|
|
|
if (method_exists($this, 'permissionsCheckOverride'))
|
|
$this->permissionsCheckOverride();
|
|
else if (mfLoginController::isLoggedIn() && !$permissionAllowed && !$this->user->is(["Admin"]))
|
|
$this->redirect("Dashboard");
|
|
|
|
$c = get_class($this);
|
|
foreach ([str_replace('Controller', 'Model', $c), str_replace('Controller', '', $c)] as $m)
|
|
if (class_exists($m)) {
|
|
$this->model = new $m();
|
|
break;
|
|
}
|
|
|
|
$this->postData = json_decode(file_get_contents('php://input'), true);
|
|
$this->checkArray = $this->getCheckArray();
|
|
$this->infoMessages = $this->getInfoMessages();
|
|
if (method_exists($this, 'afterInit')) $this->afterInit();
|
|
}
|
|
|
|
protected function loginOverride() {
|
|
$allowedIPs = ['193.105.204.200', '91.227.230.253', '91.227.230.251', '193.105.204.195', '172.18.0.1', '46.151.204.50'];
|
|
if (!in_array($_SERVER['REMOTE_ADDR'], $allowedIPs)) $this->redirect('Dashboard');
|
|
|
|
if (isset($_POST['wantedUserId']) && is_numeric($_POST['wantedUserId'])) {
|
|
$user = new User($_POST['wantedUserId']);
|
|
if ($user->id && $user->address_id == 1) {
|
|
$_SESSION[MFAPPNAME . '_warehouse_login_override'] = $user->id;
|
|
$_SESSION[MFAPPNAME . '_warehouse_login_override_timestamp'] = time();
|
|
$this->redirect('WarehouseShippingNote');
|
|
}
|
|
$this->redirect('Dashboard');
|
|
}
|
|
|
|
$sessionUserId = $_SESSION[MFAPPNAME . '_warehouse_login_override'] ?? null;
|
|
$sessionTimestamp = $_SESSION[MFAPPNAME . '_warehouse_login_override_timestamp'] ?? 0;
|
|
|
|
if (is_numeric($sessionUserId) && (time() - $sessionTimestamp <= 300)) {
|
|
$user = new User($sessionUserId);
|
|
if ($user->id && $user->address_id == 1) return $user;
|
|
$this->redirect('WarehouseShippingNote');
|
|
}
|
|
|
|
$users = UserModel::search(['employee' => true, 'active' => true]);
|
|
$userOptions = array_map(fn($user) => ['value' => (int)$user->id, 'text' => $user->name], $users);
|
|
|
|
$this->layout()->set('userOptions', $userOptions);
|
|
$this->layout()->setTemplate("VueViews/WarehouseLoginOverride");
|
|
echo $this->layout()->render();
|
|
exit;
|
|
}
|
|
/**
|
|
* Returns the checkArray for the CRUD component.
|
|
* @return array
|
|
*/
|
|
protected function getCheckArray(): array {
|
|
if (!$this->columns || count($this->columns) === 0) return [];
|
|
$checkArray = [];
|
|
|
|
foreach ($this->columns as $column) {
|
|
$checkArray[$column['key']] = ['required' => $column['required'] ?? false,
|
|
'required_length' => $column['required_length'] ?? 0,
|
|
'title' => $column['text'] ?? $column['key'],
|
|
'regex' => $column['regex'] ?? false];
|
|
}
|
|
|
|
return $checkArray;
|
|
}
|
|
|
|
|
|
|
|
protected function indexAction() {
|
|
$this->layout()->set('additionalJS', array_merge(['js/pages/WarehouseHistory/WarehouseHistoryModal.js'], $this->additionalJS ?? []));
|
|
$pageName = (defined('BASEDIR') && file_exists(BASEDIR . "/public/js/pages/{$this->mod}/{$this->mod}.js"))
|
|
? $this->mod
|
|
: "DefaultCrudView";
|
|
|
|
$JS_VARIABLES = [
|
|
"CRUD_CONFIG" => $this->getCrudConfig(),
|
|
"CREATE_URL" => $this::getUrl("{$this->mod}/create"),
|
|
"TABLE_URL" => $this::getUrl("{$this->mod}/get"),
|
|
"UPDATE_URL" => $this::getUrl("{$this->mod}/update"),
|
|
"GET_BY_ID_URL" => $this::getUrl("{$this->mod}/getById"),
|
|
"DELETE_URL" => $this::getUrl("{$this->mod}/delete"),
|
|
"USER_ID" => $this->user->id
|
|
];
|
|
|
|
if (!empty($this->additionalJSVariables) && is_array($this->additionalJSVariables)) $JS_VARIABLES = array_merge($JS_VARIABLES, $this->additionalJSVariables);
|
|
if (!empty($this->additionalHead) && is_array($this->additionalHead)) $this->layout()->set('additionalHead', $this->additionalHead);
|
|
|
|
Helper::renderVue($this, $pageName, $this->headerTitle, $JS_VARIABLES);
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the configuration for the CRUD component for the Vue component.
|
|
* @return array
|
|
*/
|
|
protected function getCrudConfig(): array {
|
|
|
|
|
|
$column = array_search('createBy', array_column($this->columns, 'key'));
|
|
if ($column !== false) {
|
|
$this->columns[$column]['modal']['items'] = array_map(function ($user) {
|
|
return ['value' => intval($user->id), 'text' => $user->name];
|
|
}, UserModel::search(['employee' => true]));
|
|
}
|
|
|
|
if (method_exists($this, 'prepareCrudConfig')) {
|
|
$this->prepareCrudConfig();
|
|
}
|
|
|
|
|
|
$columns = array_map(function ($column) {
|
|
if (isset($column['type']) && (!isset($column['modal']) || !isset($column['modal']['type']))) {
|
|
$column['modal']['type'] = $column['type'];
|
|
}
|
|
$newColumn = $column;
|
|
unset($newColumn['required'], $newColumn['required_length'], $newColumn['regex']);
|
|
return $newColumn;
|
|
}, $this->columns);
|
|
|
|
// check if in columns array there is a column with key "actions" and if so, we set the priority of the first column to 20 and actions to 19
|
|
$actionsColumn = array_filter($columns, function ($column) {
|
|
return $column['key'] === 'actions';
|
|
});
|
|
if (count($actionsColumn) > 0) {
|
|
$columns = array_map(function ($column) {
|
|
if ($column['key'] === 'actions') {
|
|
$column['priority'] = 119;
|
|
}
|
|
return $column;
|
|
}, $columns);
|
|
$columns[0]['priority'] = 120;
|
|
}
|
|
|
|
return ['key' => $this->mod,
|
|
'tableHeader' => $this->headerTitle,
|
|
'reopenOnCreate' => $this->reopenOnCreate ?? false,
|
|
'createText' => $this->createText,
|
|
'columns' => $columns,
|
|
'additionalActions' => $this->additionalActions];
|
|
}
|
|
|
|
protected function getAction() {
|
|
$filter = $this->postData['filters'] ?? [];
|
|
$order = $this->postData['order'] ?? ['key' => null, 'order' => 'ASC'];
|
|
$page = $this->postData['pagination']['page'] ?? 1;
|
|
$perPage = $this->postData['pagination']['per_page'] ?? 10;
|
|
|
|
if ($order['key'] === null && isset($this->defaultOrder)) {
|
|
$order = $this->defaultOrder;
|
|
}
|
|
|
|
$rows = $this->model::getAll($filter, $perPage, ($page - 1) * $perPage, $order);
|
|
$filteredAvailable = $this->model::count($filter);
|
|
$totalRows = $this->model::count();
|
|
|
|
// check if any column is a autocomplete to add the text to the row
|
|
$autoCompleteColumns = array_filter($this->columns, function ($column) {
|
|
return isset($column['type']) && isset($column['modal']) && isset($column['modal']['type']) && $column['type'] === 'autocomplete' && $column['modal']['type'] === 'autocomplete';
|
|
|
|
});
|
|
$autocompleteData = [];
|
|
foreach ($rows as $row) {
|
|
$row = (array) $row;
|
|
foreach ($autoCompleteColumns as $column) {
|
|
if (isset($autocompleteData[$column['key']][$row[$column['key']]])) {
|
|
continue;
|
|
}
|
|
|
|
if ($row[$column['key']] === null || $row[$column['key']] === '') {
|
|
continue;
|
|
}
|
|
|
|
// if function customAutoComplete"COLUMN_KEY" is defined, we call it instead of the default
|
|
$data = null;
|
|
if (method_exists($this, 'customAutoComplete' . ucfirst($column['key']))) {
|
|
$data = $this->{'customAutoComplete' . ucfirst($column['key'])}($row[$column['key']]);
|
|
} else {
|
|
|
|
$autoCompleteModelName = explode('/', $column['modal']['apiUrl'])[0] . 'Model';
|
|
$autoCompleteModel = new $autoCompleteModelName();
|
|
$data = $autoCompleteModel::get($row[$column['key']]);
|
|
|
|
// TODO: fix that keys can be anything
|
|
if (isset($data->name) && !isset($data->title)) {
|
|
$data->title = $data->name;
|
|
}
|
|
}
|
|
|
|
$autocompleteData[$column['key']][$row[$column['key']]] = $data;
|
|
}
|
|
}
|
|
|
|
if (method_exists($this, 'customRowsHandler')) {
|
|
$rows = $this->customRowsHandler($rows);
|
|
}
|
|
|
|
self::returnJson(["rows" => $rows,
|
|
"autoCompleteData" => $autocompleteData,
|
|
"pagination" => ["page" => $page,
|
|
"total_pages" => ceil($filteredAvailable / $perPage),
|
|
"per_page" => $perPage,
|
|
"filtered_available" => intval($filteredAvailable),
|
|
"total_rows" => intval($totalRows)]]);
|
|
}
|
|
|
|
protected function createAction() {
|
|
if (property_exists($this->model, 'createBy')) {
|
|
$this->postData['createBy'] = $this->user->id;
|
|
}
|
|
if (property_exists($this->model, 'create')) {
|
|
$this->postData['create'] = time();
|
|
}
|
|
|
|
if (method_exists($this, 'beforeCreate') && !$this->beforeCreate($this->postData)) {
|
|
self::returnJson(['success' => false, 'message' => 'Ein Fehler ist aufgetreten.']);
|
|
}
|
|
|
|
Helper::validateArray($this->postData, $this->checkArray);
|
|
|
|
$id = $this->model::create($this->postData);
|
|
|
|
if (method_exists($this, 'afterCreate')) {
|
|
$this->afterCreate(array_merge($this->postData, ['id' => $id]));
|
|
}
|
|
|
|
self::returnJson(['success' => true,
|
|
'message' => $this->infoMessages['create'],
|
|
'id' => $id]);
|
|
}
|
|
|
|
protected function updateAction() {
|
|
if (property_exists($this->model, 'create')) {
|
|
$this->postData['create'] = $this->model::get($this->postData['id'])->create;
|
|
}
|
|
if (property_exists($this->model, 'createBy')) {
|
|
$this->postData['createBy'] = $this->model::get($this->postData['id'])->createBy;
|
|
}
|
|
|
|
Helper::validateArray($this->postData, array_merge($this->checkArray, ['id' => ['required' => true]]));
|
|
|
|
if (method_exists($this, 'beforeUpdate') && !$this->beforeUpdate($this->postData)) {
|
|
self::returnJson(['success' => false, 'message' => 'Ein Fehler ist aufgetreten.']);
|
|
}
|
|
|
|
$affectedRows = $this->model::update($this->postData);
|
|
|
|
if (method_exists($this, 'afterUpdate')) {
|
|
$this->afterUpdate($this->postData);
|
|
}
|
|
|
|
self::returnJson(['success' => $affectedRows > 0,
|
|
'message' => $affectedRows > 0 ? $this->infoMessages['update'] : $this->infoMessages['noChanges']]);
|
|
}
|
|
|
|
protected function deleteAction() {
|
|
Helper::validateArray($this->postData, ['id' => ['required' => true]]);
|
|
|
|
if (method_exists($this, 'beforeDelete') && !$this->beforeDelete($this->postData)) {
|
|
self::returnJson(['success' => false, 'message' => 'Ein Fehler ist aufgetreten.']);
|
|
}
|
|
|
|
$affectedRows = $this->model::delete($this->postData['id']);
|
|
|
|
if (method_exists($this, 'afterDelete')) {
|
|
$this->afterDelete($this->postData);
|
|
}
|
|
|
|
self::returnJson(['success' => $affectedRows > 0,
|
|
'message' => $affectedRows > 0 ? $this->infoMessages['delete'] : $this->infoMessages['noChanges']]);
|
|
}
|
|
|
|
protected function autocompleteAction() {
|
|
$textKey = property_exists($this->model, 'name') ? 'name' : 'title';
|
|
if (strlen($this->request->searchedID) > 0) {
|
|
$filter = ['id' => $this->request->searchedID];
|
|
$data = $this->model::getAll($filter, 10);
|
|
} else {
|
|
if (isset($this->autocompleteColumns) && is_array($this->autocompleteColumns)) {
|
|
$filterKey = join('|', $this->autocompleteColumns);
|
|
} else {
|
|
$filterKey = $textKey;
|
|
}
|
|
|
|
$data = [];
|
|
if (count($data) < 11) {
|
|
// $this->request->q replace ? with
|
|
$data = $this->model::getAll([$textKey => $this->request->q . '%'], 10);
|
|
$lazyData = $this->model::getAll([$filterKey => $this->request->q], 10);
|
|
|
|
$data = array_merge($data, $lazyData);
|
|
$data = array_unique($data, SORT_REGULAR);
|
|
$data = array_slice($data, 0, 10);
|
|
}
|
|
}
|
|
|
|
self::returnJson(array_map(function ($item) use ($textKey) {
|
|
return ['value' => $item->id, 'text' => $item->$textKey];
|
|
}, $data));
|
|
}
|
|
|
|
protected function getAllAction() {
|
|
self::returnJson($this->model::getAll($this->postData['filters'] ?? []));
|
|
}
|
|
|
|
protected function getByIdAction() {
|
|
$id = $_GET['id'] ?? null;
|
|
if (!$id || !is_numeric($id)) {
|
|
http_response_code(500);
|
|
self::returnJson(['success' => false, 'message' => 'No ID provided.']);
|
|
die();
|
|
}
|
|
|
|
$data = (array) $this->model::get($id);
|
|
if (!empty($data) && method_exists($this, 'getByIdParse') && !isset($_GET['disableParse'])) $data = $this->getByIdParse($data);
|
|
self::returnJson($data);
|
|
}
|
|
|
|
private function getInfoMessages(): array {
|
|
if (isset($this->infoMessages) && is_array($this->infoMessages)) {
|
|
return $this->infoMessages;
|
|
}
|
|
|
|
if (isset($this->singleText) && is_string($this->singleText)) {
|
|
return ['create' => $this->singleText . ' wurde erstellt.',
|
|
'update' => $this->singleText . ' wurde aktualisiert',
|
|
'delete' => $this->singleText . ' wurde gelöscht',
|
|
'noChanges' => 'Keine Änderungen'];
|
|
}
|
|
|
|
return ['create' => 'Eintrag wurde erstellt.',
|
|
'update' => 'Eintrag wurde aktualisiert',
|
|
'delete' => 'Eintrag wurde gelöscht',
|
|
'noChanges' => 'Keine Änderungen'];
|
|
}
|
|
}
|
|
|
|
?>
|