diff --git a/.env.example b/.env.example index 244e6a5..a41650b 100644 --- a/.env.example +++ b/.env.example @@ -5,12 +5,12 @@ APP_DEBUG=true APP_LOG_LEVEL=debug APP_URL=http://localhost -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=homestead -DB_USERNAME=homestead -DB_PASSWORD=secret +DB_CONNECTION=pgsql +DB_HOST=db +DB_PORT=5432 +DB_DATABASE=tissue +DB_USERNAME=tissue +DB_PASSWORD=tissue BROADCAST_DRIVER=log CACHE_DRIVER=file @@ -35,3 +35,8 @@ SPARKPOST_SECRET= PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= + +# (Optional) reCAPTCHA Key +# https://www.google.com/recaptcha +NOCAPTCHA_SECRET= +NOCAPTCHA_SITEKEY= diff --git a/.gitattributes b/.gitattributes index 967315d..78179de 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,3 +3,4 @@ *.scss linguist-vendored *.js linguist-vendored CHANGELOG.md export-ignore +*.sh text eol=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore index 59247f3..f2e912f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ Homestead.yaml npm-debug.log yarn-error.log .env -*.iml \ No newline at end of file +*.iml +.php_cs +.php_cs.cache \ No newline at end of file diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000..1bfcc9f --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,26 @@ +setRules([ + '@PSR2' => true, + 'array_syntax' => [ + 'syntax' => 'short' + ], + 'blank_line_before_return' => true, + 'function_typehint_space' => true, + 'method_separation' => true, + 'ordered_imports' => true, + 'return_type_declaration' => true, + 'new_with_braces' => true, + 'no_empty_statement' => true, + 'standardize_not_equals' => true + ]) + ->setFinder( + \PhpCsFixer\Finder::create() + ->exclude('bootstrap/cache') + ->exclude('resources/views') + ->exclude('storage') + ->exclude('vendor') + ->exclude('node_modules') + ->in(__DIR__) + ); diff --git a/Dockerfile b/Dockerfile index 9301d92..65d49a8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,12 +3,19 @@ FROM php:7.1-apache ENV APACHE_DOCUMENT_ROOT /var/www/html/public RUN apt-get update \ - && apt-get install -y git libpq-dev \ + && apt-get install -y git libpq-dev unzip \ && docker-php-ext-install pdo_pgsql \ + && pecl install xdebug \ && curl -sS https://getcomposer.org/installer | php \ && mv composer.phar /usr/local/bin/composer \ && sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \ && sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf \ && a2enmod rewrite +COPY dist/bin /usr/local/bin/ +COPY dist/php.d /usr/local/etc/php/php.d/ + +ENTRYPOINT ["tissue-entrypoint.sh"] +CMD ["apache2-foreground"] + WORKDIR /var/www/html diff --git a/app/Ejaculation.php b/app/Ejaculation.php index 48bdaf9..83b3ad2 100644 --- a/app/Ejaculation.php +++ b/app/Ejaculation.php @@ -30,6 +30,8 @@ class Ejaculation extends Model public function textTags() { - return implode(' ', $this->tags->map(function ($v) { return $v->name; })->all()); + return implode(' ', $this->tags->map(function ($v) { + return $v->name; + })->all()); } } diff --git a/app/Events/LinkDiscovered.php b/app/Events/LinkDiscovered.php index 0163dc6..4fa6198 100644 --- a/app/Events/LinkDiscovered.php +++ b/app/Events/LinkDiscovered.php @@ -2,9 +2,9 @@ namespace App\Events; -use Illuminate\Queue\SerializesModels; -use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Queue\SerializesModels; class LinkDiscovered { diff --git a/app/Facades/Formatter.php b/app/Facades/Formatter.php index ed43178..b629419 100644 --- a/app/Facades/Formatter.php +++ b/app/Facades/Formatter.php @@ -10,4 +10,4 @@ class Formatter extends Facade { return \App\Utilities\Formatter::class; } -} \ No newline at end of file +} diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index c68ed7e..0f6dfcb 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -2,10 +2,10 @@ namespace App\Http\Controllers\Auth; -use App\User; use App\Http\Controllers\Controller; -use Illuminate\Support\Facades\Validator; +use App\User; use Illuminate\Foundation\Auth\RegistersUsers; +use Illuminate\Support\Facades\Validator; class RegisterController extends Controller { @@ -47,11 +47,20 @@ class RegisterController extends Controller */ protected function validator(array $data) { - return Validator::make($data, [ + $rules = [ 'name' => 'required|string|regex:/^[a-zA-Z0-9_-]+$/u|max:15|unique:users', 'email' => 'required|string|email|max:255|unique:users', - 'password' => 'required|string|min:6|confirmed', - ], + 'password' => 'required|string|min:6|confirmed' + ]; + + // reCAPTCHAのキーが設定されている場合、判定を有効化 + if (!empty(config('captcha.secret'))) { + $rules['g-recaptcha-response'] = 'required|captcha'; + } + + return Validator::make( + $data, + $rules, ['name.regex' => 'ユーザー名には半角英数字とアンダーバー、ハイフンのみ使用できます。'], ['name' => 'ユーザー名'] ); diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 03e02a2..a0a2a8a 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -2,10 +2,10 @@ namespace App\Http\Controllers; -use Illuminate\Foundation\Bus\DispatchesJobs; -use Illuminate\Routing\Controller as BaseController; -use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; +use Illuminate\Foundation\Bus\DispatchesJobs; +use Illuminate\Foundation\Validation\ValidatesRequests; +use Illuminate\Routing\Controller as BaseController; class Controller extends BaseController { diff --git a/app/Http/Controllers/EjaculationController.php b/app/Http/Controllers/EjaculationController.php index 83f4dd9..4490677 100644 --- a/app/Http/Controllers/EjaculationController.php +++ b/app/Http/Controllers/EjaculationController.php @@ -2,14 +2,14 @@ namespace App\Http\Controllers; +use App\Ejaculation; use App\Events\LinkDiscovered; use App\Tag; use App\User; use Carbon\Carbon; -use Validator; -use App\Ejaculation; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Validator; class EjaculationController extends Controller { @@ -104,6 +104,7 @@ class EjaculationController extends Controller public function edit($id) { $ejaculation = Ejaculation::findOrFail($id); + return view('ejaculation.edit')->with(compact('ejaculation')); } @@ -133,7 +134,7 @@ class EjaculationController extends Controller }); if ($validator->fails()) { - return redirect()->route('checkin')->withErrors($validator)->withInput(); + return redirect()->route('checkin.edit', ['id' => $id])->withErrors($validator)->withInput(); } $ejaculation->fill([ @@ -166,6 +167,7 @@ class EjaculationController extends Controller $user = User::findOrFail($ejaculation->user_id); $ejaculation->tags()->detach(); $ejaculation->delete(); + return redirect()->route('user.profile', ['name' => $user->name])->with('status', '削除しました。'); } -} \ No newline at end of file +} diff --git a/app/Http/Controllers/InfoController.php b/app/Http/Controllers/InfoController.php index 6a43159..33ff29b 100644 --- a/app/Http/Controllers/InfoController.php +++ b/app/Http/Controllers/InfoController.php @@ -14,6 +14,7 @@ class InfoController extends Controller ->orderByDesc('pinned') ->orderByDesc('created_at') ->paginate(20); + return view('info.index')->with([ 'informations' => $informations, 'categories' => Information::CATEGORIES @@ -23,6 +24,7 @@ class InfoController extends Controller public function show($id) { $information = Information::findOrFail($id); + return view('info.show')->with([ 'info' => $information, 'category' => Information::CATEGORIES[$information->category] diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 0b7205c..f0eb1d4 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -38,4 +38,4 @@ class SearchController extends Controller return view('search.relatedTag')->with(compact('inputs', 'results')); } -} \ No newline at end of file +} diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index c07fada..b6cf901 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -21,7 +21,8 @@ class UserController extends Controller } // チェックインの取得 - $query = Ejaculation::select(DB::raw(<<<'SQL' + $query = Ejaculation::select(DB::raw( + <<<'SQL' id, ejaculated_date, note, @@ -63,7 +64,8 @@ SQL abort(404); } - $groupByDay = Ejaculation::select(DB::raw(<<<'SQL' + $groupByDay = Ejaculation::select(DB::raw( + <<<'SQL' to_char(ejaculated_date, 'YYYY/MM/DD') AS "date", count(*) AS "count" SQL @@ -73,7 +75,8 @@ SQL ->orderBy(DB::raw("to_char(ejaculated_date, 'YYYY/MM/DD')")) ->get(); - $groupByHour = Ejaculation::select(DB::raw(<<<'SQL' + $groupByHour = Ejaculation::select(DB::raw( + <<<'SQL' to_char(ejaculated_date, 'HH24') AS "hour", count(*) AS "count" SQL @@ -133,7 +136,8 @@ SQL } // チェックインの取得 - $query = Ejaculation::select(DB::raw(<<<'SQL' + $query = Ejaculation::select(DB::raw( + <<<'SQL' id, ejaculated_date, note, diff --git a/app/Http/ViewComposers/ProfileComposer.php b/app/Http/ViewComposers/ProfileComposer.php index 5a0f862..cbb9a85 100644 --- a/app/Http/ViewComposers/ProfileComposer.php +++ b/app/Http/ViewComposers/ProfileComposer.php @@ -58,4 +58,4 @@ SQL $view->with(compact('latestEjaculation', 'currentSession', 'summary')); } -} \ No newline at end of file +} diff --git a/app/Listeners/LinkCollector.php b/app/Listeners/LinkCollector.php index 3d34b89..0484f95 100644 --- a/app/Listeners/LinkCollector.php +++ b/app/Listeners/LinkCollector.php @@ -7,8 +7,8 @@ use App\Metadata; use App\MetadataResolver\MetadataResolver; use App\Utilities\Formatter; use GuzzleHttp\Exception\TransferException; -use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Queue\InteractsWithQueue; use Illuminate\Support\Facades\Log; class LinkCollector @@ -43,14 +43,14 @@ class LinkCollector // 無かったら取得 // TODO: ある程度古かったら再取得とかありだと思う $metadata = Metadata::find($url); - if ($metadata == null) { + if ($metadata == null || ($metadata->expires_at !== null && $metadata->expires_at < now())) { try { $resolved = $this->metadataResolver->resolve($url); - Metadata::create([ - 'url' => $url, + Metadata::updateOrCreate(['url' => $url], [ 'title' => $resolved->title, 'description' => $resolved->description, - 'image' => $resolved->image + 'image' => $resolved->image, + 'expires_at' => $resolved->expires_at ]); } catch (TransferException $e) { // 何らかの通信エラーによってメタデータの取得に失敗した時、とりあえずエラーログにURLを残す diff --git a/app/Metadata.php b/app/Metadata.php index 98badb6..dc44009 100644 --- a/app/Metadata.php +++ b/app/Metadata.php @@ -10,6 +10,8 @@ class Metadata extends Model protected $primaryKey = 'url'; protected $keyType = 'string'; - protected $fillable = ['url', 'title', 'description', 'image']; - protected $visible = ['url', 'title', 'description', 'image']; + protected $fillable = ['url', 'title', 'description', 'image', 'expires_at']; + protected $visible = ['url', 'title', 'description', 'image', 'expires_at']; + + protected $dates = ['created_at', 'updated_at', 'expires_at']; } diff --git a/app/MetadataResolver/DLsiteResolver.php b/app/MetadataResolver/DLsiteResolver.php index 866bde0..ac1a717 100644 --- a/app/MetadataResolver/DLsiteResolver.php +++ b/app/MetadataResolver/DLsiteResolver.php @@ -2,8 +2,6 @@ namespace App\MetadataResolver; -use Illuminate\Support\Facades\Log; - class DLsiteResolver implements Resolver { public function resolve(string $url): Metadata @@ -14,9 +12,10 @@ class DLsiteResolver implements Resolver $ogpResolver = new OGPResolver(); $metadata = $ogpResolver->parse($res->getBody()); $metadata->image = str_replace("img_sam.jpg", "img_main.jpg", $metadata->image); + return $metadata; } else { throw new \RuntimeException("{$res->getStatusCode()}: $url"); } } -} \ No newline at end of file +} diff --git a/app/MetadataResolver/FantiaResolver.php b/app/MetadataResolver/FantiaResolver.php new file mode 100644 index 0000000..8a998c4 --- /dev/null +++ b/app/MetadataResolver/FantiaResolver.php @@ -0,0 +1,42 @@ +get($url); + if ($res->getStatusCode() === 200) { + $ogpResolver = new OGPResolver(); + $metadata = $ogpResolver->parse($res->getBody()); + + $dom = new \DOMDocument(); + @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8')); + $xpath = new \DOMXPath($dom); + + $node = $xpath->query("//meta[@property='twitter:image']")->item(0); + $ogpUrl = $node->getAttribute('content'); + + // 投稿に画像がない場合(ogp.jpgでない場合)のみ大きい画像に変換する + if ($ogpUrl != "http://fantia.jp/images/ogp.jpg") { + preg_match("~https://fantia\.s3\.amazonaws\.com/uploads/post/file/{$postId}/ogp_(.*?)\.(jpg|png)~", $ogpUrl, $match); + $uuid = $match[1]; + $extension = $match[2]; + + // 大きい画像に変換 + $metadata->image = "https://c.fantia.jp/uploads/post/file/{$postId}/main_{$uuid}.{$extension}"; + } + + return $metadata; + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } +} diff --git a/app/MetadataResolver/IwaraResolver.php b/app/MetadataResolver/IwaraResolver.php index d1bd8b9..60aaf1b 100644 --- a/app/MetadataResolver/IwaraResolver.php +++ b/app/MetadataResolver/IwaraResolver.php @@ -54,4 +54,4 @@ class IwaraResolver implements Resolver throw new \RuntimeException("{$res->getStatusCode()}: $url"); } } -} \ No newline at end of file +} diff --git a/app/MetadataResolver/KomifloResolver.php b/app/MetadataResolver/KomifloResolver.php index 81e0577..b09396a 100644 --- a/app/MetadataResolver/KomifloResolver.php +++ b/app/MetadataResolver/KomifloResolver.php @@ -27,4 +27,4 @@ class KomifloResolver implements Resolver throw new \RuntimeException("{$res->getStatusCode()}: $url"); } } -} \ No newline at end of file +} diff --git a/app/MetadataResolver/MelonbooksResolver.php b/app/MetadataResolver/MelonbooksResolver.php index 90d221a..2e8b7fb 100644 --- a/app/MetadataResolver/MelonbooksResolver.php +++ b/app/MetadataResolver/MelonbooksResolver.php @@ -26,4 +26,4 @@ class MelonbooksResolver implements Resolver throw new \RuntimeException("{$res->getStatusCode()}: $url"); } } -} \ No newline at end of file +} diff --git a/app/MetadataResolver/Metadata.php b/app/MetadataResolver/Metadata.php index ae2508b..dbe8654 100644 --- a/app/MetadataResolver/Metadata.php +++ b/app/MetadataResolver/Metadata.php @@ -2,9 +2,13 @@ namespace App\MetadataResolver; +use Carbon\Carbon; + class Metadata { public $title = ''; public $description = ''; public $image = ''; -} \ No newline at end of file + /** @var Carbon|null */ + public $expires_at = null; +} diff --git a/app/MetadataResolver/MetadataResolver.php b/app/MetadataResolver/MetadataResolver.php index 8180589..f1f43ed 100644 --- a/app/MetadataResolver/MetadataResolver.php +++ b/app/MetadataResolver/MetadataResolver.php @@ -12,6 +12,8 @@ class MetadataResolver implements Resolver '~ec\.toranoana\.jp/tora_r/ec/item/.*~' => ToranoanaResolver::class, '~iwara\.tv/videos/.*~' => IwaraResolver::class, '~www\.dlsite\.com/.*/work/=/product_id/..\d+\.html~' => DLsiteResolver::class, + '~www\.pixiv\.net/member_illust\.php\?illust_id=\d+~' => PixivResolver::class, + '~fantia\.jp/posts/\d+~' => FantiaResolver::class, '/.*/' => OGPResolver::class ]; @@ -19,11 +21,12 @@ class MetadataResolver implements Resolver { foreach ($this->rules as $pattern => $class) { if (preg_match($pattern, $url) === 1) { - $resolver = new $class; + $resolver = new $class(); + return $resolver->resolve($url); } } throw new \UnexpectedValueException('URL not matched.'); } -} \ No newline at end of file +} diff --git a/app/MetadataResolver/NicoSeigaResolver.php b/app/MetadataResolver/NicoSeigaResolver.php index dbd81bc..3e6d5c0 100644 --- a/app/MetadataResolver/NicoSeigaResolver.php +++ b/app/MetadataResolver/NicoSeigaResolver.php @@ -21,4 +21,4 @@ class NicoSeigaResolver implements Resolver throw new \RuntimeException("{$res->getStatusCode()}: $url"); } } -} \ No newline at end of file +} diff --git a/app/MetadataResolver/NijieResolver.php b/app/MetadataResolver/NijieResolver.php index e0802e6..45b73de 100644 --- a/app/MetadataResolver/NijieResolver.php +++ b/app/MetadataResolver/NijieResolver.php @@ -37,4 +37,4 @@ class NijieResolver implements Resolver throw new \RuntimeException("{$res->getStatusCode()}: $url"); } } -} \ No newline at end of file +} diff --git a/app/MetadataResolver/OGPResolver.php b/app/MetadataResolver/OGPResolver.php index 43d1543..e51fe2f 100644 --- a/app/MetadataResolver/OGPResolver.php +++ b/app/MetadataResolver/OGPResolver.php @@ -41,6 +41,7 @@ class OGPResolver implements Resolver } } } + return ''; } -} \ No newline at end of file +} diff --git a/app/MetadataResolver/PixivResolver.php b/app/MetadataResolver/PixivResolver.php new file mode 100644 index 0000000..b859675 --- /dev/null +++ b/app/MetadataResolver/PixivResolver.php @@ -0,0 +1,93 @@ +get($url); + if ($res->getStatusCode() === 200) { + $ogpResolver = new OGPResolver(); + $metadata = $ogpResolver->parse($res->getBody()); + + preg_match("~https://i\.pximg\.net/c/128x128/img-master/img/\d{4}/\d{2}/\d{2}/\d{2}/\d{2}/\d{2}/{$illustId}_p0_square1200\.jpg~", $res->getBody(), $match); + $illustThumbnailUrl = $match[0]; + + $illustUrl = $this->thumbnailToMasterUrl($illustThumbnailUrl); + + // 指定ページに変換 + $illustUrl = str_replace("p0_master", "p{$page}_master", $illustUrl); + + $metadata->image = $this->proxize($illustUrl); + + return $metadata; + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } else { + $client = new \GuzzleHttp\Client(); + $res = $client->get($url); + if ($res->getStatusCode() === 200) { + $ogpResolver = new OGPResolver(); + $metadata = $ogpResolver->parse($res->getBody()); + + // OGP がデフォルト画像であるようならなんとかして画像を取得する + if (strpos($metadata->image, "pixiv_logo.gif") || strpos($metadata->image, "pictures.jpg")) { + + // 作品ページの場合のみ対応 + if (strpos(parse_url($url)["query"], "mode=medium")) { + preg_match("~https://i\.pximg\.net/c/128x128/img-master/img/\d{4}/\d{2}/\d{2}/\d{2}/\d{2}/\d{2}/{$illustId}(_p0)?_square1200\.jpg~", $res->getBody(), $match); + $illustThumbnailUrl = $match[0]; + + $illustUrl = $this->thumbnailToMasterUrl($illustThumbnailUrl); + + $metadata->image = $this->proxize($illustUrl); + } + } + + return $metadata; + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } + } +} diff --git a/app/MetadataResolver/Resolver.php b/app/MetadataResolver/Resolver.php index cc54d28..a982822 100644 --- a/app/MetadataResolver/Resolver.php +++ b/app/MetadataResolver/Resolver.php @@ -5,4 +5,4 @@ namespace App\MetadataResolver; interface Resolver { public function resolve(string $url): Metadata; -} \ No newline at end of file +} diff --git a/app/MetadataResolver/ToranoanaResolver.php b/app/MetadataResolver/ToranoanaResolver.php index 84911e8..968fff6 100644 --- a/app/MetadataResolver/ToranoanaResolver.php +++ b/app/MetadataResolver/ToranoanaResolver.php @@ -14,9 +14,10 @@ class ToranoanaResolver implements Resolver $res = $client->get($url, ['cookies' => $cookieJar]); if ($res->getStatusCode() === 200) { $ogpResolver = new OGPResolver(); + return $ogpResolver->parse($res->getBody()); } else { throw new \RuntimeException("{$res->getStatusCode()}: $url"); } } -} \ No newline at end of file +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 9784b1a..e12ff88 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -2,8 +2,8 @@ namespace App\Providers; -use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; +use Illuminate\Support\Facades\Gate; class AuthServiceProvider extends ServiceProvider { diff --git a/app/Providers/BroadcastServiceProvider.php b/app/Providers/BroadcastServiceProvider.php index 352cce4..395c518 100644 --- a/app/Providers/BroadcastServiceProvider.php +++ b/app/Providers/BroadcastServiceProvider.php @@ -2,8 +2,8 @@ namespace App\Providers; -use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Broadcast; +use Illuminate\Support\ServiceProvider; class BroadcastServiceProvider extends ServiceProvider { diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 4e1b51e..2993781 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -2,8 +2,8 @@ namespace App\Providers; -use Illuminate\Support\Facades\Event; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; +use Illuminate\Support\Facades\Event; class EventServiceProvider extends ServiceProvider { diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 5ea48d3..548e4be 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -2,8 +2,8 @@ namespace App\Providers; -use Illuminate\Support\Facades\Route; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; +use Illuminate\Support\Facades\Route; class RouteServiceProvider extends ServiceProvider { diff --git a/app/User.php b/app/User.php index 94fcf46..5469e52 100644 --- a/app/User.php +++ b/app/User.php @@ -2,8 +2,8 @@ namespace App; -use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; +use Illuminate\Notifications\Notifiable; use Illuminate\Support\Facades\Auth; class User extends Authenticatable @@ -36,9 +36,10 @@ class User extends Authenticatable * @param int $size 画像サイズ * @return string Gravatar 画像URL */ - public function getProfileImageUrl($size = 30) : string + public function getProfileImageUrl($size = 30): string { $hash = md5(strtolower(trim($this->email))); + return '//www.gravatar.com/avatar/' . $hash . '?s=' . $size; } diff --git a/app/Utilities/Formatter.php b/app/Utilities/Formatter.php index c19e6f2..b7ea0e7 100644 --- a/app/Utilities/Formatter.php +++ b/app/Utilities/Formatter.php @@ -24,6 +24,7 @@ class Formatter $days = floor($value / 86400); $hours = floor($value % 86400 / 3600); $minutes = floor($value % 3600 / 60); + return "{$days}日 {$hours}時間 {$minutes}分"; } @@ -61,4 +62,4 @@ class Formatter return $url; } -} \ No newline at end of file +} diff --git a/composer.json b/composer.json index b309ae6..12d430e 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "type": "project", "require": { "php": ">=7.0.0", + "anhskohbo/no-captcha": "^3.0", "doctrine/dbal": "^2.9", "fideloper/proxy": "~3.3", "guzzlehttp/guzzle": "^6.3", @@ -16,6 +17,7 @@ "require-dev": { "barryvdh/laravel-debugbar": "^3.1", "filp/whoops": "~2.0", + "friendsofphp/php-cs-fixer": "^2.14", "fzaninotto/faker": "~1.4", "mockery/mockery": "~1.0", "phpunit/phpunit": "~6.0", diff --git a/composer.lock b/composer.lock index 0d47d7a..0e3e49e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,67 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "6ac4cd158b1f93a24e21fce57d4404c8", + "content-hash": "9a0efd1b396f7a748eee3b98cbd7b6a6", "packages": [ + { + "name": "anhskohbo/no-captcha", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/anhskohbo/no-captcha.git", + "reference": "164715a2de0fded5979e7a9b7721785d72a4a7d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/anhskohbo/no-captcha/zipball/164715a2de0fded5979e7a9b7721785d72a4a7d3", + "reference": "164715a2de0fded5979e7a9b7721785d72a4a7d3", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.2", + "illuminate/support": "5.0.*|5.1.*|5.2.*|5.3.*|5.4.*|5.5.*|5.6.*|5.7.*", + "php": ">=5.5.5" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Anhskohbo\\NoCaptcha\\NoCaptchaServiceProvider" + ], + "aliases": { + "NoCaptcha": "Anhskohbo\\NoCaptcha\\Facades\\NoCaptcha" + } + } + }, + "autoload": { + "psr-4": { + "Anhskohbo\\NoCaptcha\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "anhskohbo", + "email": "anhskohbo@gmail.com" + } + ], + "description": "No CAPTCHA reCAPTCHA For Laravel.", + "keywords": [ + "captcha", + "laravel", + "laravel4", + "laravel5", + "no-captcha", + "recaptcha" + ], + "time": "2018-08-27T02:16:31+00:00" + }, { "name": "dnoegel/php-xdg-base-dir", "version": "0.1", @@ -2986,6 +3045,180 @@ ], "time": "2018-11-09T08:37:55+00:00" }, + { + "name": "composer/semver", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2016-08-30T16:08:34+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "dc523135366eb68f22268d069ea7749486458562" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/dc523135366eb68f22268d069ea7749486458562", + "reference": "dc523135366eb68f22268d069ea7749486458562", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "time": "2018-11-29T10:59:02+00:00" + }, + { + "name": "doctrine/annotations", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2017-12-06T07:11:42+00:00" + }, { "name": "doctrine/instantiator", "version": "1.1.0", @@ -3101,6 +3334,102 @@ ], "time": "2018-10-23T09:00:00+00:00" }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v2.14.0", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "b788ea0af899cedc8114dca7db119c93b6685da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/b788ea0af899cedc8114dca7db119c93b6685da2", + "reference": "b788ea0af899cedc8114dca7db119c93b6685da2", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4", + "composer/xdebug-handler": "^1.2", + "doctrine/annotations": "^1.2", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^5.6 || ^7.0", + "php-cs-fixer/diff": "^1.3", + "symfony/console": "^3.4.17 || ^4.1.6", + "symfony/event-dispatcher": "^3.0 || ^4.0", + "symfony/filesystem": "^3.0 || ^4.0", + "symfony/finder": "^3.0 || ^4.0", + "symfony/options-resolver": "^3.0 || ^4.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0", + "symfony/stopwatch": "^3.0 || ^4.0" + }, + "conflict": { + "hhvm": "*" + }, + "require-dev": { + "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", + "justinrainbow/json-schema": "^5.0", + "keradus/cli-executor": "^1.2", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.1", + "php-cs-fixer/accessible-object": "^1.0", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.0.1", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.0.1", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1", + "phpunitgoodpractices/traits": "^1.5.1", + "symfony/phpunit-bridge": "^4.0" + }, + "suggest": { + "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "extra": { + "branch-alias": { + "dev-master": "2.14-dev" + } + }, + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationCaseFactory.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php", + "tests/Test/IntegrationCaseFactoryInterface.php", + "tests/Test/InternalIntegrationCaseFactory.php", + "tests/TestCase.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "time": "2019-01-04T18:29:47+00:00" + }, { "name": "fzaninotto/faker", "version": "v1.8.0", @@ -3475,6 +3804,57 @@ "description": "Library for handling version information and constraints", "time": "2017-03-05T17:38:23+00:00" }, + { + "name": "php-cs-fixer/diff", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/diff.git", + "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756", + "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "symfony/process": "^3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "SpacePossum" + } + ], + "description": "sebastian/diff v2 backport support for PHP5.6", + "homepage": "https://github.com/PHP-CS-Fixer", + "keywords": [ + "diff" + ], + "time": "2018-02-15T16:58:55+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", @@ -4641,6 +5021,215 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2016-10-03T07:35:21+00:00" }, + { + "name": "symfony/filesystem", + "version": "v4.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "c2ffd9a93f2d6c5be2f68a0aa7953cc229f871f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/c2ffd9a93f2d6c5be2f68a0aa7953cc229f871f8", + "reference": "c2ffd9a93f2d6c5be2f68a0aa7953cc229f871f8", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2019-01-03T09:07:35+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v4.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "fbcb106aeee72f3450298bf73324d2cc00d083d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/fbcb106aeee72f3450298bf73324d2cc00d083d1", + "reference": "fbcb106aeee72f3450298bf73324d2cc00d083d1", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2019-01-03T09:07:35+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", + "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2018-09-21T13:07:52+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v4.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "af62b35760fc92c8dbdce659b4eebdfe0e6a0472" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/af62b35760fc92c8dbdce659b4eebdfe0e6a0472", + "reference": "af62b35760fc92c8dbdce659b4eebdfe0e6a0472", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Stopwatch Component", + "homepage": "https://symfony.com", + "time": "2019-01-03T09:07:35+00:00" + }, { "name": "symfony/thanks", "version": "v1.1.0", diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 93d7dc8..ddf1941 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -1,8 +1,8 @@ timestamp('expires_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('metadata', function (Blueprint $table) { + $table->removeColumn('expires_at'); + }); + } +} diff --git a/dist/bin/tissue-entrypoint.sh b/dist/bin/tissue-entrypoint.sh new file mode 100755 index 0000000..49280f5 --- /dev/null +++ b/dist/bin/tissue-entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +if [[ "$APP_DEBUG" == "true" ]]; then + export PHP_INI_SCAN_DIR=":/usr/local/etc/php/php.d" +fi + +exec docker-php-entrypoint "$@" diff --git a/dist/php.d/99-xdebug.ini b/dist/php.d/99-xdebug.ini new file mode 100644 index 0000000..a6e8b8c --- /dev/null +++ b/dist/php.d/99-xdebug.ini @@ -0,0 +1,5 @@ +; Dockerでのデバッグ用設定 +zend_extension=xdebug.so +xdebug.remote_enable=true +xdebug.remote_autostart=true +xdebug.remote_host=host.docker.internal \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index f5fbae3..6055b8d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,13 +3,8 @@ version: "3" services: web: build: . - environment: - DB_CONNECTION: pgsql - DB_HOST: db - DB_PORT: 5432 - DB_DATABASE: tissue - DB_USERNAME: tissue - DB_PASSWORD: tissue + env_file: + - .env volumes: - .:/var/www/html networks: diff --git a/resources/lang/ja/validation.php b/resources/lang/ja/validation.php index 7b11851..ecf3a03 100644 --- a/resources/lang/ja/validation.php +++ b/resources/lang/ja/validation.php @@ -99,6 +99,10 @@ return [ 'attribute-name' => [ 'rule-name' => 'custom-message', ], + 'g-recaptcha-response' => [ + 'required' => '「私はロボットではありません」にチェックを入れてください。', + 'captcha' => 'reCAPTCHAチェックに失敗しました。何度試しても解決しない場合、管理者にお問い合わせください。', + ], ], /* @@ -117,4 +121,4 @@ return [ 'password' => 'パスワード', ], -]; \ No newline at end of file +]; diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index fed7176..395cc11 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -13,7 +13,7 @@