-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This route updates the current playlist state and updates the users' playback history
- Loading branch information
Showing
8 changed files
with
263 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"$schema": "https://json-schema.org/draft/2020-12/schema", | ||
"$id": "https://uxmp/NowPlayingUpdate.json", | ||
"title": "Update NowPlaying state", | ||
"description": "Defines the nowplaying state request for the user", | ||
"type": "object", | ||
"properties": { | ||
"songId": { | ||
"type": "integer", | ||
"description": "The current song id" | ||
}, | ||
"temporaryPlaylist": { | ||
"type": "object", | ||
"description": "Playlist id, if available", | ||
"properties": { | ||
"id": { | ||
"type": ["string", "null"], | ||
"description": "The id of the temporary playlist" | ||
}, | ||
"offset": { | ||
"type": "integer", | ||
"description": "The position of the song in the playlist" | ||
} | ||
}, | ||
"required": ["id", "offset"] | ||
} | ||
}, | ||
"additionalProperties": false, | ||
"required": ["songId", "temporaryPlaylist"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Uxmp\Core\Api\Playback; | ||
|
||
use DateTime; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
use Uxmp\Core\Api\AbstractApiApplication; | ||
use Uxmp\Core\Api\Lib\SchemaValidatorInterface; | ||
use Uxmp\Core\Component\Authentication\SessionValidatorMiddleware; | ||
use Uxmp\Core\Orm\Repository\PlaybackHistoryRepositoryInterface; | ||
use Uxmp\Core\Orm\Repository\SongRepositoryInterface; | ||
use Uxmp\Core\Orm\Repository\TemporaryPlaylistRepositoryInterface; | ||
|
||
/** | ||
* Adds the song to the users' playback history and updates the temporary playlist | ||
*/ | ||
final class NowPlayingUpdate extends AbstractApiApplication | ||
{ | ||
/** | ||
* @param SchemaValidatorInterface<array{ | ||
* songId: int, | ||
* temporaryPlaylist: array{ | ||
* id: string|null, | ||
* offset: int | ||
* } | ||
* }> $schemaValidator | ||
*/ | ||
public function __construct( | ||
private readonly SchemaValidatorInterface $schemaValidator, | ||
private readonly TemporaryPlaylistRepositoryInterface $temporaryPlaylistRepository, | ||
private readonly PlaybackHistoryRepositoryInterface $playbackHistoryRepository, | ||
private readonly SongRepositoryInterface $songRepository, | ||
) { | ||
} | ||
|
||
protected function run( | ||
ServerRequestInterface $request, | ||
ResponseInterface $response, | ||
array $args | ||
): ResponseInterface { | ||
$body = $this->schemaValidator->getValidatedBody( | ||
$request, | ||
'NowPlayingUpdate.json', | ||
); | ||
$user = $request->getAttribute(SessionValidatorMiddleware::USER); | ||
|
||
$temporaryPlaylist = $this->temporaryPlaylistRepository->findOneBy([ | ||
'id' => $body['temporaryPlaylist']['id'], | ||
'owner' => $user, | ||
]); | ||
|
||
if ($temporaryPlaylist !== null) { | ||
$temporaryPlaylist->setOffset($body['temporaryPlaylist']['offset']); | ||
|
||
$this->temporaryPlaylistRepository->save($temporaryPlaylist); | ||
} | ||
|
||
$song = $this->songRepository->find($body['songId']); | ||
|
||
if ($song !== null) { | ||
$history = $this->playbackHistoryRepository->prototype() | ||
->setUser($user) | ||
->setSong($song) | ||
->setPlayDate(new DateTime()); | ||
|
||
$this->playbackHistoryRepository->save($history); | ||
} | ||
|
||
return $this->asJson( | ||
$response, | ||
[ | ||
'result' => true, | ||
] | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Uxmp\Core\Api\Playback; | ||
|
||
use DateTime; | ||
use Mockery; | ||
use Mockery\Adapter\Phpunit\MockeryTestCase; | ||
use Mockery\MockInterface; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
use Psr\Http\Message\StreamInterface; | ||
use Uxmp\Core\Api\Lib\SchemaValidatorInterface; | ||
use Uxmp\Core\Component\Authentication\SessionValidatorMiddleware; | ||
use Uxmp\Core\Orm\Model\PlaybackHistoryInterface; | ||
use Uxmp\Core\Orm\Model\SongInterface; | ||
use Uxmp\Core\Orm\Model\TemporaryPlaylistInterface; | ||
use Uxmp\Core\Orm\Model\UserInterface; | ||
use Uxmp\Core\Orm\Repository\PlaybackHistoryRepositoryInterface; | ||
use Uxmp\Core\Orm\Repository\SongRepositoryInterface; | ||
use Uxmp\Core\Orm\Repository\TemporaryPlaylistRepositoryInterface; | ||
|
||
class NowPlayingUpdateTest extends MockeryTestCase | ||
{ | ||
private MockInterface $schemaValidator; | ||
|
||
private MockInterface $temporaryPlaylistRepository; | ||
|
||
private MockInterface $playbackHistoryRepository; | ||
|
||
private MockInterface $songRepository; | ||
|
||
private NowPlayingUpdate $subject; | ||
|
||
public function setUp(): void | ||
{ | ||
$this->schemaValidator = Mockery::mock(SchemaValidatorInterface::class); | ||
$this->temporaryPlaylistRepository = Mockery::mock(TemporaryPlaylistRepositoryInterface::class); | ||
$this->playbackHistoryRepository = Mockery::mock(PlaybackHistoryRepositoryInterface::class); | ||
$this->songRepository = Mockery::mock(SongRepositoryInterface::class); | ||
|
||
$this->subject = new NowPlayingUpdate( | ||
$this->schemaValidator, | ||
$this->temporaryPlaylistRepository, | ||
$this->playbackHistoryRepository, | ||
$this->songRepository, | ||
); | ||
} | ||
|
||
public function testInvokeReturnsData(): void | ||
{ | ||
$request = Mockery::mock(ServerRequestInterface::class); | ||
$response = Mockery::mock(ResponseInterface::class); | ||
$user = Mockery::mock(UserInterface::class); | ||
$temporaryPlaylist = Mockery::mock(TemporaryPlaylistInterface::class); | ||
$song = Mockery::mock(SongInterface::class); | ||
$history = Mockery::mock(PlaybackHistoryInterface::class); | ||
$stream = Mockery::mock(StreamInterface::class); | ||
|
||
$playlistId = 'some-id'; | ||
$offset = 666; | ||
$songId = 42; | ||
|
||
$request->shouldReceive('getAttribute') | ||
->with(SessionValidatorMiddleware::USER) | ||
->once() | ||
->andReturn($user); | ||
|
||
$this->temporaryPlaylistRepository->shouldReceive('findOneBy') | ||
->with([ | ||
'id' => $playlistId, | ||
'owner' => $user, | ||
]) | ||
->once() | ||
->andReturn($temporaryPlaylist); | ||
|
||
$this->schemaValidator->shouldReceive('getValidatedBody') | ||
->with($request, 'NowPlayingUpdate.json') | ||
->once() | ||
->andReturn([ | ||
'temporaryPlaylist' => [ | ||
'id' => $playlistId, | ||
'offset' => $offset, | ||
], | ||
'songId' => $songId, | ||
]); | ||
$this->temporaryPlaylistRepository->shouldReceive('save') | ||
->with($temporaryPlaylist) | ||
->once(); | ||
|
||
$temporaryPlaylist->shouldReceive('setOffset') | ||
->with($offset) | ||
->once(); | ||
|
||
$this->songRepository->shouldReceive('find') | ||
->with($songId) | ||
->once() | ||
->andReturn($song); | ||
|
||
$this->playbackHistoryRepository->shouldReceive('prototype->setUser') | ||
->with($user) | ||
->once() | ||
->andReturn($history); | ||
$this->playbackHistoryRepository->shouldReceive('save') | ||
->with($history) | ||
->once(); | ||
|
||
$history->shouldReceive('setSong') | ||
->with($song) | ||
->once() | ||
->andReturnSelf(); | ||
$history->shouldReceive('setPlayDate') | ||
->with(Mockery::type(DateTime::class)) | ||
->once() | ||
->andReturnSelf(); | ||
|
||
$response->shouldReceive('getBody') | ||
->withNoArgs() | ||
->once() | ||
->andReturn($stream); | ||
$response->shouldReceive('withHeader') | ||
->with('Content-Type', 'application/json') | ||
->once() | ||
->andReturnSelf(); | ||
|
||
$stream->shouldReceive('write') | ||
->with(json_encode([ | ||
'result' => true, | ||
], JSON_PRETTY_PRINT)) | ||
->once(); | ||
|
||
$this->assertSame( | ||
$response, | ||
call_user_func($this->subject, $request, $response, []) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters