Merge pull request #473 from shikorism/feature/365-csv-flags
非公開フラグ、センシティブフラグのCSVインポート・エクスポート対応
This commit is contained in:
		
							
								
								
									
										62
									
								
								app/Rules/FuzzyBoolean.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								app/Rules/FuzzyBoolean.php
									
									
									
									
									
										Normal 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');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -30,7 +30,7 @@ class CheckinCsvExporter
 | 
			
		||||
            $csv->addStreamFilter('convert.mbstring.encoding.UTF-8:SJIS-win');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $header = ['日時', 'ノート', 'オカズリンク'];
 | 
			
		||||
        $header = ['日時', 'ノート', 'オカズリンク', '非公開', 'センシティブ'];
 | 
			
		||||
        for ($i = 1; $i <= 32; $i++) {
 | 
			
		||||
            $header[] = "タグ{$i}";
 | 
			
		||||
        }
 | 
			
		||||
@@ -45,6 +45,8 @@ class CheckinCsvExporter
 | 
			
		||||
                            $ejaculation->ejaculated_date->format('Y/m/d H:i'),
 | 
			
		||||
                            $ejaculation->note,
 | 
			
		||||
                            $ejaculation->link,
 | 
			
		||||
                            self::formatBoolean($ejaculation->is_private),
 | 
			
		||||
                            self::formatBoolean($ejaculation->is_too_sensitive),
 | 
			
		||||
                        ];
 | 
			
		||||
                        foreach ($ejaculation->tags->take(32) as $tag) {
 | 
			
		||||
                            $record[] = $tag->name;
 | 
			
		||||
@@ -54,4 +56,9 @@ class CheckinCsvExporter
 | 
			
		||||
                });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static function formatBoolean($value): string
 | 
			
		||||
    {
 | 
			
		||||
        return $value ? 'true' : 'false';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ namespace App\Services;
 | 
			
		||||
use App\Ejaculation;
 | 
			
		||||
use App\Exceptions\CsvImportException;
 | 
			
		||||
use App\Rules\CsvDateTime;
 | 
			
		||||
use App\Rules\FuzzyBoolean;
 | 
			
		||||
use App\Tag;
 | 
			
		||||
use App\User;
 | 
			
		||||
use Carbon\Carbon;
 | 
			
		||||
@@ -75,6 +76,8 @@ class CheckinCsvImporter
 | 
			
		||||
                    '日時' => ['required', new CsvDateTime()],
 | 
			
		||||
                    'ノート' => 'nullable|string|max:500',
 | 
			
		||||
                    'オカズリンク' => 'nullable|url|max:2000',
 | 
			
		||||
                    '非公開' => ['nullable', new FuzzyBoolean()],
 | 
			
		||||
                    'センシティブ' => ['nullable', new FuzzyBoolean()],
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
                if ($validator->fails()) {
 | 
			
		||||
@@ -88,6 +91,12 @@ class CheckinCsvImporter
 | 
			
		||||
                $ejaculation->note = str_replace(["\r\n", "\r"], "\n", $record['ノート'] ?? '');
 | 
			
		||||
                $ejaculation->link = $record['オカズリンク'] ?? '';
 | 
			
		||||
                $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 {
 | 
			
		||||
                    $tags = $this->parseTags($line, $record);
 | 
			
		||||
 
 | 
			
		||||
@@ -277,6 +277,48 @@ class CheckinCsvImporterTest extends TestCase
 | 
			
		||||
        $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()
 | 
			
		||||
    {
 | 
			
		||||
        $user = factory(User::class)->create();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								tests/fixture/Csv/private.utf8.csv
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/fixture/Csv/private.utf8.csv
									
									
									
									
										vendored
									
									
										Normal 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,
 | 
			
		||||
		
		
			
  | 
							
								
								
									
										10
									
								
								tests/fixture/Csv/too-sensitive.utf8.csv
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/fixture/Csv/too-sensitive.utf8.csv
									
									
									
									
										vendored
									
									
										Normal 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,
 | 
			
		||||
		
		
			
  | 
		Reference in New Issue
	
	Block a user