repository = $repository; $this->languagesRepository = $languagesRepository; } public function list(): string { $sortableColumns = ['id', 'o', 'name', 'type', 'status', 'values_count']; $filterDefinitions = [ [ 'key' => 'name', 'label' => 'Nazwa', 'type' => 'text', ], [ 'key' => 'status', 'label' => 'Aktywny', 'type' => 'select', 'options' => [ '' => '- aktywny -', '1' => 'tak', '0' => 'nie', ], ], ]; $listRequest = \admin\Support\TableListRequestFactory::fromRequest( $filterDefinitions, $sortableColumns, 'o' ); $sortDir = $listRequest['sortDir']; if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') { $sortDir = 'ASC'; } $result = $this->repository->listForAdmin( $listRequest['filters'], $listRequest['sortColumn'], $sortDir, $listRequest['page'], $listRequest['perPage'] ); $rows = []; $lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1; foreach ($result['items'] as $item) { $id = (int)($item['id'] ?? 0); $name = trim((string)($item['name'] ?? '')); $status = (int)($item['status'] ?? 0); $type = (int)($item['type'] ?? 0); $order = (int)($item['o'] ?? 0); $valuesCount = (int)($item['values_count'] ?? 0); $typeLabel = '-'; if ($type === 0) { $typeLabel = 'tekst'; } elseif ($type === 1) { $typeLabel = 'kolor'; } elseif ($type === 2) { $typeLabel = 'wzor'; } $rows[] = [ 'lp' => $lp++ . '.', 'o' => $order, 'name' => '' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '', 'type' => htmlspecialchars($typeLabel, ENT_QUOTES, 'UTF-8'), 'status' => $status === 1 ? 'tak' : 'nie', 'values' => 'edytuj wartosci', 'values_count' => $valuesCount, '_actions' => [ [ 'label' => 'Edytuj', 'url' => '/admin/shop_attribute/edit/id=' . $id, 'class' => 'btn btn-xs btn-primary', ], [ 'label' => 'Usun', 'url' => '/admin/shop_attribute/delete/id=' . $id, 'class' => 'btn btn-xs btn-danger', 'confirm' => 'Na pewno chcesz usunac wybrana ceche?', ], ], ]; } $total = (int)$result['total']; $totalPages = max(1, (int)ceil($total / $listRequest['perPage'])); $viewModel = new PaginatedTableViewModel( [ ['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false], ['key' => 'o', 'sort_key' => 'o', 'label' => 'Kolejnosc', 'class' => 'text-center', 'sortable' => true], ['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true], ['key' => 'type', 'sort_key' => 'type', 'label' => 'Typ', 'class' => 'text-center', 'sortable' => true], ['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true], ['key' => 'values_count', 'sort_key' => 'values_count', 'label' => 'Ilosc wartosci', 'class' => 'text-center', 'sortable' => true], ['key' => 'values', 'label' => 'Wartosci', 'class' => 'text-center', 'sortable' => false, 'raw' => true], ], $rows, $listRequest['viewFilters'], [ 'column' => $listRequest['sortColumn'], 'dir' => $sortDir, ], [ 'page' => $listRequest['page'], 'per_page' => $listRequest['perPage'], 'total' => $total, 'total_pages' => $totalPages, ], array_merge($listRequest['queryFilters'], [ 'sort' => $listRequest['sortColumn'], 'dir' => $sortDir, 'per_page' => $listRequest['perPage'], ]), $listRequest['perPageOptions'], $sortableColumns, '/admin/shop_attribute/list/', 'Brak danych w tabeli.', '/admin/shop_attribute/edit/', 'Dodaj ceche' ); return \Shared\Tpl\Tpl::view('shop-attribute/attributes-list', [ 'viewModel' => $viewModel, ]); } public function edit(): string { $attribute = $this->repository->findAttribute((int)\Shared\Helpers\Helpers::get('id')); $languages = $this->languagesRepository->languagesList(); return \Shared\Tpl\Tpl::view('shop-attribute/attribute-edit', [ 'form' => $this->buildFormViewModel($attribute, $languages), ]); } public function save(): void { $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania atrybutu wystapil blad. Prosze sprobowac ponownie.', ]; $legacyValues = \Shared\Helpers\Helpers::get('values'); if ($legacyValues) { $values = json_decode((string)$legacyValues, true); if (is_array($values)) { $id = $this->repository->saveAttribute($values); if (!empty($id)) { $response = [ 'status' => 'ok', 'msg' => 'Atrybut zostal zapisany.', 'id' => (int)$id, ]; } } echo json_encode($response); exit; } $payload = $_POST; if (empty($payload['id'])) { $routeId = (int)\Shared\Helpers\Helpers::get('id'); if ($routeId > 0) { $payload['id'] = $routeId; } } $id = $this->repository->saveAttribute($payload); if (!empty($id)) { echo json_encode([ 'success' => true, 'id' => (int)$id, 'message' => 'Atrybut zostal zapisany.', ]); exit; } echo json_encode([ 'success' => false, 'errors' => ['general' => 'Podczas zapisywania atrybutu wystapil blad.'], ]); exit; } public function delete(): void { if ($this->repository->deleteAttribute((int)\Shared\Helpers\Helpers::get('id'))) { \Shared\Helpers\Helpers::alert('Atrybut zostal usuniety.'); } header('Location: /admin/shop_attribute/list/'); exit; } public function values(): string { $attributeId = (int)\Shared\Helpers\Helpers::get('id'); if ($attributeId <= 0) { \Shared\Helpers\Helpers::alert('Nieprawidlowy identyfikator cechy.'); header('Location: /admin/shop_attribute/list/'); exit; } $attribute = $this->repository->findAttribute($attributeId); if ((int)($attribute['id'] ?? 0) <= 0) { \Shared\Helpers\Helpers::alert('Wybrana cecha nie zostala znaleziona.'); header('Location: /admin/shop_attribute/list/'); exit; } $languages = $this->languagesRepository->languagesList(); return \Shared\Tpl\Tpl::view('shop-attribute/values-edit', [ 'attribute' => $attribute, 'values' => $this->repository->findValues($attributeId), 'languages' => $languages, 'defaultLanguageId' => $this->languagesRepository->defaultLanguageId(), ]); } public function values_save(): void { $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania wartosci atrybutu wystapil blad. Prosze sprobowac ponownie.', ]; $attributeId = (int)\Shared\Helpers\Helpers::get('attribute_id'); if ($attributeId <= 0) { $attributeId = (int)\Shared\Helpers\Helpers::get('id'); } $payloadRaw = \Shared\Helpers\Helpers::get('payload'); $payload = json_decode((string)$payloadRaw, true); if (is_array($payload) && is_array($payload['rows'] ?? null) && $attributeId > 0) { $validationErrors = $this->validateValuesRows( $payload['rows'], $this->languagesRepository->defaultLanguageId() ); if (!empty($validationErrors)) { echo json_encode([ 'status' => 'error', 'msg' => $validationErrors[0], 'errors' => $validationErrors, ]); exit; } $saved = $this->repository->saveValues($attributeId, ['rows' => $payload['rows']]); if ($saved) { $response = [ 'status' => 'ok', 'msg' => 'Wartosci atrybutu zostaly zapisane.', 'id' => (int)$attributeId, ]; } echo json_encode($response); exit; } $valuesRaw = \Shared\Helpers\Helpers::get('values'); $values = json_decode((string)$valuesRaw, true); if (is_array($values) && $attributeId > 0) { $savedId = $this->repository->saveLegacyValues( $attributeId, is_array($values['name'] ?? null) ? $values['name'] : [], is_array($values['value'] ?? null) ? $values['value'] : [], is_array($values['ids'] ?? null) ? $values['ids'] : [], $values['default_value'] ?? '', is_array($values['impact_on_the_price'] ?? null) ? $values['impact_on_the_price'] : [] ); if (!empty($savedId)) { $response = [ 'status' => 'ok', 'msg' => 'Wartosci atrybutu zostaly zapisane.', 'id' => (int)$savedId, ]; } } echo json_encode($response); exit; } public function value_row_tpl(): void { $rowKey = trim((string)\Shared\Helpers\Helpers::get('row_key')); if ($rowKey === '') { $rowKey = 'new-' . time(); } $html = \Shared\Tpl\Tpl::view('shop-attribute/_partials/value-row', [ 'rowKey' => $rowKey, 'value' => ['id' => 0, 'is_default' => 0, 'impact_on_the_price' => null, 'languages' => []], 'languages' => $this->languagesRepository->languagesList(), 'defaultLanguageId' => $this->languagesRepository->defaultLanguageId(), ]); echo $html; exit; } /** * @param array> $rows * @return array */ private function validateValuesRows(array $rows, string $defaultLanguageId): array { $errors = []; if (empty($rows)) { return ['Dodaj co najmniej jedna wartosc cechy.']; } $defaultCount = 0; foreach ($rows as $index => $row) { $rowNumber = $index + 1; if (!is_array($row)) { $errors[] = 'Nieprawidlowe dane wiersza nr ' . $rowNumber . '.'; continue; } if (!empty($row['is_default'])) { ++$defaultCount; } $translations = is_array($row['translations'] ?? null) ? $row['translations'] : []; $defaultLangData = is_array($translations[$defaultLanguageId] ?? null) ? $translations[$defaultLanguageId] : []; $defaultName = trim((string)($defaultLangData['name'] ?? '')); if ($defaultName === '') { $errors[] = 'Wiersz nr ' . $rowNumber . ': nazwa w jezyku domyslnym jest wymagana.'; } $impact = trim((string)($row['impact_on_the_price'] ?? '')); if ($impact !== '' && !preg_match('/^-?[0-9]+([.,][0-9]{1,4})?$/', $impact)) { $errors[] = 'Wiersz nr ' . $rowNumber . ': nieprawidlowy format "wplyw na cene".'; } } if ($defaultCount !== 1) { $errors[] = 'Wybierz dokladnie jedna wartosc domyslna.'; } return $errors; } private function buildFormViewModel(array $attribute, array $languages): FormEditViewModel { $id = (int)($attribute['id'] ?? 0); $isNew = $id <= 0; $data = [ 'id' => $id, 'status' => (int)($attribute['status'] ?? 1), 'type' => (int)($attribute['type'] ?? 0), 'o' => (int)($attribute['o'] ?? 0), 'languages' => [], ]; if (is_array($attribute['languages'] ?? null)) { foreach ($attribute['languages'] as $langId => $translation) { $data['languages'][(string)$langId] = [ 'name' => (string)($translation['name'] ?? ''), ]; } } $fields = [ FormField::hidden('id', $id), FormField::langSection('attribute_content', 'content', [ FormField::text('name', [ 'label' => 'Tytul', ]), ]), FormField::switch('status', [ 'label' => 'Aktywny', 'tab' => 'settings', 'value' => true, ]), FormField::select('type', [ 'label' => 'Typ', 'tab' => 'settings', 'options' => [ 0 => 'tekst', 1 => 'kolor', 2 => 'wzor', ], ]), FormField::number('o', [ 'label' => 'Kolejnosc', 'tab' => 'settings', ]), ]; $tabs = [ new FormTab('content', 'Tresc', 'fa-file'), new FormTab('settings', 'Ustawienia', 'fa-wrench'), ]; $actionUrl = '/admin/shop_attribute/save/' . ($isNew ? '' : ('id=' . $id)); $actions = [ FormAction::save($actionUrl, '/admin/shop_attribute/list/'), FormAction::cancel('/admin/shop_attribute/list/'), ]; return new FormEditViewModel( 'shop-attribute-edit', $isNew ? 'Nowa cecha' : 'Edycja cechy', $data, $fields, $tabs, $actions, 'POST', $actionUrl, '/admin/shop_attribute/list/', true, ['id' => $id], $languages ); } }