2016-12-17 16:59:59 +01:00
< ? php
namespace App\Services ;
2017-01-06 09:40:27 +01:00
use App\AlternativeTitle ;
2017-01-25 14:44:51 +01:00
use App\Services\Models\EpisodeService ;
2017-01-23 22:26:04 +01:00
use App\Services\Models\ItemService ;
2017-01-06 13:00:18 +01:00
use App\Setting ;
use Carbon\Carbon ;
2017-01-31 10:03:58 +01:00
use Illuminate\Support\Facades\DB ;
use Symfony\Component\HttpFoundation\Response ;
2016-12-17 16:59:59 +01:00
class FileParser {
2017-01-25 14:44:51 +01:00
const ADDED = 'added' ;
const REMOVED = 'removed' ;
2017-01-27 16:06:18 +01:00
const UPDATED = 'updated' ;
const SUPPORTED_FIELDS = [ 'src' , 'subtitles' ];
2017-01-25 14:44:51 +01:00
private $itemService ;
private $episodeService ;
2017-01-06 09:40:27 +01:00
private $tmdb ;
private $alternativeTitle ;
private $itemCategory ;
2016-12-17 16:59:59 +01:00
2017-01-23 22:26:04 +01:00
public function __construct (
2017-01-25 14:44:51 +01:00
ItemService $itemService ,
EpisodeService $episodeService ,
2017-01-23 22:26:04 +01:00
TMDB $tmdb ,
AlternativeTitle $alternativeTitle
){
2017-01-25 14:44:51 +01:00
$this -> itemService = $itemService ;
$this -> episodeService = $episodeService ;
2017-01-06 09:40:27 +01:00
$this -> tmdb = $tmdb ;
$this -> alternativeTitle = $alternativeTitle ;
2016-12-17 16:59:59 +01:00
}
2017-01-06 09:40:27 +01:00
/**
* Make a request to flox - file - parser and get local files data .
*
* @ return array
*/
public function fetch ()
2016-12-17 16:59:59 +01:00
{
2017-01-27 16:06:18 +01:00
return json_decode ( file_get_contents ( base_path ( 'tests/fixtures/fp/all.json' )));
2016-12-17 16:59:59 +01:00
}
2017-01-06 09:40:27 +01:00
/**
2017-01-25 14:44:51 +01:00
* Loop over all local files .
2017-01-06 09:40:27 +01:00
*
* @ param $files
2017-01-31 10:03:58 +01:00
* @ return \Illuminate\Http\JsonResponse
2017-01-06 09:40:27 +01:00
*/
2017-01-25 14:44:51 +01:00
public function updateDatabase ( $files )
2016-12-17 16:59:59 +01:00
{
2017-01-31 10:03:58 +01:00
DB :: beginTransaction ();
$this -> updateTimestamp ();
2017-01-06 09:40:27 +01:00
foreach ( $files as $type => $items ) {
$this -> itemCategory = $type ;
2016-12-17 16:59:59 +01:00
2017-01-06 09:40:27 +01:00
foreach ( $items as $item ) {
2017-01-31 10:03:58 +01:00
try {
$this -> handleStatus ( $item );
} catch ( \Exception $e ) {
return response () -> json ( $e -> getMessage (), Response :: HTTP_BAD_REQUEST );
}
2017-01-25 14:44:51 +01:00
}
}
2017-01-31 10:03:58 +01:00
DB :: commit ();
2017-01-25 14:44:51 +01:00
}
2017-01-06 09:40:27 +01:00
2017-01-25 14:44:51 +01:00
/**
* Check which status the file has .
2017-01-31 10:03:58 +01:00
* If we can ' t handle the status , throw an exception .
2017-01-25 14:44:51 +01:00
*
* @ param $item
* @ return bool | mixed | void
*/
private function handleStatus ( $item )
{
switch ( $item -> status ) {
case self :: ADDED :
2017-01-26 16:14:32 +01:00
return $this -> validateStore ( $item );
2017-01-27 16:06:18 +01:00
case self :: UPDATED :
return $this -> validateUpdate ( $item );
2017-01-25 14:44:51 +01:00
case self :: REMOVED :
2017-01-26 16:14:32 +01:00
return $this -> remove ( $item );
2017-01-31 10:03:58 +01:00
default :
return $this -> abortParser ( $item );
2017-01-25 14:44:51 +01:00
}
}
2017-01-06 09:40:27 +01:00
2017-01-25 14:44:51 +01:00
/**
2017-01-27 16:06:18 +01:00
* See if it can find the item in our database .
* Otherwise search in TMDb .
2017-01-25 14:44:51 +01:00
*
* @ param $item
* @ return bool | mixed
*/
2017-01-26 16:14:32 +01:00
private function validateStore ( $item )
2017-01-25 14:44:51 +01:00
{
// See if file is already in our database.
2017-01-27 16:06:18 +01:00
if ( $found = $this -> itemService -> findBy ( 'title' , $item -> name )) {
2017-01-26 16:14:32 +01:00
return $this -> store ( $item , $found -> tmdb_id );
2017-01-06 09:40:27 +01:00
}
2017-01-25 14:44:51 +01:00
// Otherwise make a new TMDb request.
2017-01-27 16:06:18 +01:00
return $this -> tmdbSearch ( $item );
}
/**
* See if it can find the item in our database .
* Otherwise search in TMDb and try to find them in our database again and update the fields .
*
* @ param $item
* @ return mixed
*/
private function validateUpdate ( $item )
{
// See if file is already in our database.
if ( $found = $this -> findItemBySrc ( $item )) {
return $this -> update ( $item , $found );
}
// Otherwise make a new TMDb request.
$this -> tmdbSearch ( $item );
return $this -> validateUpdate ( $item );
2017-01-06 09:40:27 +01:00
}
/**
* Make a new request to TMDb and check against the database . Otherwise create a new item .
*
* @ param $item
2017-01-23 22:26:04 +01:00
* @ return bool | mixed
2017-01-06 09:40:27 +01:00
*/
2017-01-27 16:06:18 +01:00
private function tmdbSearch ( $item )
2017-01-06 09:40:27 +01:00
{
2017-01-27 16:06:18 +01:00
$result = $this -> tmdb -> search ( $item -> name );
2017-01-06 09:40:27 +01:00
if ( ! $result ) {
return false ;
}
return $this -> findOrCreateItem ( $result [ 0 ], $item );
}
/**
* Check tmdb_id against the database or create a new item .
*
* @ param $firstResult
* @ param $item
2017-01-25 14:44:51 +01:00
* @ return mixed
2017-01-06 09:40:27 +01:00
*/
private function findOrCreateItem ( $firstResult , $item )
{
$tmdbId = $firstResult [ 'tmdb_id' ];
// Check against our database.
2017-01-25 14:44:51 +01:00
if ( $this -> itemService -> findBy ( 'tmdb_id' , $tmdbId )) {
2017-01-26 16:14:32 +01:00
return $this -> store ( $item , $tmdbId );
2017-01-06 09:40:27 +01:00
}
// Otherwise create a new item from the result.
2017-01-25 14:44:51 +01:00
$created = $this -> itemService -> create ( $firstResult );
2017-01-06 09:40:27 +01:00
2017-01-26 16:14:32 +01:00
return $this -> store ( $item , $created -> tmdb_id );
2017-01-06 09:40:27 +01:00
}
/**
2017-01-27 16:06:18 +01:00
* Store current supported fields from local file into our database .
2017-01-06 09:40:27 +01:00
*
* @ param $item
2017-01-25 14:44:51 +01:00
* @ param $tmdbId
2017-01-06 09:40:27 +01:00
* @ return mixed
*/
2017-01-26 16:14:32 +01:00
private function store ( $item , $tmdbId )
2017-01-06 09:40:27 +01:00
{
2017-01-27 16:06:18 +01:00
if ( $model = $this -> findItem ( $item , $tmdbId )) {
foreach ( self :: SUPPORTED_FIELDS as $field ) {
$model -> { $field } = $item -> { $field };
}
2017-01-25 14:44:51 +01:00
2017-01-27 16:06:18 +01:00
$model -> save ();
}
}
/**
* Iterate over all changed properties and update them in our database .
*
* @ param $item
* @ param $model
* @ return mixed
*/
private function update ( $item , $model )
{
foreach ( $item -> changed as $field => $value ) {
if ( in_array ( $field , self :: SUPPORTED_FIELDS )) {
$model -> { $field } = $value ;
}
2017-01-06 09:40:27 +01:00
}
2017-01-27 16:06:18 +01:00
return $model -> save ();
2017-01-06 09:40:27 +01:00
}
/**
2017-01-27 16:06:18 +01:00
* Reset all supported fields for local file from our database .
2017-01-06 09:40:27 +01:00
*
* @ param $item
2017-01-25 14:44:51 +01:00
* @ return mixed
2017-01-06 09:40:27 +01:00
*/
2017-01-26 16:14:32 +01:00
private function remove ( $item )
2017-01-25 14:44:51 +01:00
{
2017-01-27 16:06:18 +01:00
if ( $model = $this -> findItemBySrc ( $item )) {
foreach ( self :: SUPPORTED_FIELDS as $field ) {
$model -> { $field } = null ;
}
2017-01-25 14:44:51 +01:00
2017-01-27 16:06:18 +01:00
$model -> save ();
2017-01-25 14:44:51 +01:00
}
}
2017-01-31 10:03:58 +01:00
/**
* Cancel the complete fetch and make a rollback of fetched files .
*
* @ param $item
* @ throws \Exception
*/
private function abortParser ( $item )
{
DB :: rollBack ();
$itemAsString = json_encode ( $item );
throw new \Exception ( " Failed to parse file ' $item->name ' with status ' $item->status '. Please open an issue: https://github.com/devfake/flox/issues and include the following content: \n \n $itemAsString " );
}
2017-01-25 14:44:51 +01:00
/**
* @ param $item
* @ param $tmdbId
* @ return \Illuminate\Support\Collection | mixed
*/
private function findItem ( $item , $tmdbId )
2017-01-06 09:40:27 +01:00
{
if ( $this -> itemCategory == 'tv' ) {
2017-01-25 14:44:51 +01:00
return $this -> episodeService -> findBy ( 'episode' , $tmdbId , $item );
2017-01-06 09:40:27 +01:00
}
2017-01-25 14:44:51 +01:00
return $this -> itemService -> findBy ( 'tmdb_id' , $tmdbId );
}
/**
* @ param $item
* @ return \Illuminate\Support\Collection | mixed
*/
private function findItemBySrc ( $item )
{
if ( $this -> itemCategory == 'tv' ) {
return $this -> episodeService -> findBy ( 'src' , $item -> src );
}
return $this -> itemService -> findBy ( 'src' , $item -> src );
2016-12-17 16:59:59 +01:00
}
2017-01-06 13:00:18 +01:00
/**
* Update last time we fetched flox - file - parser .
*/
private function updateTimestamp ()
{
Setting :: first () -> update ([
'last_fetch_to_file_parser' => Carbon :: now (),
]);
}
2017-01-24 16:11:47 +01:00
}