Skip to content

[課題管理]レポート評価のインポート機能を追加しました #2177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions app/Enums/LearningtaskImportType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Enums;

use App\Enums\EnumsBase;

/**
* 課題管理インポートタイプ
*/
final class LearningtaskImportType extends EnumsBase
{
// 定数メンバ
const report = 'report';

// key/valueの連想配列
const enum = [
self::report => 'レポート評価',
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace App\Plugins\User\Learningtasks\Contracts;

/**
* 課題管理CSVインポートにおけるカラム定義を提供するクラスのためのインターフェース
*
* 実装クラスは、特定のインポートタイプ(例:レポート評価、試験評価)に応じた
* ヘッダーリスト、カラムマッピング、基本的なバリデーションルールを提供する責務を持つ。
*/
interface ColumnDefinitionInterface
{
/**
* 現在のコンテキスト(例: 課題投稿の設定など)に基づいて、
* CSVで期待される(または処理対象となる)ヘッダーカラム名のリストを取得する。
*
* @return array ヘッダー文字列の配列。例: ['ログインID', '評価', '評価コメント']
*/
public function getHeaders(): array;

/**
* この定義クラスが扱う可能性のある全てのCSVヘッダー名と、
* それに対応する内部キー名の完全なマッピング配列を取得する。
* Importer が列インデックスと内部キーを紐付けるために利用する。
*
* @return array ['CSVヘッダー名' => '内部キー名', ...]
*/
public function getColumnMap(): array;

/**
* 指定されたCSVヘッダー名に対応する内部キー名を取得する。
* マッピングが存在しない場合は null を返す。
*
* @param string $header_name CSVヘッダー名。例: '評価コメント'
* @return string|null 内部キー名。例: 'comment'。見つからない場合は null。
*/
public function getInternalKey(string $header_name): ?string;

/**
* このカラム定義(インポートタイプ)に対応する基本的なバリデーションルールを取得する。
* ルールは内部キー名に対して定義された連想配列として返す。
* Importer はこの基本ルールを利用してバリデーションを行う。
*
* @return array ['内部キー名' => ['ルール1', 'ルール2', ...], ...]
* 例: ['userid' => ['required', 'exists:users,userid'], 'grade' => ['nullable']]
*/
public function getValidationRulesBase(): array;

/**
* (任意) このカラム定義に対応するカスタムバリデーションメッセージを取得する。
* メッセージは '内部キー名.ルール名' をキーとする連想配列で返す。
* 実装クラスで不要な場合は空配列を返せば良い。
*
* @return array ['内部キー名.ルール名' => 'メッセージ文字列', ...]
* 例: ['userid.required' => 'ログインIDは必須です。']
*/
public function getValidationMessages(): array;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace App\Plugins\User\Learningtasks\Contracts;

use Illuminate\Validation\ValidationException;
use Throwable;

/**
* CSV行処理中の例外ハンドリング戦略を定義するインターフェース
*/
interface RowProcessorExceptionHandlerInterface
{
// 結果を表す定数
public const OUTCOME_ERROR = 'error';
public const OUTCOME_SKIP = 'skip';

// ログレベルを表す定数 (Log ファサードのメソッド名に合わせる)
public const LOG_ERROR = 'error';
public const LOG_WARN = 'warning';
public const LOG_INFO = 'info';
public const LOG_DEBUG = 'debug';

// 配列キーを示す定数
public const KEY_OUTCOME = 'outcome';
public const KEY_TYPE = 'type';
public const KEY_LOG_LEVEL = 'logLevel';

/**
* 捕捉された例外を処理し、その結果(エラーかスキップか、詳細タイプ、ログレベル)を返す。
*
* @param Throwable $e 捕捉された例外オブジェクト
* @return array|null 処理方法を示す配列 ['outcome' => 'error'|'skip', 'type' => string, 'log_level' => string] を返す。
* 処理できない/予期せぬ例外の場合は null を返すことも可能(その場合は Importer 側で 'unexpected_error' として扱われる)。
*/
public function handle(Throwable $e): ?array;

/**
* ValidationException から整形済みのメッセージを取得するヘルパ
* @param Throwable $e 捕捉された例外オブジェクト
* @return string
*/
public function formatValidationMessage(ValidationException $e): string;
}
31 changes: 31 additions & 0 deletions app/Plugins/User/Learningtasks/Contracts/RowProcessorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace App\Plugins\User\Learningtasks\Contracts;

use App\Models\Common\Page;
use App\Models\User\Learningtasks\LearningtasksPosts;
use App\User;
use Exception; // エラー発生時に基底例外を投げることを想定

/**
* インポート時に検証済みのCSVデータ1行分を処理するためのインターフェース
*/
interface RowProcessorInterface
{
/**
* 検証済みのデータ1行分を処理する。
*
* このメソッドの実装クラスが、CSVの1行に対応する
* データベースレコードの検索、更新、または作成といった
* コアなビジネスロジックを担当します。
*
* @param array $validated_data 検証済みデータ(内部キー名 => 値 の連想配列)
* 例: ['userid' => '123', 'grade' => 'A', 'comment' => 'Good']
* @param LearningtasksPosts $post インポート対象の課題投稿コンテキスト
* @param User $importer インポート操作を実行しているユーザー (評価者ID等に利用)
* @return void
* @throws Exception 処理中にエラーが発生した場合 (例: 関連データが見つからない、DBエラー)。
* より具体的なカスタム例外を定義して投げるのが望ましい。
*/
public function process(array $validated_data, LearningtasksPosts $post, Page $page, User $importer): void;
}
Loading