日付形式と範囲のチェック

This commit is contained in:
shibafu 2020-02-16 14:28:30 +09:00
parent b29a82435c
commit ea59bcf150
4 changed files with 70 additions and 4 deletions

View File

@ -51,6 +51,7 @@ class CheckinCsvImporter
} }
foreach ($csv->getRecords() as $offset => $record) { foreach ($csv->getRecords() as $offset => $record) {
$line = $offset + 1;
$ejaculation = new Ejaculation(['user_id' => $this->user->id]); $ejaculation = new Ejaculation(['user_id' => $this->user->id]);
$validator = Validator::make($record, [ $validator = Validator::make($record, [
@ -61,7 +62,7 @@ class CheckinCsvImporter
if ($validator->fails()) { if ($validator->fails()) {
foreach ($validator->errors()->all() as $message) { foreach ($validator->errors()->all() as $message) {
$errors[] = "{$offset} 行 : {$message}"; $errors[] = "{$line} 行 : {$message}";
} }
continue; continue;
} }
@ -82,7 +83,7 @@ class CheckinCsvImporter
break; break;
} }
if (mb_strlen($tag) > 255) { if (mb_strlen($tag) > 255) {
$errors[] = "{$offset} 行 : {$column}列は255文字以内にしてください。"; $errors[] = "{$line} 行 : {$column}列は255文字以内にしてください。";
continue 2; continue 2;
} }

View File

@ -17,6 +17,12 @@ class CsvDateTime implements Rule
'Y/n/j G:i', 'Y/n/j G:i',
]; ];
const MINIMUM_TIMESTAMP = 946652400; // 2000-01-01 00:00:00 JST
const MAXIMUM_TIMESTAMP = 4102412399; // 2099-12-31 23:59:59 JST
/** @var string Validation error message */
private $message = ':attribute の形式は "年/月/日 時:分" にしてください。';
/** /**
* Create a new rule instance. * Create a new rule instance.
* *
@ -44,8 +50,19 @@ class CsvDateTime implements Rule
foreach (self::VALID_FORMATS as $format) { foreach (self::VALID_FORMATS as $format) {
$date = \DateTime::createFromFormat('!' . $format, $value); $date = \DateTime::createFromFormat('!' . $format, $value);
if (!$date) {
continue;
}
if ($date && $date->format($format) === $value) { $timestamp = (int) $date->format('U');
if ($timestamp < self::MINIMUM_TIMESTAMP || self::MAXIMUM_TIMESTAMP < $timestamp) {
$this->message = ':attribute は 2000/01/01 00:00 〜 2099/12/31 23:59 の間のみ対応しています。';
return false;
}
$formatted = $date->format($format);
if ($formatted === $value) {
return true; return true;
} }
} }
@ -60,6 +77,6 @@ class CsvDateTime implements Rule
*/ */
public function message() public function message()
{ {
return ':attribute の形式は "年/月/日 時:分" にしてください。'; return $this->message;
} }
} }

View File

@ -70,4 +70,35 @@ class CheckinCsvImporterTest extends TestCase
'NoZero, NoSecond, UTF8' => [$date, __DIR__ . '/../../fixture/Csv/date-nozero-nosecond.utf8.csv'], 'NoZero, NoSecond, UTF8' => [$date, __DIR__ . '/../../fixture/Csv/date-nozero-nosecond.utf8.csv'],
]; ];
} }
public function testInvalidDate()
{
$user = factory(User::class)->create();
try {
$importer = new CheckinCsvImporter($user, __DIR__ . '/../../fixture/Csv/invalid-date.utf8.csv');
$importer->execute();
} catch (CsvImportException $e) {
$this->assertSame('2 行 : 日時 は 2000/01/01 00:00 〜 2099/12/31 23:59 の間のみ対応しています。', $e->getErrors()[0]);
$this->assertSame('3 行 : 日時 は 2000/01/01 00:00 〜 2099/12/31 23:59 の間のみ対応しています。', $e->getErrors()[1]);
$this->assertSame('4 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[2]);
$this->assertSame('5 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[3]);
$this->assertSame('6 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[4]);
$this->assertSame('7 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[5]);
$this->assertSame('8 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[6]);
$this->assertSame('9 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[7]);
$this->assertSame('10 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[8]);
$this->assertSame('11 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[9]);
$this->assertSame('12 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[10]);
$this->assertSame('13 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[11]);
$this->assertSame('14 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[12]);
$this->assertSame('15 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[13]);
$this->assertSame('16 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[14]);
$this->assertSame('17 行 : 日時 の形式は "年/月/日 時:分" にしてください。', $e->getErrors()[15]);
return;
}
$this->fail('期待する例外が発生していません');
}
} }

17
tests/fixture/Csv/invalid-date.utf8.csv vendored Normal file
View File

@ -0,0 +1,17 @@
日時,ノート
1999/12/31 23:59:59,最小境界
2100/01/01 00:00:00,最大境界
-1/01/01 00:00:00,存在しない日付
2019/-1/01 00:00:00,存在しない日付
2019/01/-1 00:00:00,存在しない日付
2019/02/29 00:00:00,存在しない日付
2019/00/01 00:00:00,存在しない日付
2019/01/00 00:00:00,存在しない日付
2019/01/32 00:00:00,存在しない日付
2019/13/01 00:00:00,存在しない日付
2019/01/01 00:60:00,存在しない時刻
2019/01/01 24:00:00,存在しない時刻
2019/01/01 00:00:60,存在しない時刻
2019/01/01 -1:00:00,存在しない時刻
2019/01/01 00:-1:00,存在しない時刻
2019/01/01 00:00:-1,存在しない時刻
1 日時 ノート
2 1999/12/31 23:59:59 最小境界
3 2100/01/01 00:00:00 最大境界
4 -1/01/01 00:00:00 存在しない日付
5 2019/-1/01 00:00:00 存在しない日付
6 2019/01/-1 00:00:00 存在しない日付
7 2019/02/29 00:00:00 存在しない日付
8 2019/00/01 00:00:00 存在しない日付
9 2019/01/00 00:00:00 存在しない日付
10 2019/01/32 00:00:00 存在しない日付
11 2019/13/01 00:00:00 存在しない日付
12 2019/01/01 00:60:00 存在しない時刻
13 2019/01/01 24:00:00 存在しない時刻
14 2019/01/01 00:00:60 存在しない時刻
15 2019/01/01 -1:00:00 存在しない時刻
16 2019/01/01 00:-1:00 存在しない時刻
17 2019/01/01 00:00:-1 存在しない時刻