enforceAccess('perusahaan')) !== null) { return $deny; } return $this->loadExtra('company/kantor', 'admin/perusahaan/kantor'); } public function kantorSave(): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->postExtra('company/kantor/save', 'admin/perusahaan/kantor'); } public function kantorDelete(int $id): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->postExtra('company/kantor/delete/' . $id, 'admin/perusahaan/kantor', []); } public function unitKerja(): ResponseInterface|string { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->loadExtra('company/unit_kerja', 'admin/perusahaan/unit_kerja'); } public function unitKerjaSave(): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->postExtra('company/unit_kerja/save', 'admin/perusahaan/unit_kerja'); } public function unitKerjaDelete(int $id): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->postExtra('company/unit_kerja/delete/' . $id, 'admin/perusahaan/unit_kerja', []); } public function golongan(): ResponseInterface|string { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->loadExtra('company/golongan', 'admin/perusahaan/golongan'); } public function golonganSave(): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->postExtra('company/golongan/save', 'admin/perusahaan/golongan'); } public function golonganDelete(int $id): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->postExtra('company/golongan/delete/' . $id, 'admin/perusahaan/golongan', []); } public function jabatan(): ResponseInterface|string { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->loadExtra('company/jabatan', 'admin/perusahaan/jabatan'); } public function jabatanSave(): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->postExtra('company/jabatan/save', 'admin/perusahaan/jabatan'); } public function jabatanDelete(int $id): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->postExtra('company/jabatan/delete/' . $id, 'admin/perusahaan/jabatan', []); } public function berita(): ResponseInterface|string { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->loadExtra('company/berita', 'admin/perusahaan/berita'); } public function beritaSave(): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } $post = $this->request->getPost() ?? []; $existing = (string) ($this->request->getPost('photo_existing') ?? ''); if (($err = $this->mergeBeritaPhotoIntoPost($post, $existing)) !== null) { return redirect()->to(site_url('admin/perusahaan/berita'))->with('error', $err); } unset($post['photo_existing']); $r = $this->apiAdminPost('company/berita/save', $post); if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) { return redirect()->to(site_url('admin/perusahaan/berita'))->with('message', (string) ($r['json']['pesan'] ?? 'OK')); } $msg = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal') : 'Gagal'); return redirect()->to(site_url('admin/perusahaan/berita'))->with('error', $msg); } public function beritaDelete(int $id): ResponseInterface { if (($deny = $this->enforceAccess('perusahaan')) !== null) { return $deny; } return $this->postExtra('company/berita/delete/' . $id, 'admin/perusahaan/berita', []); } private function loadExtra(string $apiPath, string $view): string { $errors = []; $data = null; $r = $this->apiAdminGet($apiPath); if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) { $data = $r['json']['data'] ?? null; } else { $errors[] = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal memuat data') : 'Gagal memuat data'); } return view($view, [ 'payload' => is_array($data) ? $data : null, 'errors' => $errors, ]); } private function postExtra(string $apiPath, string $redirectUri, ?array $mergePost = null): ResponseInterface { $post = array_merge($this->request->getPost(), $mergePost ?? []); $r = $this->apiAdminPost($apiPath, $post); if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) { return redirect()->to(site_url($redirectUri))->with('message', (string) ($r['json']['pesan'] ?? 'OK')); } $msg = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal') : 'Gagal'); return redirect()->to(site_url($redirectUri))->with('error', $msg); } /** * Selaras CI3: `assets/uploads/berita/`. */ private function beritaPhotoUploadDir(): string { $base = FCPATH . 'assets' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'berita'; if (! is_dir($base)) { mkdir($base, 0755, true); } return $base; } /** * Unggah ke folder berita atau nama file manual. Kolom DB kosong di API disimpan sebagai '-'. * * @param array $post * * @return string|null pesan error, atau null jika OK */ private function mergeBeritaPhotoIntoPost(array &$post, string $photoExistingFromDb): ?string { $file = $this->request->getFile('photo_file'); if ($file !== null && $file->getError() !== UPLOAD_ERR_NO_FILE) { if (! $file->isValid()) { return 'Unggah foto tidak valid.'; } $mime = (string) $file->getMimeType(); $allowedMime = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; if (! in_array($mime, $allowedMime, true)) { return 'Format foto harus JPG, PNG, GIF, atau WebP.'; } if ($file->getSize() > 2_097_152) { return 'Ukuran foto maksimal 2 MB.'; } $ext = strtolower((string) ($file->guessExtension() ?: $file->getClientExtension())); if (! in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'], true)) { return 'Ekstensi foto tidak didukung.'; } $dir = $this->beritaPhotoUploadDir(); $rawName = pathinfo($file->getClientName(), PATHINFO_FILENAME); $safeOriginal = preg_replace('/[^A-Za-z0-9._-]+/', '_', (string) $rawName) ?: 'berita'; $safeOriginal = substr($safeOriginal, 0, 80); $filename = uniqid((string) mt_rand(), true) . '-' . $safeOriginal . '.' . $ext; if (! $file->move($dir, $filename, true)) { return 'Gagal menyimpan file foto ke server.'; } $old = trim($photoExistingFromDb); if ($old !== '' && $old !== '-' && $old !== $filename) { $oldPath = $dir . DIRECTORY_SEPARATOR . basename(str_replace('\\', '/', $old)); if (is_file($oldPath)) { @unlink($oldPath); } } $post['photo'] = $filename; return null; } $manual = isset($post['photo']) ? trim((string) $post['photo']) : ''; if ($manual === '' || $manual === '-') { $post['photo'] = ''; return null; } $base = basename(str_replace('\\', '/', $manual)); if (! preg_match('/^[A-Za-z0-9._-]+$/', $base)) { return 'Nama file foto hanya boleh huruf, angka, titik, garis bawah, dan tanda hubung (atau unggah file).'; } $post['photo'] = substr($base, 0, 255); return null; } }