the browser-facing portion of osu!
at master 5.8 kB view raw
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 Database\Factories; 9 10use App\Libraries\Fulfillments\ApplySupporterTag; 11use App\Libraries\User\CountryChangeTarget; 12use App\Models\Beatmap; 13use App\Models\Country; 14use App\Models\User; 15use App\Models\UserAccountHistory; 16use App\Models\UserCountryHistory; 17use App\Models\UserStatistics\Model as UserStatisticsModel; 18 19class UserFactory extends Factory 20{ 21 const DEFAULT_PASSWORD = 'password'; 22 23 public static function createRecentCountryHistory(User $user, ?string $country, ?int $months): void 24 { 25 $months ??= CountryChangeTarget::minMonths(); 26 $country ??= Country::factory()->create()->getKey(); 27 $currentMonth = CountryChangeTarget::currentMonth(); 28 $userId = $user->getKey(); 29 for ($i = 0; $i < $months; $i++) { 30 UserCountryHistory::create([ 31 'country_acronym' => $country, 32 'user_id' => $userId, 33 'year_month' => $currentMonth->subMonths($i), 34 ]); 35 } 36 } 37 38 private static function defaultPasswordHash() 39 { 40 static $password; 41 42 return $password ??= password_hash(md5(static::DEFAULT_PASSWORD), PASSWORD_BCRYPT); 43 } 44 45 protected $model = User::class; 46 47 public function configure() 48 { 49 return $this->afterCreating(function (User $user) { 50 $user->addToGroup(app('groups')->byIdOrFail($user->group_id)); 51 }); 52 } 53 54 public function definition(): array 55 { 56 // Get or create a random country 57 $countryAcronym = fn () => Country::inRandomOrder()->first() ?? Country::factory()->create(); 58 59 return [ 60 'username' => fn () => substr(str_replace('.', ' ', $this->faker->unique()->userName()), 0, 15), 61 'user_password' => static::defaultPasswordHash(), 62 'user_email' => fn () => $this->faker->unique()->safeEmail(), 63 'group_id' => fn () => app('groups')->byIdentifier('default'), 64 'user_lastvisit' => time(), 65 'user_posts' => rand(1, 500), 66 'user_warnings' => 0, 67 'user_type' => 0, 68 'osu_kudosavailable' => rand(1, 500), 69 'osu_kudosdenied' => rand(1, 500), 70 'osu_kudostotal' => rand(1, 500), 71 'country_acronym' => $countryAcronym, 72 'osu_playstyle' => [array_rand(User::PLAYSTYLES)], 73 'user_website' => 'http://www.google.com/', 74 'user_twitter' => 'ppy', 75 'user_permissions' => '', 76 'user_interests' => fn () => mb_substr($this->faker->bs(), 0, 30), 77 'user_occ' => fn () => mb_substr($this->faker->catchPhrase(), 0, 30), 78 'user_sig' => fn () => $this->faker->realText(155), 79 'user_from' => fn () => mb_substr($this->faker->country(), 0, 25), 80 'user_regdate' => fn () => $this->faker->dateTimeBetween('-6 years'), 81 ]; 82 } 83 84 // convenience for dataProviders so null checks don't have to be called when creating with named state. 85 public function default() 86 { 87 return $this; 88 } 89 90 public function restricted() 91 { 92 return $this 93 ->state(['user_warnings' => 1]) 94 ->has(UserAccountHistory::factory()->restriction(), 'accountHistories'); 95 } 96 97 public function silenced() 98 { 99 return $this->has(UserAccountHistory::factory()->silence(), 'accountHistories'); 100 } 101 102 public function supporter() 103 { 104 return $this->state([ 105 'osu_subscriber' => true, 106 'osu_subscriptionexpiry' => ApplySupporterTag::addDuration(now()->floorSecond(), 1), 107 ]); 108 } 109 110 public function tournamentBanned() 111 { 112 return $this->has(UserAccountHistory::factory()->tournamentBan(), 'accountHistories'); 113 } 114 115 public function withGroup(?string $groupIdentifier, ?array $playmodes = null) 116 { 117 if ($groupIdentifier === null) { 118 return $this; 119 } 120 121 $group = app('groups')->byIdentifier($groupIdentifier); 122 123 return $this 124 ->state(['group_id' => $group]) 125 ->afterCreating(function (User $user) use ($group, $playmodes) { 126 $user->addToGroup($group); 127 128 if ($playmodes !== null) { 129 if (!$group->has_playmodes) { 130 $group->update(['has_playmodes' => true]); 131 132 // TODO: This shouldn't have to be called here, since it's already 133 // called by `Group::afterCommit`, but `Group::afterCommit` isn't 134 // running in tests when creating/saving `Group`s. 135 app('groups')->resetMemoized(); 136 } 137 138 $user->findUserGroup($group, true)->update(['playmodes' => $playmodes]); 139 } 140 }); 141 } 142 143 public function withNote() 144 { 145 return $this->has(UserAccountHistory::factory(), 'accountHistories'); 146 } 147 148 public function withPlays(?int $count = null, ?string $ruleset = 'osu'): static 149 { 150 $state = [ 151 'playcount' => $count ?? $GLOBALS['cfg']['osu']['user']['min_plays_for_posting'], 152 ]; 153 154 $ret = $this->has( 155 UserStatisticsModel::getClass($ruleset)::factory()->state($state), 156 'statistics'.studly_case($ruleset), 157 ); 158 159 foreach (Beatmap::VARIANTS[$ruleset] ?? [] as $variant) { 160 $ret = $ret->has( 161 UserStatisticsModel::getClass($ruleset, $variant)::factory()->state($state), 162 'statistics'.studly_case("{$ruleset}_{$variant}"), 163 ); 164 } 165 166 return $ret; 167 } 168}