289 lines
10 KiB
PHP
289 lines
10 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controllers\Admin;
|
|
|
|
use App\Services\ApiClient;
|
|
use CodeIgniter\HTTP\ResponseInterface;
|
|
|
|
/**
|
|
* CRUD pegawai lewat API `/api/admin/pegawai/*` (tanpa query DB di controller).
|
|
*/
|
|
class Pegawai extends BaseAdminController
|
|
{
|
|
public function index(): ResponseInterface|string
|
|
{
|
|
if (($deny = $this->enforceAccess('pegawai')) !== null) {
|
|
return $deny;
|
|
}
|
|
|
|
$page = max(1, (int) ($this->request->getGet('page') ?? 1));
|
|
$q = (string) ($this->request->getGet('q') ?? '');
|
|
$errors = [];
|
|
$payload = null;
|
|
|
|
$r = $this->apiAdminGet('pegawai', [
|
|
'page' => (string) $page,
|
|
'per_page' => '20',
|
|
'q' => $q,
|
|
]);
|
|
|
|
if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) {
|
|
$payload = $r['json']['data'] ?? null;
|
|
} else {
|
|
$errors[] = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal memuat daftar pegawai') : 'Gagal memuat daftar pegawai');
|
|
}
|
|
|
|
return view('admin/pegawai/index', [
|
|
'payload' => $payload,
|
|
'errors' => $errors,
|
|
'q' => $q,
|
|
'page' => $page,
|
|
]);
|
|
}
|
|
|
|
public function create(): ResponseInterface|string
|
|
{
|
|
if (($deny = $this->enforceAccess('pegawai_tambah')) !== null) {
|
|
return $deny;
|
|
}
|
|
|
|
$refs = $this->loadReferences();
|
|
|
|
return view('admin/pegawai/form', [
|
|
'mode' => 'create',
|
|
'row' => null,
|
|
'refs' => $refs['data'],
|
|
'errors' => $refs['errors'],
|
|
'apiError' => null,
|
|
]);
|
|
}
|
|
|
|
public function store(): ResponseInterface
|
|
{
|
|
if (($deny = $this->enforceAccess('pegawai_tambah')) !== null) {
|
|
return $deny;
|
|
}
|
|
|
|
$post = $this->sanitizePegawaiPost($this->request->getPost() ?? []);
|
|
if (($err = $this->mergePegawaiPhotoIntoPost($post, null)) !== null) {
|
|
return redirect()->back()->withInput()->with('error', $err);
|
|
}
|
|
|
|
$res = $this->apiAdminPost('pegawai/create', $post);
|
|
|
|
if ($res['transport_ok'] && ApiClient::isSuccess($res['json'])) {
|
|
return redirect()->to(site_url('admin/pegawai'))->with('message', (string) ($res['json']['pesan'] ?? 'Data berhasil disimpan'));
|
|
}
|
|
|
|
$msg = is_array($res['json']) ? (string) ($res['json']['pesan'] ?? 'Gagal menyimpan') : ($res['error'] ?? 'Gagal menyimpan');
|
|
|
|
return redirect()->back()->withInput()->with('error', $msg);
|
|
}
|
|
|
|
public function edit(int $id): ResponseInterface|string
|
|
{
|
|
if (($deny = $this->enforceAccess('pegawai')) !== null) {
|
|
return $deny;
|
|
}
|
|
|
|
$refs = $this->loadReferences();
|
|
$row = null;
|
|
$err = $refs['errors'];
|
|
|
|
$r = $this->apiAdminGet('pegawai/' . $id);
|
|
if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) {
|
|
$row = $r['json']['data'] ?? null;
|
|
} else {
|
|
$err[] = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal memuat pegawai') : 'Gagal memuat pegawai');
|
|
}
|
|
|
|
return view('admin/pegawai/form', [
|
|
'mode' => 'edit',
|
|
'row' => is_array($row) ? $row : null,
|
|
'refs' => $refs['data'],
|
|
'errors' => $err,
|
|
'apiError' => null,
|
|
]);
|
|
}
|
|
|
|
public function update(int $id): ResponseInterface
|
|
{
|
|
if (($deny = $this->enforceAccess('pegawai')) !== null) {
|
|
return $deny;
|
|
}
|
|
|
|
$post = $this->sanitizePegawaiPost($this->request->getPost() ?? []);
|
|
$post['id_pegawai'] = $id;
|
|
$photoExisting = (string) ($this->request->getPost('photo_existing') ?? '');
|
|
if (($err = $this->mergePegawaiPhotoIntoPost($post, $photoExisting)) !== null) {
|
|
return redirect()->back()->withInput()->with('error', $err);
|
|
}
|
|
|
|
$res = $this->apiAdminPost('pegawai/update', $post);
|
|
|
|
if ($res['transport_ok'] && ApiClient::isSuccess($res['json'])) {
|
|
return redirect()->to(site_url('admin/pegawai'))->with('message', (string) ($res['json']['pesan'] ?? 'Data berhasil diperbarui'));
|
|
}
|
|
|
|
$msg = is_array($res['json']) ? (string) ($res['json']['pesan'] ?? 'Gagal memperbarui') : ($res['error'] ?? 'Gagal memperbarui');
|
|
|
|
return redirect()->back()->withInput()->with('error', $msg);
|
|
}
|
|
|
|
public function delete(int $id): ResponseInterface
|
|
{
|
|
if (($deny = $this->enforceAccess('pegawai')) !== null) {
|
|
return $deny;
|
|
}
|
|
|
|
$res = $this->apiAdminPost('pegawai/delete', ['id_pegawai' => (string) $id]);
|
|
|
|
if ($res['transport_ok'] && ApiClient::isSuccess($res['json'])) {
|
|
return redirect()->to(site_url('admin/pegawai'))->with('message', (string) ($res['json']['pesan'] ?? 'Terhapus'));
|
|
}
|
|
|
|
$msg = is_array($res['json']) ? (string) ($res['json']['pesan'] ?? 'Gagal menghapus') : ($res['error'] ?? 'Gagal menghapus');
|
|
|
|
return redirect()->back()->with('error', $msg);
|
|
}
|
|
|
|
public function reset(int $id): ResponseInterface
|
|
{
|
|
if (($deny = $this->enforceAccess('pegawai')) !== null) {
|
|
return $deny;
|
|
}
|
|
|
|
$res = $this->apiAdminPost('pegawai/reset_password', ['id_pegawai' => (string) $id]);
|
|
|
|
if ($res['transport_ok'] && ApiClient::isSuccess($res['json'])) {
|
|
return redirect()->to(site_url('admin/pegawai'))->with('message', (string) ($res['json']['pesan'] ?? 'Password direset'));
|
|
}
|
|
|
|
$msg = is_array($res['json']) ? (string) ($res['json']['pesan'] ?? 'Gagal reset') : ($res['error'] ?? 'Gagal reset');
|
|
|
|
return redirect()->back()->with('error', $msg);
|
|
}
|
|
|
|
/**
|
|
* @return array{data: array<string, mixed>|null, errors: list<string>}
|
|
*/
|
|
private function loadReferences(): array
|
|
{
|
|
$errors = [];
|
|
$data = null;
|
|
$r = $this->apiAdminGet('references');
|
|
if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) {
|
|
$data = is_array($r['json']['data'] ?? null) ? $r['json']['data'] : null;
|
|
} else {
|
|
$errors[] = $r['error'] ?? 'Referensi jabatan/unit tidak dapat dimuat.';
|
|
}
|
|
|
|
return ['data' => $data, 'errors' => $errors];
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $post
|
|
*
|
|
* @return array<string, scalar|null>
|
|
*/
|
|
private function sanitizePegawaiPost(array $post): array
|
|
{
|
|
$out = [];
|
|
foreach ($post as $k => $v) {
|
|
if (! is_scalar($v) && $v !== null) {
|
|
continue;
|
|
}
|
|
$key = (string) $k;
|
|
if (in_array($key, ['nip', 'nama_lengkap', 'jenis_kelamin', 'tempat_lahir', 'tanggal_lahir', 'email', 'jabatan', 'unit_kerja', 'golongan_pekerjaan', 'kantor', 'status_kepegawaian', 'tanggal_bergabung', 'jadwal', 'super_akses', 'username', 'password', 'photo'], true)) {
|
|
$out[$key] = $v;
|
|
}
|
|
}
|
|
|
|
foreach (['jabatan', 'unit_kerja', 'golongan_pekerjaan', 'kantor', 'jadwal'] as $intKey) {
|
|
if (isset($out[$intKey]) && $out[$intKey] !== '' && $out[$intKey] !== null) {
|
|
$out[$intKey] = (int) $out[$intKey];
|
|
}
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Sama dengan aplikasi mobile: `public/assets/uploads/pengguna/`.
|
|
*/
|
|
private function pegawaiPhotoUploadDir(): string
|
|
{
|
|
$base = FCPATH . 'assets' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'pengguna';
|
|
if (! is_dir($base)) {
|
|
mkdir($base, 0755, true);
|
|
}
|
|
|
|
return $base;
|
|
}
|
|
|
|
/**
|
|
* Unggah file ke folder pengguna atau pakai nama file manual. Mengisi `$post['photo']`.
|
|
*
|
|
* @param array<string, scalar|null> $post
|
|
*
|
|
* @return string|null pesan error, atau null jika OK
|
|
*/
|
|
private function mergePegawaiPhotoIntoPost(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->pegawaiPhotoUploadDir();
|
|
$rawName = pathinfo($file->getClientName(), PATHINFO_FILENAME);
|
|
$safeOriginal = preg_replace('/[^A-Za-z0-9._-]+/', '_', (string) $rawName) ?: 'photo';
|
|
$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 = $photoExistingFromDb !== null ? 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;
|
|
}
|
|
}
|