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
6namespace Tests\Transformers;
7
8use App\Transformers\TransformerAbstract;
9use League\Fractal\TransformerAbstract as FractalTrasformerAbstract;
10use ReflectionClass;
11use Symfony\Component\Finder\Finder;
12use Symfony\Component\Finder\SplFileInfo;
13use Tests\TestCase;
14
15class DeclaredPermissionsTest extends TestCase
16{
17 /**
18 * @dataProvider transformerClassesDataProvider
19 */
20 public function testCorrectSubclass($class)
21 {
22 $this->assertTrue(is_subclass_of($class, TransformerAbstract::class));
23 }
24
25 /**
26 * @dataProvider privilegeDataProvider
27 */
28 public function testPrivilegeExists($class, ?string $include, string $privilege)
29 {
30 /** @var TransformerAbstract $transformer */
31 $transformer = new $class();
32 $allIncludes = array_merge($transformer->getDefaultIncludes(), $transformer->getAvailableIncludes());
33
34 if ($include !== null) {
35 $this->assertContains($include, $allIncludes, "{$class} has permission check for {$include} but does not exist in transformer.");
36 }
37
38 $this->assertTrue(method_exists(app('OsuAuthorize'), "check{$privilege}"), "{$class} uses check{$privilege} but is not implemented.");
39 }
40
41 public static function transformerClassesDataProvider()
42 {
43 return array_map(
44 function ($class) {
45 return [$class];
46 },
47 static::getTransformerClasses()
48 );
49 }
50
51 public static function privilegeDataProvider()
52 {
53 $data = [];
54
55 foreach (static::getTransformerClasses() as $class) {
56 $transformer = new $class();
57
58 if ($transformer->getRequiredPermission() !== null) {
59 $data[] = [$class, null, $transformer->getRequiredPermission()];
60 }
61
62 foreach ($transformer->getPermissions() as $include => $privilege) {
63 $data[] = [$class, $include, $privilege];
64 }
65 }
66
67 return $data;
68 }
69
70 private static function getTransformerClasses()
71 {
72 // data provider is set up before laravel boots, so can't use laravel methods.
73 $path = realpath(__DIR__.'/../../app/Transformers');
74 $files = Finder::create()->files()->in($path)->sortByName();
75 $classes = [];
76
77 foreach ($files as $file) {
78 $class = static::classFromFileInfo($file);
79 // use ReflectionClass so the qualified names are normalized.
80 $reflectionClass = new ReflectionClass($class);
81 if (
82 $reflectionClass->isSubclassOf(FractalTrasformerAbstract::class)
83 && $reflectionClass->getName() !== (new ReflectionClass(TransformerAbstract::class))->getName()
84 ) {
85 $classes[] = $class;
86 }
87 }
88
89 return $classes;
90 }
91
92 private static function classFromFileInfo(SplFileInfo $fileInfo)
93 {
94 $baseName = $fileInfo->getBasename(".{$fileInfo->getExtension()}");
95 $namespace = str_replace('/', '\\', $fileInfo->getRelativePath());
96 if (mb_strlen($namespace) !== 0) {
97 $namespace .= '\\';
98 }
99
100 return "\\App\\Transformers\\{$namespace}{$baseName}";
101 }
102}