diff --git a/app/Commands/AddTrackToPlaylistCommand.php b/app/Commands/AddTrackToPlaylistCommand.php new file mode 100644 index 00000000..cd514001 --- /dev/null +++ b/app/Commands/AddTrackToPlaylistCommand.php @@ -0,0 +1,46 @@ +_playlist = Playlist::find($playlistId); + $this->_track = Track::find($trackId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $user != null && $this->_playlist && $this->_track && $this->_playlist->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $songIndex = $this->_playlist->tracks()->count() + 1; + $this->_playlist->tracks()->attach($this->_track, ['position' => $songIndex]); + + Playlist::whereId($this->_playlist->id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM playlist_track WHERE playlist_id = ' . $this->_playlist->id . ')') + ]); + + return CommandResponse::succeed(['message' => 'Track added!']); + } +} \ No newline at end of file diff --git a/app/Commands/CommandBase.php b/app/Commands/CommandBase.php new file mode 100644 index 00000000..850f571e --- /dev/null +++ b/app/Commands/CommandBase.php @@ -0,0 +1,33 @@ +_listeners[] = $listener; + } + + protected function notify($message, $progress) + { + foreach ($this->_listeners as $listener) { + $listener($message, $progress); + } + } + + /** + * @return bool + */ + public function authorize() + { + return true; + } + + /** + * @return CommandResponse + */ + public abstract function execute(); +} \ No newline at end of file diff --git a/app/Commands/CommandResponse.php b/app/Commands/CommandResponse.php new file mode 100644 index 00000000..b1616e74 --- /dev/null +++ b/app/Commands/CommandResponse.php @@ -0,0 +1,58 @@ +_didFail = true; + $response->_validator = $validator; + + return $response; + } + + public static function succeed($response = null) + { + $cmdResponse = new CommandResponse(); + $cmdResponse->_didFail = false; + $cmdResponse->_response = $response; + + return $cmdResponse; + } + + private $_validator; + private $_response; + private $_didFail; + + private function __construct() + { + } + + /** + * @return bool + */ + public function didFail() + { + return $this->_didFail; + } + + /** + * @return mixed + */ + public function getResponse() + { + return $this->_response; + } + + /** + * @return Validator + */ + public function getValidator() + { + return $this->_validator; + } +} \ No newline at end of file diff --git a/app/Commands/CreateAlbumCommand.php b/app/Commands/CreateAlbumCommand.php new file mode 100644 index 00000000..244fb686 --- /dev/null +++ b/app/Commands/CreateAlbumCommand.php @@ -0,0 +1,72 @@ +_input = $input; + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'title' => 'required|min:3|max:50', + 'cover' => 'image|mimes:png|min_width:350|min_height:350', + 'cover_id' => 'exists:images,id', + 'track_ids' => 'exists:tracks,id' + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $album = new Album(); + $album->user_id = Auth::user()->id; + $album->title = $this->_input['title']; + $album->description = $this->_input['description']; + + if (isset($this->_input['cover_id'])) { + $album->cover_id = $this->_input['cover_id']; + } else { + if (isset($this->_input['cover'])) { + $cover = $this->_input['cover']; + $album->cover_id = Image::upload($cover, Auth::user())->id; + } else { + if (isset($this->_input['remove_cover']) && $this->_input['remove_cover'] == 'true') { + $album->cover_id = null; + } + } + } + + $trackIds = explode(',', $this->_input['track_ids']); + $album->save(); + $album->syncTrackIds($trackIds); + + return CommandResponse::succeed(['id' => $album->id]); + } +} \ No newline at end of file diff --git a/app/Commands/CreateCommentCommand.php b/app/Commands/CreateCommentCommand.php new file mode 100644 index 00000000..83440a87 --- /dev/null +++ b/app/Commands/CreateCommentCommand.php @@ -0,0 +1,79 @@ +_input = $input; + $this->_id = $id; + $this->_type = $type; + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'content' => 'required', + 'track_id' => 'exists:tracks,id', + 'albums_id' => 'exists:albums,id', + 'playlist_id' => 'exists:playlists,id', + 'profile_id' => 'exists:users,id', + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $comment = new Comment(); + $comment->user_id = Auth::user()->id; + $comment->content = $this->_input['content']; + + if ($this->_type == 'track') { + $column = 'track_id'; + } else { + if ($this->_type == 'user') { + $column = 'profile_id'; + } else { + if ($this->_type == 'album') { + $column = 'album_id'; + } else { + if ($this->_type == 'playlist') { + $column = 'playlist_id'; + } else { + App::abort(500); + } + } + } + } + + $comment->$column = $this->_id; + $comment->save(); + + return CommandResponse::succeed(Comment::mapPublic($comment)); + } +} \ No newline at end of file diff --git a/app/Commands/CreatePlaylistCommand.php b/app/Commands/CreatePlaylistCommand.php new file mode 100644 index 00000000..267420bf --- /dev/null +++ b/app/Commands/CreatePlaylistCommand.php @@ -0,0 +1,69 @@ +_input = $input; + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'title' => 'required|min:3|max:50', + 'is_public' => 'required', + 'is_pinned' => 'required' + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $playlist = new Playlist(); + $playlist->user_id = Auth::user()->id; + $playlist->title = $this->_input['title']; + $playlist->description = $this->_input['description']; + $playlist->is_public = $this->_input['is_public'] == 'true'; + + $playlist->save(); + + if ($this->_input['is_pinned'] == 'true') { + $playlist->pin(Auth::user()->id); + } + + return CommandResponse::succeed([ + 'id' => $playlist->id, + 'title' => $playlist->title, + 'slug' => $playlist->slug, + 'created_at' => $playlist->created_at, + 'description' => $playlist->description, + 'url' => $playlist->url, + 'is_pinned' => $this->_input['is_pinned'] == 'true', + 'is_public' => $this->_input['is_public'] == 'true' + ]); + } +} \ No newline at end of file diff --git a/app/Commands/DeleteAlbumCommand.php b/app/Commands/DeleteAlbumCommand.php new file mode 100644 index 00000000..79ee865f --- /dev/null +++ b/app/Commands/DeleteAlbumCommand.php @@ -0,0 +1,46 @@ +_albumId = $albumId; + $this->_album = ALbum::find($albumId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $this->_album && $user != null && $this->_album->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + foreach ($this->_album->tracks as $track) { + $track->album_id = null; + $track->track_number = null; + $track->updateTags(); + $track->save(); + } + + $this->_album->delete(); + + return CommandResponse::succeed(); + } +} \ No newline at end of file diff --git a/app/Commands/DeletePlaylistCommand.php b/app/Commands/DeletePlaylistCommand.php new file mode 100644 index 00000000..f06821a8 --- /dev/null +++ b/app/Commands/DeletePlaylistCommand.php @@ -0,0 +1,43 @@ +_playlistId = $playlistId; + $this->_playlist = Playlist::find($playlistId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $this->_playlist && $user != null && $this->_playlist->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + foreach ($this->_playlist->pins as $pin) { + $pin->delete(); + } + + $this->_playlist->delete(); + + return CommandResponse::succeed(); + } +} \ No newline at end of file diff --git a/app/Commands/DeleteTrackCommand.php b/app/Commands/DeleteTrackCommand.php new file mode 100644 index 00000000..bf0ebcff --- /dev/null +++ b/app/Commands/DeleteTrackCommand.php @@ -0,0 +1,46 @@ +_trackId = $trackId; + $this->_track = Track::find($trackId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $this->_track && $user != null && $this->_track->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + if ($this->_track->album_id != null) { + $album = $this->_track->album; + $this->_track->album_id = null; + $this->_track->track_number = null; + $this->_track->delete(); + $album->updateTrackNumbers(); + } else { + $this->_track->delete(); + } + + return CommandResponse::succeed(); + } +} \ No newline at end of file diff --git a/app/Commands/EditAlbumCommand.php b/app/Commands/EditAlbumCommand.php new file mode 100644 index 00000000..b2c96ba1 --- /dev/null +++ b/app/Commands/EditAlbumCommand.php @@ -0,0 +1,79 @@ +_input = $input; + $this->_albumId = $trackId; + $this->_album = Album::find($trackId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $this->_album && $user != null && $this->_album->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'title' => 'required|min:3|max:50', + 'cover' => 'image|mimes:png|min_width:350|min_height:350', + 'cover_id' => 'exists:images,id', + 'track_ids' => 'exists:tracks,id' + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $this->_album->title = $this->_input['title']; + $this->_album->description = $this->_input['description']; + + if (isset($this->_input['cover_id'])) { + $this->_album->cover_id = $this->_input['cover_id']; + } else { + if (isset($this->_input['cover'])) { + $cover = $this->_input['cover']; + $this->_album->cover_id = Image::upload($cover, Auth::user())->id; + } else { + if (isset($this->_input['remove_cover']) && $this->_input['remove_cover'] == 'true') { + $this->_album->cover_id = null; + } + } + } + + $trackIds = explode(',', $this->_input['track_ids']); + $this->_album->syncTrackIds($trackIds); + $this->_album->save(); + + Album::whereId($this->_album->id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $this->_album->id . ')') + ]); + + return CommandResponse::succeed(['real_cover_url' => $this->_album->getCoverUrl(Image::NORMAL)]); + } +} \ No newline at end of file diff --git a/app/Commands/EditPlaylistCommand.php b/app/Commands/EditPlaylistCommand.php new file mode 100644 index 00000000..46f7d4ef --- /dev/null +++ b/app/Commands/EditPlaylistCommand.php @@ -0,0 +1,77 @@ +_input = $input; + $this->_playlistId = $playlistId; + $this->_playlist = Playlist::find($playlistId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $this->_playlist && $user != null && $this->_playlist->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'title' => 'required|min:3|max:50', + 'is_public' => 'required', + 'is_pinned' => 'required' + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $this->_playlist->title = $this->_input['title']; + $this->_playlist->description = $this->_input['description']; + $this->_playlist->is_public = $this->_input['is_public'] == 'true'; + + $this->_playlist->save(); + + $pin = PinnedPlaylist::whereUserId(Auth::user()->id)->wherePlaylistId($this->_playlistId)->first(); + if ($pin && $this->_input['is_pinned'] != 'true') { + $pin->delete(); + } else { + if (!$pin && $this->_input['is_pinned'] == 'true') { + $this->_playlist->pin(Auth::user()->id); + } + } + + return CommandResponse::succeed([ + 'id' => $this->_playlist->id, + 'title' => $this->_playlist->title, + 'slug' => $this->_playlist->slug, + 'created_at' => $this->_playlist->created_at, + 'description' => $this->_playlist->description, + 'url' => $this->_playlist->url, + 'is_pinned' => $this->_input['is_pinned'] == 'true', + 'is_public' => $this->_input['is_public'] == 'true' + ]); + } +} \ No newline at end of file diff --git a/app/Commands/EditTrackCommand.php b/app/Commands/EditTrackCommand.php new file mode 100644 index 00000000..a509e03c --- /dev/null +++ b/app/Commands/EditTrackCommand.php @@ -0,0 +1,161 @@ +_trackId = $trackId; + $this->_track = Track::find($trackId); + $this->_input = $input; + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $this->_track && $user != null && $this->_track->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $isVocal = (isset($this->_input['is_vocal']) && $this->_input['is_vocal'] == 'true') ? true : false; + + $rules = [ + 'title' => 'required|min:3|max:80', + 'released_at' => 'before:' . (date('Y-m-d', + time() + (86400 * 2))) . (isset($this->_input['released_at']) && $this->_input['released_at'] != "" ? '|date' : ''), + 'license_id' => 'required|exists:licenses,id', + 'genre_id' => 'required|exists:genres,id', + 'cover' => 'image|mimes:png|min_width:350|min_height:350', + 'track_type_id' => 'required|exists:track_types,id', + 'songs' => 'required_when:track_type,2|exists:songs,id', + 'cover_id' => 'exists:images,id', + 'album_id' => 'exists:albums,id' + ]; + + if ($isVocal) { + $rules['lyrics'] = 'required'; + } + + if (isset($this->_input['track_type_id']) && $this->_input['track_type_id'] == 2) { + $rules['show_song_ids'] = 'required|exists:show_songs,id'; + } + + $validator = \Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $track = $this->_track; + $track->title = $this->_input['title']; + $track->released_at = isset($this->_input['released_at']) && $this->_input['released_at'] != "" ? strtotime($this->_input['released_at']) : null; + $track->description = isset($this->_input['description']) ? $this->_input['description'] : ''; + $track->lyrics = isset($this->_input['lyrics']) ? $this->_input['lyrics'] : ''; + $track->license_id = $this->_input['license_id']; + $track->genre_id = $this->_input['genre_id']; + $track->track_type_id = $this->_input['track_type_id']; + $track->is_explicit = $this->_input['is_explicit'] == 'true'; + $track->is_downloadable = $this->_input['is_downloadable'] == 'true'; + $track->is_listed = $this->_input['is_listed'] == 'true'; + $track->is_vocal = $isVocal; + + if (isset($this->_input['album_id']) && strlen(trim($this->_input['album_id']))) { + if ($track->album_id != null && $track->album_id != $this->_input['album_id']) { + $this->removeTrackFromAlbum($track); + } + + if ($track->album_id != $this->_input['album_id']) { + $album = Album::find($this->_input['album_id']); + $track->track_number = $album->tracks()->count() + 1; + $track->album_id = $this->_input['album_id']; + + Album::whereId($album->id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $album->id . ')') + ]); + } + } else { + if ($track->album_id != null) { + $this->removeTrackFromAlbum($track); + } + + $track->track_number = null; + $track->album_id = null; + } + + if ($track->track_type_id == 2) { + $track->showSongs()->sync(explode(',', $this->_input['show_song_ids'])); + } else { + $track->showSongs()->sync([]); + } + + if ($track->published_at == null) { + $track->published_at = new \DateTime(); + + DB::table('tracks')->whereUserId($track->user_id)->update(['is_latest' => false]); + $track->is_latest = true; + } + + if (isset($this->_input['cover_id'])) { + $track->cover_id = $this->_input['cover_id']; + } else { + if (isset($this->_input['cover'])) { + $cover = $this->_input['cover']; + $track->cover_id = Image::upload($cover, Auth::user())->id; + } else { + if ($this->_input['remove_cover'] == 'true') { + $track->cover_id = null; + } + } + } + + $track->updateTags(); + $track->save(); + + User::whereId($this->_track->user_id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE deleted_at IS NULL AND published_at IS NOT NULL AND user_id = ' . $this->_track->user_id . ')') + ]); + + return CommandResponse::succeed(['real_cover_url' => $track->getCoverUrl(Image::NORMAL)]); + } + + private function removeTrackFromAlbum($track) + { + $album = $track->album; + $index = 0; + + foreach ($album->tracks as $track) { + if ($track->id == $this->_trackId) { + continue; + } + + $track->track_number = ++$index; + $track->updateTags(); + $track->save(); + } + + Album::whereId($album->id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $album->id . ')') + ]); + } +} \ No newline at end of file diff --git a/app/Commands/SaveAccountSettingsCommand.php b/app/Commands/SaveAccountSettingsCommand.php new file mode 100644 index 00000000..830d3834 --- /dev/null +++ b/app/Commands/SaveAccountSettingsCommand.php @@ -0,0 +1,88 @@ +_input = $input; + } + + /** + * @return bool + */ + public function authorize() + { + return Auth::user() != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $user = Auth::user(); + + $rules = [ + 'display_name' => 'required|min:3|max:26', + 'bio' => 'textarea_length:250' + ]; + + if ($this->_input['sync_names'] == 'true') { + $this->_input['display_name'] = $user->mlpforums_name; + } + + if ($this->_input['uses_gravatar'] == 'true') { + $rules['gravatar'] = 'email'; + } else { + $rules['avatar'] = 'image|mimes:png|min_width:350|min_height:350'; + $rules['avatar_id'] = 'exists:images,id'; + } + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + if ($this->_input['uses_gravatar'] != 'true') { + if ($user->avatar_id == null && !isset($this->_input['avatar']) && !isset($this->_input['avatar_id'])) { + $validator->messages()->add('avatar', + 'You must upload or select an avatar if you are not using gravatar!'); + + return CommandResponse::fail($validator); + } + } + + $user->bio = $this->_input['bio']; + $user->display_name = $this->_input['display_name']; + $user->sync_names = $this->_input['sync_names'] == 'true'; + $user->can_see_explicit_content = $this->_input['can_see_explicit_content'] == 'true'; + $user->uses_gravatar = $this->_input['uses_gravatar'] == 'true'; + + if ($user->uses_gravatar) { + $user->avatar_id = null; + $user->gravatar = $this->_input['gravatar']; + } else { + if (isset($this->_input['avatar_id'])) { + $user->avatar_id = $this->_input['avatar_id']; + } else { + if (isset($this->_input['avatar'])) { + $user->avatar_id = Image::upload($this->_input['avatar'], $user)->id; + } + } + } + + $user->save(); + + return CommandResponse::succeed(); + } +} \ No newline at end of file diff --git a/app/Commands/ToggleFavouriteCommand.php b/app/Commands/ToggleFavouriteCommand.php new file mode 100644 index 00000000..54bcb4f0 --- /dev/null +++ b/app/Commands/ToggleFavouriteCommand.php @@ -0,0 +1,75 @@ +_resourceId = $resourceId; + $this->_resourceType = $resourceType; + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $typeId = $this->_resourceType . '_id'; + $existing = Favourite::where($typeId, '=', $this->_resourceId)->whereUserId(Auth::user()->id)->first(); + $isFavourited = false; + + if ($existing) { + $existing->delete(); + } else { + $fav = new Favourite(); + $fav->$typeId = $this->_resourceId; + $fav->user_id = Auth::user()->id; + $fav->created_at = time(); + $fav->save(); + $isFavourited = true; + } + + $resourceUser = ResourceUser::get(Auth::user()->id, $this->_resourceType, $this->_resourceId); + $resourceUser->is_favourited = $isFavourited; + $resourceUser->save(); + + $resourceTable = $this->_resourceType . 's'; + + // We do this to prevent a race condition. Sure I could simply increment the count columns and re-save back to the db + // but that would require an additional SELECT and the operation would be non-atomic. If two log items are created + // for the same resource at the same time, the cached values will still be correct with this method. + + DB::table($resourceTable)->whereId($this->_resourceId)->update([ + 'favourite_count' => + DB::raw('( + SELECT + COUNT(id) + FROM + favourites + WHERE ' . + $typeId . ' = ' . $this->_resourceId . ')') + ]); + + return CommandResponse::succeed(['is_favourited' => $isFavourited]); + } +} \ No newline at end of file diff --git a/app/Commands/ToggleFollowingCommand.php b/app/Commands/ToggleFollowingCommand.php new file mode 100644 index 00000000..10c07f6e --- /dev/null +++ b/app/Commands/ToggleFollowingCommand.php @@ -0,0 +1,57 @@ +_resourceId = $resourceId; + $this->_resourceType = $resourceType; + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $typeId = $this->_resourceType . '_id'; + $existing = Follower::where($typeId, '=', $this->_resourceId)->whereUserId(Auth::user()->id)->first(); + $isFollowed = false; + + if ($existing) { + $existing->delete(); + } else { + $follow = new Follower(); + $follow->$typeId = $this->_resourceId; + $follow->user_id = Auth::user()->id; + $follow->created_at = time(); + $follow->save(); + $isFollowed = true; + } + + $resourceUser = ResourceUser::get(Auth::user()->id, $this->_resourceType, $this->_resourceId); + $resourceUser->is_followed = $isFollowed; + $resourceUser->save(); + + return CommandResponse::succeed(['is_followed' => $isFollowed]); + } +} \ No newline at end of file diff --git a/app/Commands/UploadTrackCommand.php b/app/Commands/UploadTrackCommand.php new file mode 100644 index 00000000..d91e9b97 --- /dev/null +++ b/app/Commands/UploadTrackCommand.php @@ -0,0 +1,96 @@ +getPathname()); + + $validator = \Validator::make(['track' => $trackFile], [ + 'track' => + 'required|' + . 'audio_format:flac,pcm_s16le ([1][0][0][0] / 0x0001),pcm_s16be,adpcm_ms ([2][0][0][0] / 0x0002),pcm_s24le ([1][0][0][0] / 0x0001),pcm_s24be,pcm_f32le ([3][0][0][0] / 0x0003),pcm_f32be (fl32 / 0x32336C66)|' + . 'audio_channels:1,2|' + . 'sample_rate:44100,48000,88200,96000,176400,192000|' + . 'min_duration:30' + ]); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $track = new Track(); + + try { + $track->user_id = $user->id; + $track->title = pathinfo($trackFile->getClientOriginalName(), PATHINFO_FILENAME); + $track->duration = $audio->getDuration(); + $track->is_listed = true; + + $track->save(); + + $destination = $track->getDirectory(); + $track->ensureDirectoryExists(); + + $source = $trackFile->getPathname(); + $index = 0; + + $processes = []; + + foreach (Track::$Formats as $name => $format) { + $trackFile = new TrackFile(); + $trackFile->is_master = $name === 'FLAC' ? true : false; + $trackFile->format = $name; + $track->trackFiles()->save($trackFile); + + $target = $destination . '/' . $trackFile->getFilename(); //$track->getFilenameFor($name); + + $command = $format['command']; + $command = str_replace('{$source}', '"' . $source . '"', $command); + $command = str_replace('{$target}', '"' . $target . '"', $command); + + Log::info('Encoding ' . $track->id . ' into ' . $target); + $this->notify('Encoding ' . $name, $index / count(Track::$Formats) * 100); + + $pipes = []; + $proc = proc_open($command, [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'a']], $pipes); + $processes[] = $proc; + } + + foreach ($processes as $proc) { + proc_close($proc); + } + + $track->updateTags(); + + } catch (\Exception $e) { + $track->delete(); + throw $e; + } + + return CommandResponse::succeed([ + 'id' => $track->id, + 'name' => $track->name + ]); + } +} \ No newline at end of file