1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6declare(strict_types=1);
7
8namespace App\Libraries\User;
9
10use App\Libraries\ImageProcessor;
11use App\Libraries\StorageUrl;
12use App\Models\User;
13
14class AvatarHelper
15{
16 public static function set(User $user, ?\SplFileInfo $src): bool
17 {
18 $id = $user->getKey();
19 $storage = \Storage::disk(static::disk());
20
21 if ($src === null) {
22 $storage->delete($id);
23 } else {
24 $srcPath = $src->getRealPath();
25 $processor = new ImageProcessor($srcPath, [256, 256], 100000);
26 $processor->process();
27
28 $storage->putFileAs('/', $src, $id, 'public');
29 $entry = $id.'_'.time().'.'.$processor->ext();
30 }
31
32 static::purgeCache($id);
33
34 return $user->update(['user_avatar' => $entry ?? '']);
35 }
36
37 public static function url(User $user): string
38 {
39 $value = $user->getRawAttribute('user_avatar');
40
41 return present($value)
42 ? StorageUrl::make(static::disk(), strtr($value, '_', '?'))
43 : $GLOBALS['cfg']['osu']['avatar']['default'];
44 }
45
46 private static function disk(): string
47 {
48 return $GLOBALS['cfg']['osu']['avatar']['storage'];
49 }
50
51 private static function purgeCache(int $id): void
52 {
53 $prefix = presence($GLOBALS['cfg']['osu']['avatar']['cache_purge_prefix']);
54
55 if ($prefix === null) {
56 return;
57 }
58
59 $method = $GLOBALS['cfg']['osu']['avatar']['cache_purge_method'] ?? 'GET';
60 $auth = $GLOBALS['cfg']['osu']['avatar']['cache_purge_authorization_key'];
61 $ctx = [
62 'http' => [
63 'method' => $method,
64 'header' => present($auth) ? "Authorization: {$auth}" : null,
65 ],
66 ];
67 $suffix = $method === 'GET' ? '?'.time() : ''; // Bypass CloudFlare cache if using GET
68 $url = "{$prefix}{$id}{$suffix}";
69
70 try {
71 file_get_contents($url, false, stream_context_create($ctx));
72 } catch (\ErrorException $e) {
73 // ignores 404 errors, throws everything else
74 if (!ends_with($e->getMessage(), "404 Not Found\r\n")) {
75 throw $e;
76 }
77 }
78 }
79}