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']; } } ?>