krgm.so-manager-dev.com/app/Http/Controllers/Admin/OpeController.php
OU.ZAIKOU 13d2ecfceb
All checks were successful
Deploy main / deploy (push) Successful in 25s
【ログイン】二重認証実装
2026-01-21 22:37:38 +09:00

341 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Ope;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\StreamedResponse;
use App\Models\Feature;
use App\Models\Permission;
use App\Models\OpePermission;
class OpeController extends Controller
{
/**
* 一覧
*/
public function list(Request $request)
{
$inputs = [
'isMethodPost' => $request->isMethod('post'),
'sort' => $request->input('sort', 'ope_id'),
'sort_type' => $request->input('sort_type', 'asc'),
'isExport' => false,
];
// Blade 側は $list / $sort / $sort_type を参照
$list = Ope::search($inputs);
$sort = $inputs['sort'];
$sort_type = $inputs['sort_type'];
return view('admin.opes.list', compact('list', 'sort', 'sort_type'));
}
/**
* 新規登録GET 画面 / POST 保存)
*/
public function add(Request $request)
{
// ※機能(画面)一覧を取得(プルダウン用)
$features = Feature::query()
->orderBy('id')
->get(['id', 'name']);
// ※操作権限一覧を取得(チェックボックス用)
$permissions = Permission::query()
->orderBy('id')
->get(['id', 'code', 'name']);
if ($request->isMethod('get')) {
return view('admin.opes.add', [
'isEdit' => false,
'record' => new Ope(),
'ope_id' => null,
'ope_name' => '',
'ope_type' => '',
'ope_mail' => '',
'ope_phone' => '',
'ope_sendalart_que1' => 0, 'ope_sendalart_que2' => 0, 'ope_sendalart_que3' => 0,
'ope_sendalart_que4' => 0, 'ope_sendalart_que5' => 0, 'ope_sendalart_que6' => 0,
'ope_sendalart_que7' => 0, 'ope_sendalart_que8' => 0, 'ope_sendalart_que9' => 0,
'ope_sendalart_que10' => 0, 'ope_sendalart_que11' => 0, 'ope_sendalart_que12' => 0,
'ope_sendalart_que13' => 0,
'ope_auth1' => '', 'ope_auth2' => '', 'ope_auth3' => '', 'ope_auth4' => '',
'ope_quit_flag' => 0, 'ope_quitday' => '',
// ▼追加権限設定UI用
'features' => $features,
'permissions' => $permissions,
'selectedFeatureId' => old('feature_id', null),
]);
}
// 入力値を一旦取得
$data = $request->all();
// --- バリデーション ---
$rules = [
'login_id' => 'required|string|max:255|unique:ope,login_id',
'ope_name' => 'required|string|max:255',
'ope_type' => 'required|string|max:50',
'ope_mail' => [
'required',
function ($attribute, $value, $fail) {
// ; でも , でもOK、保存時は ; に統一
$emails = array_map('trim', explode(';', str_replace(',', ';', $value)));
foreach ($emails as $email) {
if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$fail("無効なメールアドレス形式です: {$email}");
}
}
}
],
'ope_phone' => 'nullable|string|max:50',
'password' => 'required|string|min:8|confirmed',
];
$request->validate($rules);
// --- 保存用にメールを ; 区切りに統一 ---
$emails = array_filter(array_map('trim', explode(';', str_replace(',', ';', $data['ope_mail']))));
$data['ope_mail'] = implode(';', $emails);
// 保存処理
$ope = new Ope();
$ope->fill($data);
$ope->save();
return redirect()->route('opes')->with('success', '登録しました。');
}
/**
* 編集GET 画面 / POST 更新)
* ※権限(自治体×機能×操作)も同画面で設定する
*/
public function edit($id, Request $request)
{
$ope = Ope::getByPk($id);
if (!$ope) abort(404);
// ※機能(画面)一覧を取得(プルダウン用)
$features = Feature::query()
->orderBy('id')
->get(['id', 'name']);
// ※操作権限一覧を取得(チェックボックス用)
$permissions = Permission::query()
->orderBy('id')
->get(['id', 'code', 'name']);
// ※自治体IDopeに紐づく想定
$municipalityId = (int)($ope->municipality_id ?? 0);
if ($request->isMethod('get')) {
return view('admin.opes.edit', [
'isEdit' => true,
'record' => $ope,
// ▼追加権限設定UI用
'features' => $features,
'permissions' => $permissions,
'selectedFeatureId' => old('feature_id', null),
]);
}
/**
* ▼権限設定の保存feature_id + permission_ids[]
* ※画面側の保存ボタンを「権限も同時保存」にする場合はここで処理する
* ※もし「基本情報の更新」と「権限更新」をボタンで分けたい場合は、別アクションに分離推奨
*/
if ($request->has('feature_id')) {
$request->validate([
'feature_id' => ['required', 'integer', 'exists:features,id'],
'permission_ids' => ['nullable', 'array'],
'permission_ids.*' => ['integer', 'exists:permissions,id'],
]);
$featureId = (int)$request->input('feature_id');
$permissionIds = array_map('intval', (array)$request->input('permission_ids', []));
DB::transaction(function () use ($municipalityId, $featureId, $permissionIds) {
// ※機能単位で置換(自治体単位)
OpePermission::replaceByFeature($municipalityId, $featureId, $permissionIds);
});
}
// 入力値を一旦取得
$data = $request->all();
// --- バリデーション ---
$rules = [
'login_id' => "required|string|max:255|unique:ope,login_id,{$id},ope_id",
'ope_name' => 'required|string|max:255',
'ope_type' => 'required|string|max:50',
'ope_phone' => 'nullable|string|max:50',
'ope_mail' => [
'required',
function ($attribute, $value, $fail) {
$emails = array_map('trim', explode(';', str_replace(',', ';', $value)));
foreach ($emails as $email) {
if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$fail("無効なメールアドレス形式です: {$email}");
}
}
}
],
'password' => 'nullable|string|min:8|confirmed',
];
$request->validate($rules);
// --- 保存用にメールを ; 区切りに統一 ---
if (!empty($data['ope_mail'])) {
$emails = array_filter(array_map('trim', explode(';', str_replace(',', ';', $data['ope_mail']))));
$data['ope_mail'] = implode(';', $emails);
}
// パスワード空なら更新しない
if (empty($data['password'])) {
unset($data['password']);
}
// 保存処理
$ope->fill($data);
$ope->save();
return redirect()->route('opes')->with('success', '更新しました。');
}
/**
* 権限回顧AJAX
* /opes/{id}/permissions?feature_id=xx
* ※ope_permissionが自治体単位のため、opeの自治体IDで取得する
*/
public function getPermissionsByFeature(int $id, Request $request)
{
$ope = Ope::getByPk($id);
if (!$ope) abort(404);
$featureId = (int)$request->query('feature_id');
if ($featureId <= 0) {
return response()->json([]);
}
$municipalityId = (int)($ope->municipality_id ?? 0);
$ids = OpePermission::query()
->where('municipality_id', $municipalityId)
->where('feature_id', $featureId)
->pluck('permission_id')
->values();
return response()->json($ids);
}
/**
* 削除(単体 or 複数)
*/
public function delete(Request $request)
{
$ids = [];
// 単体削除
if ($request->filled('id')) {
$ids[] = (int)$request->input('id');
}
// 複数削除
if ($request->filled('ids')) {
$ids = array_merge($ids, array_map('intval', (array)$request->input('ids')));
}
$ids = array_unique($ids);
if (!$ids) {
return back()->with('error', '削除対象が選択されていません。');
}
Ope::deleteByPk($ids);
return redirect()->route('opes')->with('success', '削除しました。');
}
/**
* CSVインポート
*/
public function import(Request $request)
{
$validator = Validator::make($request->all(), [
'file' => 'required|file|mimes:csv,txt|max:20480',
]);
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
$file = $request->file('file')->getRealPath();
$handle = fopen($file, 'r');
if (!$handle) return back()->with('error', 'CSVを読み取れません。');
$header = fgetcsv($handle);
$header = array_map(fn($h) => trim(ltrim($h ?? '', "\xEF\xBB\xBF")), $header);
$fillable = (new Ope())->getFillable();
$rows = [];
while (($row = fgetcsv($handle)) !== false) {
$assoc = [];
foreach ($header as $i => $key) {
if (in_array($key, $fillable, true)) {
$assoc[$key] = $row[$i] ?? null;
}
}
if ($assoc) $rows[] = $assoc;
}
fclose($handle);
DB::transaction(function () use ($rows) {
foreach ($rows as $data) {
Ope::create($data);
}
});
return redirect()->route('opes')->with('success', count($rows) . '件をインポートしました。');
}
/**
* CSVエクスポート
*/
public function export(): StreamedResponse
{
$filename = 'ope_' . now()->format('Ymd_His') . '.csv';
$fillable = (new Ope())->getFillable();
$response = new StreamedResponse(function () use ($fillable) {
$out = fopen('php://output', 'w');
fprintf($out, chr(0xEF) . chr(0xBB) . chr(0xBF)); // BOM
fputcsv($out, $fillable);
Ope::orderBy('ope_id')->chunk(500, function ($chunk) use ($out, $fillable) {
foreach ($chunk as $row) {
$line = [];
foreach ($fillable as $f) {
$line[] = $row->$f ?? '';
}
fputcsv($out, $line);
}
});
fclose($out);
});
$response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
$response->headers->set('Content-Disposition', "attachment; filename={$filename}");
return $response;
}
}