repositoryFiles() as $file) { $content = file_get_contents($file); preg_match_all( "/DB::connection\\('read'\\)->table\\([\\s\\S]*?->(?:first|get|exists|pluck|value)\\(/", $content, $matches ); foreach ($matches[0] as $query) { $this->assertContains( "->lock('WITH (NOLOCK)')", $query, basename($file) . ' has a read query without WITH (NOLOCK): ' . $this->compactQuery($query) ); } } } public function testJoinedTablesUseNoLockHints(): void { foreach ($this->repositoryFiles() as $file) { $content = file_get_contents($file); preg_match_all('/->(?:leftJoin|join)\\(([\\s\\S]*?)\\n\\s*\\)/', $content, $matches); foreach ($matches[0] as $join) { $this->assertContains( 'WITH (NOLOCK)', $join, basename($file) . ' has a joined table without WITH (NOLOCK): ' . $this->compactQuery($join) ); } } } public function testDynamicConnectionReadQueriesUseNoLockBranch(): void { foreach ($this->repositoryFiles() as $file) { $content = file_get_contents($file); preg_match_all( '/DB::connection\\(\\$connection\\)->table\\([\\s\\S]*?->(?:first|get|exists|pluck|value)\\(/', $content, $matches ); foreach ($matches[0] as $query) { $this->assertContains( "if (\$connection === 'read')", $query, basename($file) . ' has a dynamic read query without a read-only branch: ' . $this->compactQuery($query) ); $this->assertContains( "->lock('WITH (NOLOCK)')", $query, basename($file) . ' has a dynamic read query without WITH (NOLOCK): ' . $this->compactQuery($query) ); } } } public function testSettlementUsesStoredBetOddsInsteadOfCurrentOdds(): void { $content = file_get_contents( __DIR__ . '/../../app/Services/WorldCup/Repositories/SqlWorldCupSettlementRepository.php' ); $this->assertNotContains('applyCurrentOdds', $content); $this->assertNotContains('currentOdds', $content); $this->assertNotContains('self::ODDS_TABLE', $this->methodBody($content, 'payBet')); } public function testReferralRewardLogOnlyFiltersCurrentUserAsReferrer(): void { $content = file_get_contents( __DIR__ . '/../../app/Services/WorldCup/Repositories/SqlWorldCupReferralRepository.php' ); $rewardLogs = $this->methodBody($content, 'rewardLogs'); $rewardStats = $this->methodBody($content, 'rewardStats'); $this->assertContains("->where('rw.referrer_id', \$userId)", $rewardLogs); $this->assertNotContains("->orWhere('rw.invitee_id', \$userId)", $rewardLogs); $this->assertContains("->where('referrer_id', \$userId)", $rewardStats); $this->assertNotContains("->orWhere('invitee_id', \$userId)", $rewardStats); } private function repositoryFiles(): array { return glob(__DIR__ . '/../../app/Services/WorldCup/Repositories/SqlWorldCup*Repository.php'); } private function compactQuery(string $query): string { return preg_replace('/\\s+/', ' ', trim($query)); } private function methodBody(string $content, string $method): string { $pattern = '/public function ' . preg_quote($method, '/') . '\\([\\s\\S]*?\\n }/'; preg_match($pattern, $content, $matches); $this->assertNotEmpty($matches, 'Method not found: ' . $method); return $matches[0]; } }