diff --git a/src/Cms/Api.php b/src/Cms/Api.php index 9f4caee181..f1489b62e7 100644 --- a/src/Cms/Api.php +++ b/src/Cms/Api.php @@ -118,35 +118,43 @@ public function file(string $path = null, string $filename) */ public function parent(string $path) { - $modelType = $path === 'site' ? 'site' : trim(dirname($path), '/'); - $modelTypes = ['site' => 'site', 'users' => 'user', 'pages' => 'page']; - $modelName = $modelTypes[$modelType] ?? null; + $modelType = in_array($path, ['site', 'account']) ? $path : trim(dirname($path), '/'); + $modelTypes = [ + 'site' => 'site', + 'users' => 'user', + 'pages' => 'page', + 'account' => 'account' + ]; + $modelName = $modelTypes[$modelType] ?? null; if (Str::endsWith($modelType, '/files') === true) { $modelName = 'file'; } - if ($modelName === null) { - throw new InvalidArgumentException('Invalid file model type'); + $kirby = $this->kirby(); + + switch ($modelName) { + case 'site': + $model = $kirby->site(); + break; + case 'account': + $model = $kirby->user(); + break; + case 'page': + $id = str_replace(['+', ' '], '/', basename($path)); + $model = $kirby->page($id); + break; + case 'file': + $model = $this->file(...explode('/files/', $path)); + break; + case 'user': + $model = $kirby->user(basename($path)); + break; + default: + throw new InvalidArgumentException('Invalid file model type: ' . $modelType); } - if ($modelName === 'site') { - $modelId = null; - } else { - $modelId = basename($path); - - if ($modelName === 'page') { - $modelId = str_replace(['+', ' '], '/', $modelId); - } - - if ($modelName === 'file') { - if ($model = $this->file(...explode('/files/', $path))) { - return $model; - } - } - } - - if ($model = $this->kirby()->$modelName($modelId)) { + if ($model) { return $model; } diff --git a/tests/Cms/Api/ApiTest.php b/tests/Cms/Api/ApiTest.php index 58ac5cf735..688e12d740 100644 --- a/tests/Cms/Api/ApiTest.php +++ b/tests/Cms/Api/ApiTest.php @@ -214,4 +214,48 @@ public function testAuthenticationWithoutUser() $function->call($api); } + + public function testParent() + { + $app = $this->app->clone([ + 'site' => [ + 'files' => [ + ['filename' => 'sitefile.jpg'] + ] + ], + 'users' => [ + [ + 'email' => 'current@getkirby.com', + ], + [ + 'email' => 'test@getkirby.com', + 'files' => [ + ['filename' => 'userfile.jpg'] + ] + ] + ], + ]); + + $app->impersonate('current@getkirby.com'); + + $api = $app->api(); + + $this->assertInstanceOf(User::class, $api->parent('account')); + $this->assertInstanceOf(User::class, $api->parent('users/test@getkirby.com')); + $this->assertInstanceOf(Site::class, $api->parent('site')); + $this->assertInstanceOf(Page::class, $api->parent('pages/a+aa')); + $this->assertInstanceOf(File::class, $api->parent('site/files/sitefile.jpg')); + $this->assertInstanceOf(File::class, $api->parent('pages/a/files/a-regular-file.jpg')); + $this->assertInstanceOf(File::class, $api->parent('users/test@getkirby.com/files/userfile.jpg')); + + // model type is not recognized + $this->expectException('Kirby\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Invalid file model type: something'); + $this->assertNull($api->parent('something/something')); + + // model cannot be found + $this->expectException('Kirby\Exception\NotFoundException'); + $this->expectExceptionMessage('The page cannot be found'); + $this->assertNull($api->parent('pages/does-not-exist')); + } }