Merge pull request #473 from shikorism/feature/365-csv-flags

非公開フラグ、センシティブフラグのCSVインポート・エクスポート対応
This commit is contained in:
shibafu 2020-08-19 23:19:19 +09:00 committed by GitHub
commit 6f8c81cef2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 141 additions and 1 deletions

View File

@ -0,0 +1,62 @@
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class FuzzyBoolean implements Rule
{
public static function isTruthy($value): bool
{
if ($value === 1 || $value === '1') {
return true;
}
$lower = strtolower((string)$value);
return $lower === 'true';
}
public static function isFalsy($value): bool
{
if ($value === null || $value === '' || $value === 0 || $value === '0') {
return true;
}
$lower = strtolower((string)$value);
return $lower === 'false';
}
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
return self::isTruthy($value) || self::isFalsy($value);
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return __('validation.boolean');
}
}

View File

@ -30,7 +30,7 @@ class CheckinCsvExporter
$csv->addStreamFilter('convert.mbstring.encoding.UTF-8:SJIS-win'); $csv->addStreamFilter('convert.mbstring.encoding.UTF-8:SJIS-win');
} }
$header = ['日時', 'ノート', 'オカズリンク']; $header = ['日時', 'ノート', 'オカズリンク', '非公開', 'センシティブ'];
for ($i = 1; $i <= 32; $i++) { for ($i = 1; $i <= 32; $i++) {
$header[] = "タグ{$i}"; $header[] = "タグ{$i}";
} }
@ -45,6 +45,8 @@ class CheckinCsvExporter
$ejaculation->ejaculated_date->format('Y/m/d H:i'), $ejaculation->ejaculated_date->format('Y/m/d H:i'),
$ejaculation->note, $ejaculation->note,
$ejaculation->link, $ejaculation->link,
self::formatBoolean($ejaculation->is_private),
self::formatBoolean($ejaculation->is_too_sensitive),
]; ];
foreach ($ejaculation->tags->take(32) as $tag) { foreach ($ejaculation->tags->take(32) as $tag) {
$record[] = $tag->name; $record[] = $tag->name;
@ -54,4 +56,9 @@ class CheckinCsvExporter
}); });
}); });
} }
private static function formatBoolean($value): string
{
return $value ? 'true' : 'false';
}
} }

View File

@ -6,6 +6,7 @@ namespace App\Services;
use App\Ejaculation; use App\Ejaculation;
use App\Exceptions\CsvImportException; use App\Exceptions\CsvImportException;
use App\Rules\CsvDateTime; use App\Rules\CsvDateTime;
use App\Rules\FuzzyBoolean;
use App\Tag; use App\Tag;
use App\User; use App\User;
use Carbon\Carbon; use Carbon\Carbon;
@ -75,6 +76,8 @@ class CheckinCsvImporter
'日時' => ['required', new CsvDateTime()], '日時' => ['required', new CsvDateTime()],
'ノート' => 'nullable|string|max:500', 'ノート' => 'nullable|string|max:500',
'オカズリンク' => 'nullable|url|max:2000', 'オカズリンク' => 'nullable|url|max:2000',
'非公開' => ['nullable', new FuzzyBoolean()],
'センシティブ' => ['nullable', new FuzzyBoolean()],
]); ]);
if ($validator->fails()) { if ($validator->fails()) {
@ -88,6 +91,12 @@ class CheckinCsvImporter
$ejaculation->note = str_replace(["\r\n", "\r"], "\n", $record['ノート'] ?? ''); $ejaculation->note = str_replace(["\r\n", "\r"], "\n", $record['ノート'] ?? '');
$ejaculation->link = $record['オカズリンク'] ?? ''; $ejaculation->link = $record['オカズリンク'] ?? '';
$ejaculation->source = Ejaculation::SOURCE_CSV; $ejaculation->source = Ejaculation::SOURCE_CSV;
if (isset($record['非公開'])) {
$ejaculation->is_private = FuzzyBoolean::isTruthy($record['非公開']);
}
if (isset($record['センシティブ'])) {
$ejaculation->is_too_sensitive = FuzzyBoolean::isTruthy($record['センシティブ']);
}
try { try {
$tags = $this->parseTags($line, $record); $tags = $this->parseTags($line, $record);

View File

@ -277,6 +277,48 @@ class CheckinCsvImporterTest extends TestCase
$this->assertEquals(Ejaculation::SOURCE_CSV, $ejaculation->source); $this->assertEquals(Ejaculation::SOURCE_CSV, $ejaculation->source);
} }
public function testIsPrivateUTF8()
{
$user = factory(User::class)->create();
$importer = new CheckinCsvImporter($user, __DIR__ . '/../../fixture/Csv/private.utf8.csv');
$importer->execute();
$ejaculations = $user->ejaculations()->orderBy('ejaculated_date')->get();
$this->assertSame(9, $ejaculations->count());
$this->assertTrue($ejaculations[0]->is_private);
$this->assertTrue($ejaculations[1]->is_private);
$this->assertTrue($ejaculations[2]->is_private);
$this->assertTrue($ejaculations[3]->is_private);
$this->assertFalse($ejaculations[4]->is_private);
$this->assertFalse($ejaculations[5]->is_private);
$this->assertFalse($ejaculations[6]->is_private);
$this->assertFalse($ejaculations[7]->is_private);
$this->assertFalse($ejaculations[8]->is_private);
}
public function testIsTooSensitiveUTF8()
{
$user = factory(User::class)->create();
$importer = new CheckinCsvImporter($user, __DIR__ . '/../../fixture/Csv/too-sensitive.utf8.csv');
$importer->execute();
$ejaculations = $user->ejaculations()->orderBy('ejaculated_date')->get();
$this->assertSame(9, $ejaculations->count());
$this->assertTrue($ejaculations[0]->is_too_sensitive);
$this->assertTrue($ejaculations[1]->is_too_sensitive);
$this->assertTrue($ejaculations[2]->is_too_sensitive);
$this->assertTrue($ejaculations[3]->is_too_sensitive);
$this->assertFalse($ejaculations[4]->is_too_sensitive);
$this->assertFalse($ejaculations[5]->is_too_sensitive);
$this->assertFalse($ejaculations[6]->is_too_sensitive);
$this->assertFalse($ejaculations[7]->is_too_sensitive);
$this->assertFalse($ejaculations[8]->is_too_sensitive);
}
public function testDontThrowUniqueKeyViolation() public function testDontThrowUniqueKeyViolation()
{ {
$user = factory(User::class)->create(); $user = factory(User::class)->create();

10
tests/fixture/Csv/private.utf8.csv vendored Normal file
View File

@ -0,0 +1,10 @@
日時,非公開
2020/01/23 06:01:00,true
2020/01/23 06:02:00,TRUE
2020/01/23 06:03:00,True
2020/01/23 06:04:00,1
2020/01/23 07:01:00,false
2020/01/23 07:02:00,FALSE
2020/01/23 07:03:00,False
2020/01/23 07:04:00,0
2020/01/23 07:05:00,
1 日時 非公開
2 2020/01/23 06:01:00 true
3 2020/01/23 06:02:00 TRUE
4 2020/01/23 06:03:00 True
5 2020/01/23 06:04:00 1
6 2020/01/23 07:01:00 false
7 2020/01/23 07:02:00 FALSE
8 2020/01/23 07:03:00 False
9 2020/01/23 07:04:00 0
10 2020/01/23 07:05:00

View File

@ -0,0 +1,10 @@
日時,センシティブ
2020/01/23 06:01:00,true
2020/01/23 06:02:00,TRUE
2020/01/23 06:03:00,True
2020/01/23 06:04:00,1
2020/01/23 07:01:00,false
2020/01/23 07:02:00,FALSE
2020/01/23 07:03:00,False
2020/01/23 07:04:00,0
2020/01/23 07:05:00,
1 日時 センシティブ
2 2020/01/23 06:01:00 true
3 2020/01/23 06:02:00 TRUE
4 2020/01/23 06:03:00 True
5 2020/01/23 06:04:00 1
6 2020/01/23 07:01:00 false
7 2020/01/23 07:02:00 FALSE
8 2020/01/23 07:03:00 False
9 2020/01/23 07:04:00 0
10 2020/01/23 07:05:00