Added Video
This commit is contained in:
parent
ec4c7ae3d1
commit
3012004901
@ -10,7 +10,7 @@ use App\Model\Photo;
|
||||
use App\Model\PhotoTag;
|
||||
use App\Model\Tag;
|
||||
|
||||
class Import extends Command
|
||||
class PhotoImport extends Command
|
||||
{
|
||||
use \App\Traits\Files;
|
||||
|
||||
@ -51,7 +51,7 @@ class Import extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$files = $this->getFiles(['dir'=>$this->option('dir'),'file'=>$this->option('file')]);
|
||||
$files = $this->getFiles(['dir'=>$this->option('dir'),'file'=>$this->option('file')],'photo');
|
||||
if (! count($files))
|
||||
exit;
|
||||
|
||||
@ -106,6 +106,12 @@ class Import extends Command
|
||||
$po->filename = $file;
|
||||
}
|
||||
|
||||
if (! is_readable($po->file_path()))
|
||||
{
|
||||
$this->warn(sprintf('Ignoring [%s], it is not readable',$po->file_path()));
|
||||
continue;
|
||||
}
|
||||
|
||||
$po->date_taken = strtotime($po->property('exif:DateTime') ? $po->property('exif:DateTime') : $po->property('exif:DateTimeOriginal'));
|
||||
$po->subsectime = $po->property('exif:SubSecTimeOriginal');
|
||||
|
@ -7,7 +7,7 @@ use Log;
|
||||
use Illuminate\Console\Command;
|
||||
use App\Model\Photo;
|
||||
|
||||
class Move extends Command
|
||||
class PhotoMove extends Command
|
||||
{
|
||||
use \App\Traits\Files;
|
||||
|
||||
@ -66,35 +66,35 @@ class Move extends Command
|
||||
$bar->setRedrawFrequency(100);
|
||||
|
||||
$po->chunk(1,function($photo) use ($bar) {
|
||||
while ($po = $photo->shift())
|
||||
while ($o = $photo->shift())
|
||||
{
|
||||
if (($x = $po->moveable()) === TRUE) {
|
||||
Log::info(sprintf('%s: Moving (%s)[%s]',__METHOD__,$po->id,$po->filename));
|
||||
if (($x = $o->moveable()) === TRUE) {
|
||||
Log::info(sprintf('%s: Moving (%s)[%s]',__METHOD__,$o->id,$o->filename));
|
||||
|
||||
if ($this->makeParentDir(dirname($po->file_path(FALSE,TRUE))) AND rename($po->file_path(),$po->file_path(FALSE,TRUE)))
|
||||
if ($this->makeParentDir(dirname($o->file_path(FALSE,TRUE))) AND rename($o->file_path(),$o->file_path(FALSE,TRUE)))
|
||||
{
|
||||
// Convert the path to a relative one.
|
||||
$po->filename = $po->file_path(TRUE,TRUE);
|
||||
$o->filename = $o->file_path(TRUE,TRUE);
|
||||
|
||||
// @todo If the DB update failed, move it back.
|
||||
if (! $po->save()) # AND ! rename($path,$po->file_path()))
|
||||
if (! $o->save()) # AND ! rename($path,$o->file_path()))
|
||||
{
|
||||
$this->error(sprintf('Save after rename failed for (%s)',$po->id));
|
||||
$this->error(sprintf('Save after rename failed for (%s)',$o->id));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->error(sprintf('Rename failed for (%s)',$po->id));
|
||||
$this->error(sprintf('Rename failed for (%s)',$o->id));
|
||||
continue;
|
||||
}
|
||||
|
||||
chmod($po->file_path(),0444);
|
||||
chmod($o->file_path(),0444);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($x > 0)
|
||||
$this->warn(sprintf('Unable to move (%s) [%s] to [%s], moveable returned (%s)',$po->id,$po->file_path(),$po->file_path(FALSE,TRUE),$x));
|
||||
$this->warn(sprintf('Unable to move (%s) [%s] to [%s], moveable returned (%s)',$o->id,$o->file_path(),$o->file_path(FALSE,TRUE),$x));
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use Log;
|
||||
use Illuminate\Console\Command;
|
||||
use App\Model\Photo;
|
||||
|
||||
class Update extends Command
|
||||
class PhotoUpdate extends Command
|
||||
{
|
||||
use \App\Traits\Files;
|
||||
|
198
app/Console/Commands/VideoImport.php
Normal file
198
app/Console/Commands/VideoImport.php
Normal file
@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Log;
|
||||
use Illuminate\Console\Command;
|
||||
use App\Model\Video;
|
||||
use App\Model\Tag;
|
||||
use App\Model\Person;
|
||||
|
||||
class VideoImport extends Command
|
||||
{
|
||||
|
||||
use \App\Traits\Files;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'video:import
|
||||
{--dir= : Directory to Parse}
|
||||
{--file= : File to Import}
|
||||
{--ignoredupe : Ignore duplicate files}
|
||||
{--deletedupe : Delete duplicate files}
|
||||
{--dumpid3 : Dump ID3 data}
|
||||
{--people= : People to reference in video}
|
||||
{--tags= : Add tag to video}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Import videos into the database';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$files = $this->getFiles(['dir'=>$this->option('dir'),'file'=>$this->option('file')],'video');
|
||||
if (! count($files))
|
||||
exit;
|
||||
|
||||
// Show a progress bar
|
||||
$bar = $this->output->createProgressBar(count($files));
|
||||
$bar->setFormat("%current%/%max% [%bar%] %percent:3s%% (%memory%) (%remaining%) ");
|
||||
|
||||
$tags = NULL;
|
||||
$t = $p = array();
|
||||
|
||||
// Tags
|
||||
if ($this->option('tags'))
|
||||
{
|
||||
$tags = explode(',',$this->option('tags'));
|
||||
$t = Tag::whereIn('tag',$tags)->pluck('id')->toArray();
|
||||
if (! $t OR count($t) != count($tags))
|
||||
{
|
||||
$this->error(sprintf('Tag [%s] dont exist',join('|',$tags)));
|
||||
abort(501);
|
||||
}
|
||||
}
|
||||
|
||||
// People
|
||||
if ($this->option('people'))
|
||||
{
|
||||
$tags = explode(',',$this->option('people'));
|
||||
$p = Person::whereIn('tag',$tags)->pluck('id')->toArray();
|
||||
if (! $p OR count($p) != count($tags))
|
||||
{
|
||||
$this->error(sprintf('People [%s] dont exist',join('|',$tags)));
|
||||
abort(501);
|
||||
}
|
||||
}
|
||||
|
||||
$c = 0;
|
||||
foreach ($files as $file)
|
||||
{
|
||||
$bar->advance();
|
||||
|
||||
if (preg_match('/@__thumb/',$file) OR preg_match('/\/._/',$file))
|
||||
{
|
||||
$this->warn(sprintf('Ignoring file [%s]',$file));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! in_array(strtolower(pathinfo($file,PATHINFO_EXTENSION)),config('video.import.accepted')))
|
||||
{
|
||||
$this->warn(sprintf('Ignoring [%s]',$file));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->option('verbose'))
|
||||
$this->info(sprintf('Processing file [%s]',$file));
|
||||
|
||||
$c++;
|
||||
|
||||
$vo = Video::where('filename',$file)->first();
|
||||
|
||||
if (is_null($vo))
|
||||
{
|
||||
$vo = new Video;
|
||||
$vo->filename = $file;
|
||||
}
|
||||
|
||||
if (! is_readable($vo->file_path()))
|
||||
{
|
||||
$this->warn(sprintf('Ignoring [%s], it is not readable',$vo->file_path()));
|
||||
continue;
|
||||
}
|
||||
|
||||
$vo->date_created = strtotime($vo->property('creationdate'));
|
||||
$vo->signature = $vo->property('signature');
|
||||
|
||||
$vo->make = $vo->property('make');
|
||||
$vo->model = $vo->property('model');
|
||||
|
||||
$vo->height = $vo->property('height');
|
||||
$vo->width = $vo->property('width');
|
||||
$vo->type = $vo->property('type');
|
||||
$vo->length = $vo->property('length');
|
||||
$vo->codec = $vo->property('codec');
|
||||
$vo->audiochannels = $vo->property('audiochannels');
|
||||
$vo->channelmode = $vo->property('channelmode');
|
||||
$vo->samplerate = $vo->property('samplerate');
|
||||
|
||||
$vo->gps_lat = $vo->property('gps_lat');
|
||||
$vo->gps_lon = $vo->property('gps_lon');
|
||||
$vo->gps_altitude = $vo->property('gps_altitude');
|
||||
|
||||
// If this is a duplicate
|
||||
$x = Video::whereIN('id',$vo->list_duplicate())->get();
|
||||
if (count($x)) {
|
||||
$skip = FALSE;
|
||||
|
||||
foreach ($x as $o) {
|
||||
// We'll only ignore based on the same signature.
|
||||
if ($vo->signature != $o->signature AND ! $vo->exists)
|
||||
continue;
|
||||
|
||||
if ($this->option('ignoredupe'))
|
||||
{
|
||||
$skip = TRUE;
|
||||
$this->warn(sprintf("Ignoring file [%s], it's the same as [%s] with id %s",$vo->file_path(),$o->filename,$o->id));
|
||||
break;
|
||||
|
||||
}
|
||||
elseif ($this->option('deletedupe') AND ($vo->filename != $o->filename))
|
||||
{
|
||||
$skip = TRUE;
|
||||
$this->error(sprintf("Deleting file [%s], it's the same as [%s] with id %s and signature [%s]\n",$vo->file_path(),$o->filename,$o->id,$vo->signature));
|
||||
unlink($vo->file_path());
|
||||
}
|
||||
}
|
||||
|
||||
if ($skip)
|
||||
continue;
|
||||
|
||||
$vo->duplicate = '1';
|
||||
$this->warn(sprintf('Video [%s] marked as a duplicate',$file));
|
||||
}
|
||||
|
||||
if ($vo->exists)
|
||||
$this->warn(sprintf('Video [%s] already in DB: %s',$file,$vo->id));
|
||||
|
||||
$vo->save();
|
||||
|
||||
if ($vo->wasRecentlyCreated)
|
||||
$this->info(sprintf('Video [%s] stored in DB: %s',$file,$vo->id));
|
||||
|
||||
// Record our people and tags
|
||||
if ($p)
|
||||
$vo->People()->sync($p);
|
||||
if ($t)
|
||||
$vo->Tags()->sync($t);
|
||||
|
||||
if ($this->option('dumpid3'))
|
||||
dd($vo->dump());
|
||||
}
|
||||
|
||||
$bar->finish();
|
||||
|
||||
return $this->info(sprintf('Video processed: %s',$c));
|
||||
}
|
||||
}
|
113
app/Console/Commands/VideoMove.php
Normal file
113
app/Console/Commands/VideoMove.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use DB;
|
||||
use Log;
|
||||
use Illuminate\Console\Command;
|
||||
use App\Model\Video;
|
||||
|
||||
class VideoMove extends Command
|
||||
{
|
||||
use \App\Traits\Files;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'video:move
|
||||
{--file= : Video File}
|
||||
{--id= : Video ID}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Moves Videos to their new location';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->option('file'))
|
||||
{
|
||||
$vo = Video::notRemove()->notDuplicate()->where('filename',Video::path($this->option('file')));
|
||||
}
|
||||
elseif ($this->option('id'))
|
||||
{
|
||||
$vo = Video::notRemove()->notDuplicate()->where('id',$this->option('id'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$vo = Video::notRemove()->notDuplicate();
|
||||
}
|
||||
|
||||
if (! $vo)
|
||||
exit;
|
||||
|
||||
// Show a progress bar
|
||||
$bar = $this->output->createProgressBar($vo->count());
|
||||
$bar->setFormat("%current%/%max% [%bar%] %percent:3s%% (%memory%) (%remaining%) ");
|
||||
$bar->setRedrawFrequency(100);
|
||||
|
||||
$vo->chunk(1,function($video) use ($bar) {
|
||||
while ($o = $video->shift())
|
||||
{
|
||||
if (($x = $o->moveable()) === TRUE) {
|
||||
Log::info(sprintf('%s: Moving (%s)[%s]',__METHOD__,$o->id,$o->filename));
|
||||
|
||||
$fs = $o->file_size();
|
||||
$ft = $o->file_date('m');
|
||||
if ($this->makeParentDir(dirname($o->file_path(FALSE,TRUE))) AND copy($o->file_path(),$o->file_path(FALSE,TRUE)))
|
||||
{
|
||||
// If the copy worked, remove the original.
|
||||
if (file_exists($o->file_path(FALSE,TRUE)) AND $fs === filesize($o->file_path(FALSE,TRUE)))
|
||||
{
|
||||
touch($o->file_path(FALSE,TRUE),$ft);
|
||||
unlink($o->file_path());
|
||||
}
|
||||
|
||||
// Convert the path to a relative one.
|
||||
$o->filename = $o->file_path(TRUE,TRUE);
|
||||
|
||||
// @todo If the DB update failed, move it back.
|
||||
if (! $o->save()) # AND ! rename($path,$o->file_path()))
|
||||
{
|
||||
$this->error(sprintf('Save after rename failed for (%s)',$o->id));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->error(sprintf('Rename failed for (%s)',$o->id));
|
||||
continue;
|
||||
}
|
||||
|
||||
chmod($o->file_path(),0444);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($x > 0)
|
||||
$this->warn(sprintf('Unable to move (%s) [%s] to [%s], moveable returned (%s)',$o->id,$o->file_path(),$o->file_path(FALSE,TRUE),$x));
|
||||
}
|
||||
}
|
||||
|
||||
$bar->advance();
|
||||
});
|
||||
}
|
||||
}
|
@ -13,9 +13,11 @@ class Kernel extends ConsoleKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
Commands\Import::class,
|
||||
Commands\Move::class,
|
||||
Commands\Update::class,
|
||||
Commands\PhotoImport::class,
|
||||
Commands\PhotoMove::class,
|
||||
Commands\PhotoUpdate::class,
|
||||
Commands\VideoImport::class,
|
||||
Commands\VideoMove::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
107
app/Http/Controllers/VideoController.php
Normal file
107
app/Http/Controllers/VideoController.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Http\Requests;
|
||||
use App\Model\Video;
|
||||
use App\Jobs\VideoDelete;
|
||||
|
||||
class VideoController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$po = Video::notRemove()->findOrFail($id);
|
||||
|
||||
if ($po)
|
||||
{
|
||||
$po->remove = TRUE;
|
||||
$po->save();
|
||||
}
|
||||
|
||||
return redirect()->action('VideoController@info',[$id]);
|
||||
}
|
||||
|
||||
//@todo
|
||||
public function deletes()
|
||||
{
|
||||
return view('video.deletereview',['videos'=>Video::where('remove',1)->paginate(2)]);
|
||||
}
|
||||
|
||||
//@todo
|
||||
public function deletesUpdate(Request $request)
|
||||
{
|
||||
foreach ($request->input('video') as $id)
|
||||
{
|
||||
$video = Video::findOrFail($id);
|
||||
|
||||
if ($video->remove AND $request->input('remove.'.$id))
|
||||
$this->dispatch((new VideoDelete($video))->onQueue('delete'));
|
||||
}
|
||||
|
||||
return redirect()->action('VideoController@deletes',$request->input('pagenext') ? '?page='.$request->input('pagenext') : NULL);
|
||||
}
|
||||
|
||||
//@todo
|
||||
public function duplicates($id=NULL)
|
||||
{
|
||||
return view('video.duplicates',['videos'=>is_null($id) ? Video::notRemove()->where('duplicate',1)->paginate(1) : Video::where('id',$id)->paginate(1)]);
|
||||
}
|
||||
|
||||
//@todo
|
||||
public function duplicatesUpdate(Request $request)
|
||||
{
|
||||
foreach ($request->input('video') as $id)
|
||||
{
|
||||
$po = Video::findOrFail($id);
|
||||
|
||||
// Set if duplicate
|
||||
$po->duplicate = $request->input('duplicate.'.$id) ? 1 : NULL;
|
||||
|
||||
// Set if flag
|
||||
$po->flag = $request->input('flag.'.$id) ? 1 : NULL;
|
||||
|
||||
// Set if delete
|
||||
$po->remove = $request->input('remove.'.$id) ? 1 : NULL;
|
||||
|
||||
$po->isDirty() AND $po->save();
|
||||
}
|
||||
|
||||
return redirect()->action('VideoController@duplicates','?page='.$request->input('page'));
|
||||
}
|
||||
public function info($id)
|
||||
{
|
||||
return view('video.view', ['video'=> Video::findOrFail($id)]);
|
||||
}
|
||||
|
||||
public function undelete($id)
|
||||
{
|
||||
$po = Video::findOrFail($id);
|
||||
|
||||
if ($po)
|
||||
{
|
||||
$po->remove = NULL;
|
||||
$po->save();
|
||||
}
|
||||
|
||||
return redirect()->action('VideoController@info',[$id]);
|
||||
}
|
||||
|
||||
//@todo
|
||||
public function view($id)
|
||||
{
|
||||
return response(Video::findOrFail($id)->image())->header('Content-Type','video/mov');
|
||||
}
|
||||
}
|
@ -19,12 +19,19 @@ Route::get('/', function () {
|
||||
|
||||
Route::auth();
|
||||
|
||||
Route::get('/deletes/{id?}', 'PhotoController@deletes')->where('id', '[0-9]+');;
|
||||
Route::get('/duplicates/{id?}', 'PhotoController@duplicates')->where('id', '[0-9]+');;
|
||||
Route::get('/info/{id}', 'PhotoController@info')->where('id', '[0-9]+');;
|
||||
Route::get('/thumbnail/{id}', 'PhotoController@thumbnail')->where('id', '[0-9]+');;
|
||||
Route::get('/view/{id}', 'PhotoController@view')->where('id', '[0-9]+');;
|
||||
Route::post('/delete/{id}', 'PhotoController@delete')->where('id', '[0-9]+');;
|
||||
Route::post('/duplicates', 'PhotoController@duplicatesUpdate');
|
||||
Route::post('/deletes', 'PhotoController@deletesUpdate');
|
||||
Route::post('/undelete/{id}', 'PhotoController@undelete')->where('id', '[0-9]+');;
|
||||
Route::get('/p/deletes/{id?}', 'PhotoController@deletes')->where('id', '[0-9]+');;
|
||||
Route::get('/v/deletes/{id?}', 'VideoController@deletes')->where('id', '[0-9]+');;
|
||||
Route::get('/p/duplicates/{id?}', 'PhotoController@duplicates')->where('id', '[0-9]+');;
|
||||
Route::get('/v/duplicates/{id?}', 'VideoController@duplicates')->where('id', '[0-9]+');;
|
||||
Route::get('/p/info/{id}', 'PhotoController@info')->where('id', '[0-9]+');;
|
||||
Route::get('/v/info/{id}', 'VideoController@info')->where('id', '[0-9]+');;
|
||||
Route::get('/p/thumbnail/{id}', 'PhotoController@thumbnail')->where('id', '[0-9]+');;
|
||||
Route::get('/p/view/{id}', 'PhotoController@view')->where('id', '[0-9]+');;
|
||||
Route::post('/p/delete/{id}', 'PhotoController@delete')->where('id', '[0-9]+');;
|
||||
Route::post('/v/delete/{id}', 'VideoController@delete')->where('id', '[0-9]+');;
|
||||
Route::post('/p/duplicates', 'PhotoController@duplicatesUpdate');
|
||||
Route::post('/v/duplicates', 'VideoController@duplicatesUpdate');
|
||||
Route::post('/p/deletes', 'PhotoController@deletesUpdate');
|
||||
Route::post('/v/deletes', 'VideoController@deletesUpdate');
|
||||
Route::post('/p/undelete/{id}', 'PhotoController@undelete')->where('id', '[0-9]+');;
|
||||
Route::post('/v/undelete/{id}', 'VideoController@undelete')->where('id', '[0-9]+');;
|
||||
|
60
app/Jobs/VideoDelete.php
Normal file
60
app/Jobs/VideoDelete.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Log;
|
||||
use App\Jobs\Job;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use App\Model\Video;
|
||||
|
||||
class VideoDelete extends Job implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, SerializesModels;
|
||||
|
||||
private $video;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Video $video)
|
||||
{
|
||||
$this->video = $video;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! $this->video->remove)
|
||||
{
|
||||
Log::warning(sprintf('%s: NOT Deleting [%s] not marked for deletion',__METHOD__,$this->video->file_path()));
|
||||
exit;
|
||||
}
|
||||
|
||||
// Remove tags;
|
||||
if ($this->video->Tags->count())
|
||||
$this->video->Tags()->detach();
|
||||
|
||||
// Remove People;
|
||||
if ($this->video->People->count())
|
||||
$this->video->People()->detach();
|
||||
|
||||
// Make sure our parent is writable
|
||||
if (! is_writable(dirname($this->video->file_path())))
|
||||
Log::warning(sprintf('%s: NOT Deleting [%s] parent directory not writable',__METHOD__,$this->video->file_path()));
|
||||
|
||||
// Perform delete
|
||||
if (file_exists($this->video->file_path()))
|
||||
unlink($this->video->file_path());
|
||||
|
||||
Log::warning(sprintf('%s: Deleted [%s]',__METHOD__,$this->video->file_path()));
|
||||
$this->video->delete();
|
||||
}
|
||||
}
|
39
app/Jobs/VideoMove.php
Normal file
39
app/Jobs/VideoMove.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Log;
|
||||
use App\Jobs\Job;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use App\Model\Video;
|
||||
use Artisan;
|
||||
|
||||
class VideoMove extends Job implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, SerializesModels;
|
||||
|
||||
private $video;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Video $video)
|
||||
{
|
||||
$this->video = $video;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Log::info(sprintf('%s: Moving [%s]',__METHOD__,$this->video->id));
|
||||
Artisan::call('video:move',['--id' => $this->video->id]);
|
||||
}
|
||||
}
|
@ -127,7 +127,8 @@ class Photo extends Model
|
||||
*/
|
||||
public function image()
|
||||
{
|
||||
$imo = $this->io();
|
||||
if (is_null($imo = $this->io()))
|
||||
return NULL;
|
||||
|
||||
if (array_key_exists('exif',$imo->getImageProfiles()))
|
||||
$imo->removeImageProfile('exif');
|
||||
@ -143,6 +144,9 @@ class Photo extends Model
|
||||
*/
|
||||
protected function io($attr=NULL)
|
||||
{
|
||||
if (! file_exists($this->file_path()) OR ! is_readable($this->file_path()))
|
||||
return NULL;
|
||||
|
||||
if (is_null($this->_io))
|
||||
$this->_io = new \Imagick($this->file_path());
|
||||
|
||||
@ -257,11 +261,6 @@ class Photo extends Model
|
||||
return $imo->getImageBlob();
|
||||
}
|
||||
|
||||
public static function path($path)
|
||||
{
|
||||
return preg_replace('/^\//','',str_replace(config('photo.dir'),'',$path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the previous photo
|
||||
*/
|
||||
@ -340,7 +339,7 @@ class Photo extends Model
|
||||
*/
|
||||
public function type($mime=FALSE)
|
||||
{
|
||||
return strtolower($mime ? File::mime_by_ext(pathinfo($this->filename,PATHINFO_EXTENSION)) : pathinfo($this->filename,PATHINFO_EXTENSION));
|
||||
return strtolower($mime ? 'image/jpeg' : pathinfo($this->filename,PATHINFO_EXTENSION));
|
||||
}
|
||||
|
||||
/**
|
||||
|
353
app/Model/Video.php
Normal file
353
app/Model/Video.php
Normal file
@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use DB;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Video extends Model
|
||||
{
|
||||
protected $table = 'videos';
|
||||
|
||||
// ID3 Object
|
||||
private $_o = NULL;
|
||||
|
||||
public function People()
|
||||
{
|
||||
return $this->belongsToMany('App\Model\Person');
|
||||
}
|
||||
|
||||
public function Tags()
|
||||
{
|
||||
return $this->belongsToMany('App\Model\Tag');
|
||||
}
|
||||
|
||||
/**
|
||||
* Photo's NOT pending removal.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function scopeNotRemove($query)
|
||||
{
|
||||
return $query->where(function($query)
|
||||
{
|
||||
$query->where('remove','!=',TRUE)
|
||||
->orWhere('remove','=',NULL);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Photo's NOT duplicate.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function scopeNotDuplicate($query)
|
||||
{
|
||||
return $query->where(function($query)
|
||||
{
|
||||
$query->where('duplicate','!=',TRUE)
|
||||
->orWhere('duplicate','=',NULL);
|
||||
});
|
||||
}
|
||||
|
||||
public function date_taken()
|
||||
{
|
||||
return $this->date_created ? date('Y-m-d H:i:s',$this->date_created) : 'UNKNOWN';
|
||||
}
|
||||
|
||||
public function dump()
|
||||
{
|
||||
return $this->_o->info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the date of the file
|
||||
*/
|
||||
public function file_date($type,$format=FALSE)
|
||||
{
|
||||
if (! is_readable($this->file_path()))
|
||||
return NULL;
|
||||
|
||||
switch ($type)
|
||||
{
|
||||
case 'a': $t = fileatime($this->file_path());
|
||||
break;
|
||||
case 'c': $t = filectime($this->file_path());
|
||||
break;
|
||||
case 'm': $t = filemtime($this->file_path());
|
||||
break;
|
||||
}
|
||||
|
||||
return $format ? date('d-m-Y H:i:s',$t) : $t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the new name for the image
|
||||
*/
|
||||
public function file_path($short=FALSE,$new=FALSE)
|
||||
{
|
||||
$file = $this->filename;
|
||||
|
||||
if ($new)
|
||||
$file = sprintf('%s.%s',((is_null($this->date_created) OR ! $this->date_created)
|
||||
? sprintf('UNKNOWN/%07s',$this->file_path_id())
|
||||
: date('Y/m/d-His',$this->date_created)),$this->type());
|
||||
|
||||
return (($short OR preg_match('/^\//',$file)) ? '' : config('video.dir').DIRECTORY_SEPARATOR).$file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a file path ID based on the id of the file
|
||||
*/
|
||||
public function file_path_id($sep=3,$depth=9)
|
||||
{
|
||||
return trim(chunk_split(sprintf("%0{$depth}s",$this->id),$sep,'/'),'/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the photo size
|
||||
*/
|
||||
public function file_size()
|
||||
{
|
||||
return (! is_readable($this->file_path())) ? NULL : filesize($this->file_path());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the GPS coordinates
|
||||
*/
|
||||
public function gps()
|
||||
{
|
||||
return ($this->gps_lat AND $this->gps_lon) ? sprintf('%s/%s',$this->gps_lat,$this->gps_lon) : 'UNKNOWN';
|
||||
}
|
||||
|
||||
public function isParentWritable($dir)
|
||||
{
|
||||
if (file_exists($dir) AND is_writable($dir) AND is_dir($dir))
|
||||
return TRUE;
|
||||
elseif ($dir == dirname($dir) OR file_exists($dir))
|
||||
return FALSE;
|
||||
else
|
||||
return ($this->isParentWritable(dirname($dir)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a file is moveable
|
||||
*
|
||||
* useID boolean Determine if the path is based on the the ID or date
|
||||
*/
|
||||
public function moveable()
|
||||
{
|
||||
// If the source and target are the same, we dont need to move it
|
||||
if ($this->file_path() == $this->file_path(FALSE,TRUE))
|
||||
return FALSE;
|
||||
|
||||
// If there is already a file in the target.
|
||||
// @todo If the target file is to be deleted, we could move this file
|
||||
if (file_exists($this->file_path(FALSE,TRUE)))
|
||||
return 1;
|
||||
|
||||
// Test if the source is readable
|
||||
if (! is_readable($this->file_path()))
|
||||
return 2;
|
||||
|
||||
// Test if the dir is writable (so we can remove the file)
|
||||
if (! $this->isParentWritable(dirname($this->file_path())))
|
||||
return 3;
|
||||
|
||||
// Test if the target dir is writable
|
||||
// @todo The target dir may not exist yet, so we should check that a parent exists and is writable.
|
||||
if (! $this->isParentWritable($this->file_path(FALSE,TRUE)))
|
||||
return 4;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the previous photo
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
$po = DB::table('videos');
|
||||
$po->where('id','>',$this->id);
|
||||
$po->orderby('id','ASC');
|
||||
return $po->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an Imagick object or attribute
|
||||
*
|
||||
*/
|
||||
protected function o($attr=NULL)
|
||||
{
|
||||
if (! $this->filename OR ! file_exists($this->file_path()) OR ! is_readable($this->file_path()))
|
||||
return FALSE;
|
||||
|
||||
if (is_null($this->_o))
|
||||
{
|
||||
$this->_o = new \getID3;
|
||||
$this->_o->analyze($this->file_path());
|
||||
$this->_o->getHashdata('sha1');
|
||||
}
|
||||
|
||||
return is_null($attr) ? $this->_o : (array_key_exists($attr,$this->_o->info) ? $this->_o->info[$attr] : NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the previous photo
|
||||
*/
|
||||
public function previous()
|
||||
{
|
||||
$po = DB::table('videos');
|
||||
$po->where('id','<',$this->id);
|
||||
$po->orderby('id','DEC');
|
||||
return $po->first();
|
||||
}
|
||||
|
||||
public function property($property)
|
||||
{
|
||||
if (! $this->o())
|
||||
return NULL;
|
||||
|
||||
switch ($property)
|
||||
{
|
||||
case 'creationdate':
|
||||
// Try creation_Data
|
||||
$x = array_get($this->_o->info,'quicktime.comments.creation_date.0');
|
||||
|
||||
// Try creation_Data
|
||||
if (is_null($x))
|
||||
$x = array_get($this->_o->info,'quicktime.comments.creationdate.0');
|
||||
|
||||
return $x;
|
||||
|
||||
case 'make': return array_get($this->_o->info,'quicktime.comments.make.0');
|
||||
case 'model': return array_get($this->_o->info,'quicktime.comments.model.0');
|
||||
case 'signature': return array_get($this->_o->info,'sha1_data');
|
||||
#case 'height': return $this->subatomsearch('quicktime.moov.subatoms',['trak','tkhd'],'height'); break;
|
||||
#case 'width': return $this->subatomsearch('quicktime.moov.subatoms',['trak','tkhd'],'width'); break;
|
||||
case 'height': return array_get($this->_o->info,'video.resolution_y');
|
||||
case 'width': return array_get($this->_o->info,'video.resolution_x');
|
||||
case 'length': return array_get($this->_o->info,'playtime_seconds');
|
||||
case 'type': return array_get($this->_o->info,'video.dataformat');
|
||||
case 'codec': return array_get($this->_o->info,'audio.codec');
|
||||
case 'audiochannels': return array_get($this->_o->info,'audio.channels');
|
||||
case 'samplerate': return array_get($this->_o->info,'audio.sample_rate');
|
||||
case 'channelmode': return array_get($this->_o->info,'audio.channelmode');
|
||||
case 'gps_lat': return array_get($this->_o->info,'quicktime.comments.gps_latitude.0');
|
||||
case 'gps_lon': return array_get($this->_o->info,'quicktime.comments.gps_longitude.0');
|
||||
case 'gps_altitude': return array_get($this->_o->info,'quicktime.comments.gps_altitude.0');
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Navigate through ID3 data to find the value.
|
||||
*/
|
||||
private function subatomsearch($atom,array $paths,$key,array $data=[]) {
|
||||
if (! $data AND is_null($data = array_get($this->_o->info,$atom)))
|
||||
{
|
||||
// Didnt find it.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
foreach ($paths as $path)
|
||||
{
|
||||
$found = FALSE;
|
||||
foreach ($data as $array)
|
||||
{
|
||||
if ($array['name'] === $path)
|
||||
{
|
||||
$found = TRUE;
|
||||
if ($path != last($paths))
|
||||
$data = $array['subatoms'];
|
||||
else
|
||||
$data = $array;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $found)
|
||||
break;
|
||||
}
|
||||
|
||||
return isset($data[$key]) ? $data[$key] : NULL;
|
||||
}
|
||||
|
||||
public function properties()
|
||||
{
|
||||
return $this->o() ? $this->_io->info : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the photo signature
|
||||
*/
|
||||
public function signature($short=FALSE)
|
||||
{
|
||||
return $short ? static::signaturetrim($this->signature) : $this->signature;
|
||||
}
|
||||
|
||||
public static function signaturetrim($signature,$chars=6)
|
||||
{
|
||||
return sprintf('%s...%s',substr($signature,0,$chars),substr($signature,-1*$chars));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the image should be moved
|
||||
*/
|
||||
public function shouldMove()
|
||||
{
|
||||
return ($this->filename != $this->file_path(TRUE,TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the extension of the image
|
||||
*/
|
||||
public function type($mime=FALSE)
|
||||
{
|
||||
return strtolower($mime ? File::mime_by_ext(pathinfo($this->filename,PATHINFO_EXTENSION)) : pathinfo($this->filename,PATHINFO_EXTENSION));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find duplicate images based on some attributes of the current image
|
||||
*/
|
||||
public function list_duplicate($includeme=FALSE)
|
||||
{
|
||||
$po = DB::table('videos');
|
||||
|
||||
if ($this->id AND ! $includeme)
|
||||
$po->where('id','!=',$this->id);
|
||||
|
||||
// Ignore photo's pending removal.
|
||||
if (! $includeme)
|
||||
$po->where(function($query)
|
||||
{
|
||||
$query->where('remove','!=',TRUE)
|
||||
->orWhere('remove','=',NULL);
|
||||
});
|
||||
|
||||
// Where the signature is the same
|
||||
$po->where(function($query)
|
||||
{
|
||||
$query->where('signature','=',$this->signature);
|
||||
|
||||
// Or they have the same time taken with the same camera
|
||||
if ($this->date_created AND ($this->model OR $this->make))
|
||||
{
|
||||
$query->orWhere(function($query)
|
||||
{
|
||||
$query->where('date_created','=',$this->date_created ? $this->date_created : NULL);
|
||||
|
||||
if (! is_null($this->model))
|
||||
$query->where('model','=',$this->model);
|
||||
|
||||
if (! is_null($this->make))
|
||||
$query->where('make','=',$this->make);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return $po->pluck('id');
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ use Log;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App\Model\Photo;
|
||||
use App\Jobs\PhotoMove;
|
||||
use App\Model\Video;
|
||||
use App\Jobs\VideoMove;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
@ -27,6 +29,15 @@ class AppServiceProvider extends ServiceProvider
|
||||
$this->dispatch((new PhotoMove($photo))->onQueue('move'));
|
||||
}
|
||||
});
|
||||
|
||||
// Any video saved, queue it to be moved.
|
||||
Video::saved(function($video) {
|
||||
if (! $video->duplicate AND ($x=$video->moveable()) === TRUE)
|
||||
{
|
||||
Log::info(sprintf('%s: Need to Move [%s]',__METHOD__,$video->id.'|'.serialize($x)));
|
||||
$this->dispatch((new VideoMove($video))->onQueue('move'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,41 +10,42 @@ trait Files
|
||||
/**
|
||||
* Get a list of files
|
||||
*/
|
||||
public function getFiles(array $option)
|
||||
public function getFiles(array $option,$type)
|
||||
{
|
||||
// Make sure we got a directory or a file to import
|
||||
if (is_null($option['file']) AND is_null($option['dir']))
|
||||
abort(500,'Missing filename, please use --file= OR --dir=');
|
||||
// Make sure we got a directory or a file to import
|
||||
if (is_null($option['file']) AND is_null($option['dir']))
|
||||
abort(500,'Missing filename, please use --file= OR --dir=');
|
||||
|
||||
Log::info(sprintf('%s: Processing: %s',__METHOD__,($option['file'] ? $option['file'] : $option['dir'])));
|
||||
Log::info(sprintf('%s: Processing: %s',__METHOD__,($option['file'] ? $option['file'] : $option['dir'])));
|
||||
|
||||
$files = [];
|
||||
$files = [];
|
||||
$dir = '';
|
||||
|
||||
if ($option['dir'])
|
||||
{
|
||||
// Remove our trailing slash from the directory.
|
||||
$dir = preg_replace('/\/$/','',$option['dir']);
|
||||
if ($option['dir'])
|
||||
{
|
||||
// Remove our trailing slash from the directory.
|
||||
$dir = preg_replace('/\/$/','',$option['dir']);
|
||||
|
||||
// Exclude . & .. from the path.
|
||||
$files = array_diff(scandir($dir),array('.','..'));
|
||||
// Exclude . & .. from the path.
|
||||
$files = array_diff(scandir($dir),array('.','..'));
|
||||
|
||||
}
|
||||
elseif ($option['file'])
|
||||
{
|
||||
$dir = dirname($option['file']);
|
||||
$files = array(basename($option['file']));
|
||||
}
|
||||
}
|
||||
elseif ($option['file'] AND file_exists($option['file']))
|
||||
{
|
||||
$dir = dirname($option['file']);
|
||||
$files = array(basename($option['file']));
|
||||
}
|
||||
|
||||
// Determine if our dir is releative to where we store data
|
||||
$dir = Photo::path($dir);
|
||||
// Determine if our dir is releative to where we store data
|
||||
$dir = static::path($dir,$type);
|
||||
|
||||
// Add our path
|
||||
if ($dir)
|
||||
array_walk($files,function(&$value,$key,$path='') {
|
||||
if ($path) {
|
||||
$value = sprintf('%s/%s',$path,$value);
|
||||
}
|
||||
},$dir);
|
||||
// Add our path
|
||||
if ($dir)
|
||||
array_walk($files,function(&$value,$key,$path='') {
|
||||
if ($path) {
|
||||
$value = sprintf('%s/%s',$path,$value);
|
||||
}
|
||||
},$dir);
|
||||
|
||||
return $files;
|
||||
}
|
||||
@ -58,5 +59,10 @@ trait Files
|
||||
return FALSE;
|
||||
else
|
||||
return is_writable(dirname($dir)) AND mkdir($dir);
|
||||
}
|
||||
}
|
||||
|
||||
public static function path($path,$type)
|
||||
{
|
||||
return (strpos($path,config($type.'.dir').'/') === 0) ? str_replace(config($type.'.dir').'/','',$path) : $path;
|
||||
}
|
||||
}
|
||||
|
132
composer.lock
generated
132
composer.lock
generated
@ -987,16 +987,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "382fc9ed852edabd6133e34f8549d7a7d99db115"
|
||||
"reference": "a7abb7153f6d1da47f87ec50274844e246b09d9f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/382fc9ed852edabd6133e34f8549d7a7d99db115",
|
||||
"reference": "382fc9ed852edabd6133e34f8549d7a7d99db115",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/a7abb7153f6d1da47f87ec50274844e246b09d9f",
|
||||
"reference": "a7abb7153f6d1da47f87ec50274844e246b09d9f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1043,20 +1043,20 @@
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 15:08:35"
|
||||
"time": "2016-06-29 07:02:21"
|
||||
},
|
||||
{
|
||||
"name": "symfony/debug",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/debug.git",
|
||||
"reference": "e67e1552dd7313df1cf6535cb606751899e0e727"
|
||||
"reference": "c54bc3539c3b87e86799533801e8ae0e971d78c2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/e67e1552dd7313df1cf6535cb606751899e0e727",
|
||||
"reference": "e67e1552dd7313df1cf6535cb606751899e0e727",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/c54bc3539c3b87e86799533801e8ae0e971d78c2",
|
||||
"reference": "c54bc3539c3b87e86799533801e8ae0e971d78c2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1100,20 +1100,20 @@
|
||||
],
|
||||
"description": "Symfony Debug Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 15:08:35"
|
||||
"time": "2016-06-29 05:40:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "f5b7563f67779c6d3d5370e23448e707c858df3e"
|
||||
"reference": "7f9839ede2070f53e7e2f0849b9bd14748c434c5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f5b7563f67779c6d3d5370e23448e707c858df3e",
|
||||
"reference": "f5b7563f67779c6d3d5370e23448e707c858df3e",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7f9839ede2070f53e7e2f0849b9bd14748c434c5",
|
||||
"reference": "7f9839ede2070f53e7e2f0849b9bd14748c434c5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1160,20 +1160,20 @@
|
||||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:42:41"
|
||||
"time": "2016-06-29 05:41:56"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "39e5f3d533d07b5416b9d7aad53a27f939d4f811"
|
||||
"reference": "3eb4e64c6145ef8b92adefb618a74ebdde9e3fe9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/39e5f3d533d07b5416b9d7aad53a27f939d4f811",
|
||||
"reference": "39e5f3d533d07b5416b9d7aad53a27f939d4f811",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/3eb4e64c6145ef8b92adefb618a74ebdde9e3fe9",
|
||||
"reference": "3eb4e64c6145ef8b92adefb618a74ebdde9e3fe9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1209,20 +1209,20 @@
|
||||
],
|
||||
"description": "Symfony Finder Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-05-13 18:03:36"
|
||||
"time": "2016-06-29 05:40:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-foundation.git",
|
||||
"reference": "d268a643884f85e91d6ba11ca68de96833f3f6e5"
|
||||
"reference": "1341139f906d295baa4f4abd55293d07e25a065a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/d268a643884f85e91d6ba11ca68de96833f3f6e5",
|
||||
"reference": "d268a643884f85e91d6ba11ca68de96833f3f6e5",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/1341139f906d295baa4f4abd55293d07e25a065a",
|
||||
"reference": "1341139f906d295baa4f4abd55293d07e25a065a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1262,20 +1262,20 @@
|
||||
],
|
||||
"description": "Symfony HttpFoundation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:33:26"
|
||||
"time": "2016-06-29 07:02:21"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-kernel",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-kernel.git",
|
||||
"reference": "97cc1c15e3406e7a2adf14ad6b0e41a04d4a6fc4"
|
||||
"reference": "177b63b2d50b63fa6d82ea41359ed9928cc7a1fb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/97cc1c15e3406e7a2adf14ad6b0e41a04d4a6fc4",
|
||||
"reference": "97cc1c15e3406e7a2adf14ad6b0e41a04d4a6fc4",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/177b63b2d50b63fa6d82ea41359ed9928cc7a1fb",
|
||||
"reference": "177b63b2d50b63fa6d82ea41359ed9928cc7a1fb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1283,7 +1283,7 @@
|
||||
"psr/log": "~1.0",
|
||||
"symfony/debug": "~2.8|~3.0",
|
||||
"symfony/event-dispatcher": "~2.8|~3.0",
|
||||
"symfony/http-foundation": "~2.8|~3.0"
|
||||
"symfony/http-foundation": "~2.8.8|~3.0.8|~3.1.2|~3.2"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<2.8"
|
||||
@ -1344,7 +1344,7 @@
|
||||
],
|
||||
"description": "Symfony HttpKernel Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 16:52:35"
|
||||
"time": "2016-06-30 16:30:17"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
@ -1515,16 +1515,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "bf6e2d1fa8b93fdd7cca6b684c0ea213cf0255dd"
|
||||
"reference": "d7cde1f9d94d87060204f863779389b61c382eeb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/bf6e2d1fa8b93fdd7cca6b684c0ea213cf0255dd",
|
||||
"reference": "bf6e2d1fa8b93fdd7cca6b684c0ea213cf0255dd",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/d7cde1f9d94d87060204f863779389b61c382eeb",
|
||||
"reference": "d7cde1f9d94d87060204f863779389b61c382eeb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1560,20 +1560,20 @@
|
||||
],
|
||||
"description": "Symfony Process Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:33:26"
|
||||
"time": "2016-06-29 05:40:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/routing",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/routing.git",
|
||||
"reference": "c780454838a1131adc756d737a4b4cc1d18f8c64"
|
||||
"reference": "9038984bd9c05ab07280121e9e10f61a7231457b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/c780454838a1131adc756d737a4b4cc1d18f8c64",
|
||||
"reference": "c780454838a1131adc756d737a4b4cc1d18f8c64",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/9038984bd9c05ab07280121e9e10f61a7231457b",
|
||||
"reference": "9038984bd9c05ab07280121e9e10f61a7231457b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1635,20 +1635,20 @@
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"time": "2016-05-30 06:58:27"
|
||||
"time": "2016-06-29 05:40:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "2b0aacaa613c0ec1ad8046f972d8abdcb19c1db7"
|
||||
"reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/2b0aacaa613c0ec1ad8046f972d8abdcb19c1db7",
|
||||
"reference": "2b0aacaa613c0ec1ad8046f972d8abdcb19c1db7",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/6bf844e1ee3c820c012386c10427a5c67bbefec8",
|
||||
"reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1699,20 +1699,20 @@
|
||||
],
|
||||
"description": "Symfony Translation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:33:26"
|
||||
"time": "2016-06-29 05:40:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-dumper.git",
|
||||
"reference": "d8bb851da153d97abe7c2b71a65dee19f324bcf7"
|
||||
"reference": "2f046e9a9d571f22cc8b26783564876713b06579"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/d8bb851da153d97abe7c2b71a65dee19f324bcf7",
|
||||
"reference": "d8bb851da153d97abe7c2b71a65dee19f324bcf7",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/2f046e9a9d571f22cc8b26783564876713b06579",
|
||||
"reference": "2f046e9a9d571f22cc8b26783564876713b06579",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1762,7 +1762,7 @@
|
||||
"debug",
|
||||
"dump"
|
||||
],
|
||||
"time": "2016-05-24 10:03:10"
|
||||
"time": "2016-06-29 05:40:00"
|
||||
},
|
||||
{
|
||||
"name": "vlucas/phpdotenv",
|
||||
@ -3383,16 +3383,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "e8a66c51bf65f188c02f8120c0748b2291d3a2d0"
|
||||
"reference": "b8999c1f33c224b2b66b38253f5e3a838d0d0115"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/e8a66c51bf65f188c02f8120c0748b2291d3a2d0",
|
||||
"reference": "e8a66c51bf65f188c02f8120c0748b2291d3a2d0",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/b8999c1f33c224b2b66b38253f5e3a838d0d0115",
|
||||
"reference": "b8999c1f33c224b2b66b38253f5e3a838d0d0115",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3432,20 +3432,20 @@
|
||||
],
|
||||
"description": "Symfony CssSelector Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:33:26"
|
||||
"time": "2016-06-29 05:40:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dom-crawler",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dom-crawler.git",
|
||||
"reference": "49b588841225b205700e5122fa01911cabada857"
|
||||
"reference": "62769e3409006b937bb333b29da8df9a8b262975"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/49b588841225b205700e5122fa01911cabada857",
|
||||
"reference": "49b588841225b205700e5122fa01911cabada857",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/62769e3409006b937bb333b29da8df9a8b262975",
|
||||
"reference": "62769e3409006b937bb333b29da8df9a8b262975",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3488,20 +3488,20 @@
|
||||
],
|
||||
"description": "Symfony DomCrawler Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-04-12 18:09:53"
|
||||
"time": "2016-06-29 05:40:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "c5a7e7fc273c758b92b85dcb9c46149ccda89623"
|
||||
"reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/c5a7e7fc273c758b92b85dcb9c46149ccda89623",
|
||||
"reference": "c5a7e7fc273c758b92b85dcb9c46149ccda89623",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/2884c26ce4c1d61aebf423a8b912950fe7c764de",
|
||||
"reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3537,7 +3537,7 @@
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-14 11:18:07"
|
||||
"time": "2016-06-29 05:41:56"
|
||||
},
|
||||
{
|
||||
"name": "way/generators",
|
||||
|
@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'dir'=>'/var/www/sites/co.dlcm.p/store',
|
||||
'dir'=>'/var/www/sites/co.dlcm.p/store/photos',
|
||||
'import'=>[
|
||||
'accepted'=>['jpg'],
|
||||
'log'=>'/tmp/import.log',
|
||||
],
|
||||
];
|
||||
|
9
config/video.php
Normal file
9
config/video.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'dir'=>'/var/www/sites/co.dlcm.p/store/video',
|
||||
'import'=>[
|
||||
'accepted'=>['m4v','mov','mp4','avi'],
|
||||
'log'=>'/tmp/import.log',
|
||||
],
|
||||
];
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class CreateVideosTable extends Migration {
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('videos', function(Blueprint $table)
|
||||
{
|
||||
$table->bigInteger('id', true);
|
||||
$table->timestamps();
|
||||
$table->integer('date_created')->nullable();
|
||||
$table->string('filename', 128);
|
||||
$table->string('signature', 64)->nullable();
|
||||
$table->string('make', 32)->nullable();
|
||||
$table->string('model', 32)->nullable();
|
||||
$table->string('type', 32)->nullable();
|
||||
$table->string('codec', 32)->nullable();
|
||||
$table->integer('audiochannels')->nullable();
|
||||
$table->string('channelmode', 16)->nullable();
|
||||
$table->float('samplerate', 10, 0)->nullable();
|
||||
$table->integer('height')->nullable();
|
||||
$table->integer('width')->nullable();
|
||||
$table->float('length')->nullable();
|
||||
$table->integer('orientation')->nullable();
|
||||
$table->float('gps_lat', 10, 0)->nullable();
|
||||
$table->float('gps_lon', 10, 0)->nullable();
|
||||
$table->float('gps_altitude', 10, 0)->nullable();
|
||||
$table->boolean('duplicate')->nullable();
|
||||
$table->boolean('remove')->nullable();
|
||||
$table->boolean('flag')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('videos');
|
||||
}
|
||||
|
||||
}
|
@ -47,8 +47,10 @@
|
||||
<div class="collapse navbar-collapse" id="app-navbar-collapse">
|
||||
<!-- Left Side Of Navbar -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="{{ url('/deletes') }}">Deletes</a></li>
|
||||
<li><a href="{{ url('/duplicates') }}">Duplicates</a></li>
|
||||
<li><a href="{{ url('/p/deletes') }}">Photo Deletes</a></li>
|
||||
<li><a href="{{ url('/p/duplicates') }}">Photo Duplicates</a></li>
|
||||
<li><a href="{{ url('/v/deletes') }}">Video Deletes</a></li>
|
||||
<li><a href="{{ url('/v/duplicates') }}">Video Duplicates</a></li>
|
||||
</ul>
|
||||
|
||||
<!-- Right Side Of Navbar -->
|
||||
|
@ -32,7 +32,7 @@
|
||||
<div class="text-center">{{ $photos->links() }}</div>
|
||||
<div class="panel-body">
|
||||
@if ($photos->count())
|
||||
<form action="{{ url('/deletes') }}" method="POST">
|
||||
<form action="{{ url('/p/deletes') }}" method="POST">
|
||||
<table class="table table-striped table-condensed table-hover">
|
||||
@foreach ($data as $k=>$v)
|
||||
<tr>
|
||||
@ -40,8 +40,8 @@
|
||||
@foreach ($photos as $o)
|
||||
<?php
|
||||
switch ($v) :
|
||||
case 'id': $x=$o->id; $y=sprintf('<input type="hidden" name="photo[]" value="%s"><a href="%s">%s</a>',$o->id,url('/info/'.$o->id),$o->id); break;
|
||||
case 'thumbnail': $x=md5($o->thumbnail); $y=sprintf('<a href="%s"><img src="%s" width="200px"></a>',url('/view/'.$o->id),url('/thumbnail/'.$o->id)); break;
|
||||
case 'id': $x=$o->id; $y=sprintf('<input type="hidden" name="photo[]" value="%s"><a href="%s">%s</a>',$o->id,url('/p/info/'.$o->id),$o->id); break;
|
||||
case 'thumbnail': $x=md5($o->thumbnail); $y=sprintf('<a href="%s"><img src="%s" width="200px"></a>',url('/p/view/'.$o->id),url('/p/thumbnail/'.$o->id)); break;
|
||||
case 'signature': $x=$y=$o->signature(TRUE); break;
|
||||
case 'datetaken': $x=$y=$o->date_taken(); break;
|
||||
case 'created': $x=$y=$o->file_date('c',TRUE); break;
|
||||
@ -53,7 +53,7 @@ case 'height':
|
||||
case 'orientation':
|
||||
case 'make':
|
||||
case 'model': $y=$o->{$v}; break;
|
||||
case 'duplicates': $x=$y='';foreach($o->list_duplicate() as $id) $y.=($y ? '|' : '').sprintf('<a href="%s">%s</a>',url('/info/'.$id),$id); break;
|
||||
case 'duplicates': $x=$y='';foreach($o->list_duplicate() as $id) $y.=($y ? '|' : '').sprintf('<a href="%s">%s</a>',url('/p/info/'.$id),$id); break;
|
||||
case 'flag':
|
||||
case 'remove':
|
||||
case 'duplicate': $y=sprintf('<input type="checkbox" name="%s[%s]" value="1"%s>',$v,$o->id,$o->{$v} ? ' checked="checked"' : ''); break;
|
||||
|
@ -46,7 +46,7 @@ function changed($k,$v,$l=0)
|
||||
|
||||
<div class="text-center">{{ $photos->links() }}</div>
|
||||
<div class="panel-body">
|
||||
<form action="{{ url('/duplicates') }}" method="POST">
|
||||
<form action="{{ url('/p/duplicates') }}" method="POST">
|
||||
<table class="table table-striped table-condensed table-hover">
|
||||
@foreach ($data as $k=>$v)
|
||||
<tr>
|
||||
@ -55,8 +55,8 @@ function changed($k,$v,$l=0)
|
||||
<?php
|
||||
$o = (new \App\Model\Photo())->where('id',$id)->first();
|
||||
switch ($v) :
|
||||
case 'id': $x=$id; $y=sprintf('<a href="%s">%s</a>',url('/info/'.$o->id),$o->id); break;
|
||||
case 'thumbnail': $x=md5($o->thumbnail); $y=sprintf('<a href="%s"><img src="%s" width="200px"></a>',url('/view/'.$o->id),url('/thumbnail/'.$o->id)); break;
|
||||
case 'id': $x=$id; $y=sprintf('<a href="%s">%s</a>',url('/p/info/'.$o->id),$o->id); break;
|
||||
case 'thumbnail': $x=md5($o->thumbnail); $y=sprintf('<a href="%s"><img src="%s" width="200px"></a>',url('/p/view/'.$o->id),url('/p/thumbnail/'.$o->id)); break;
|
||||
case 'signature': $x=$y=$o->signature(TRUE); break;
|
||||
case 'datetaken': $x=$y=$o->date_taken(); break;
|
||||
case 'created': $x=$y=$o->file_date('c',TRUE); break;
|
||||
|
@ -11,11 +11,11 @@
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="col-md-2">
|
||||
<a href="{{ url('/view/'.$photo->id) }}"><img src="{{ url('/thumbnail/'.$photo->id) }}" width="200px"></a>
|
||||
<a href="{{ url('/p/view/'.$photo->id) }}"><img src="{{ url('/p/thumbnail/'.$photo->id) }}" width="200px"></a>
|
||||
<div class="text-center">
|
||||
<ul class="pagination">
|
||||
<li <?php if (! $x = $photo->previous()) : ?>class="disabled"<?php endif ?>><a href="{{ $x ? url('/info/'.$x->id) : '#' }}"><<</a></li>
|
||||
<li <?php if (! $x = $photo->next()) : ?>class="disabled"<?php endif ?>><a href="{{ $x ? url('/info/'.$x->id) : '#' }}">>></a></li>
|
||||
<li <?php if (! $x = $photo->previous()) : ?>class="disabled"<?php endif ?>><a href="{{ $x ? url('/p/info/'.$x->id) : '#' }}"><<</a></li>
|
||||
<li <?php if (! $x = $photo->next()) : ?>class="disabled"<?php endif ?>><a href="{{ $x ? url('/p/info/'.$x->id) : '#' }}">>></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -66,10 +66,10 @@
|
||||
</div>
|
||||
|
||||
<?php if ($photo->remove) : ?>
|
||||
<form action="{{ url('/undelete/'.$photo->id) }}" method="POST">
|
||||
<form action="{{ url('/p/undelete/'.$photo->id) }}" method="POST">
|
||||
<button class="btn btn-default">Undelete</button>
|
||||
<?php else : ?>
|
||||
<form action="{{ url('/delete/'.$photo->id) }}" method="POST">
|
||||
<form action="{{ url('/p/delete/'.$photo->id) }}" method="POST">
|
||||
<button class="btn btn-default">Delete</button>
|
||||
<?php endif ?>
|
||||
{{ csrf_field() }}
|
||||
|
75
resources/views/video/deletereview.blade.php
Normal file
75
resources/views/video/deletereview.blade.php
Normal file
@ -0,0 +1,75 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<?php $data = [
|
||||
'ID'=>'id',
|
||||
'Signature'=>'signature',
|
||||
'Date Created'=>'datecreated',
|
||||
'File Created'=>'created',
|
||||
'File Modified'=>'modified',
|
||||
'Filename'=>'filepath',
|
||||
'Filesize'=>'filesize',
|
||||
'Width'=>'width',
|
||||
'Height'=>'height',
|
||||
'Make'=>'make',
|
||||
'Model'=>'model',
|
||||
'Duplicates'=>'duplicates',
|
||||
'Is Duplicate'=>'duplicate',
|
||||
'Flagged'=>'flag',
|
||||
'Delete'=>'remove',
|
||||
];?>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-11 col-md-offset-1">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Permanently Delete Photos
|
||||
</div>
|
||||
|
||||
<div class="text-center">{{ $videos->links() }}</div>
|
||||
<div class="panel-body">
|
||||
@if ($videos->count())
|
||||
<form action="{{ url('/v/deletes') }}" method="POST">
|
||||
<table class="table table-striped table-condensed table-hover">
|
||||
@foreach ($data as $k=>$v)
|
||||
<tr>
|
||||
<th>{{ $k }}</th>
|
||||
@foreach ($videos as $o)
|
||||
<?php
|
||||
switch ($v) :
|
||||
case 'id': $x=$o->id; $y=sprintf('<input type="hidden" name="video[]" value="%s"><a href="%s">%s</a>',$o->id,url('/v/info/'.$o->id),$o->id); break;
|
||||
case 'signature': $x=$y=$o->signature(TRUE); break;
|
||||
case 'datecreated': $x=$y=$o->date_taken(); break;
|
||||
case 'created': $x=$y=$o->file_date('c',TRUE); break;
|
||||
case 'modified': $x=$y=$o->file_date('m',TRUE); break;
|
||||
case 'filepath': $x=$y=$o->file_path(TRUE); break;
|
||||
case 'filesize': $x=$y=$o->file_size(); break;
|
||||
case 'width':
|
||||
case 'height':
|
||||
case 'orientation':
|
||||
case 'make':
|
||||
case 'model': $y=$o->{$v}; break;
|
||||
case 'duplicates': $x=$y='';foreach($o->list_duplicate() as $id) $y.=($y ? '|' : '').sprintf('<a href="%s">%s</a>',url('/v/info/'.$id),$id); break;
|
||||
case 'flag':
|
||||
case 'remove':
|
||||
case 'duplicate': $y=sprintf('<input type="checkbox" name="%s[%s]" value="1"%s>',$v,$o->id,$o->{$v} ? ' checked="checked"' : ''); break;
|
||||
endswitch ?>
|
||||
<td><?php echo $y; ?></td>
|
||||
@endforeach {{-- video --}}
|
||||
</tr>
|
||||
@endforeach {{-- data --}}
|
||||
</table>
|
||||
<input type="hidden" name="pagenext" value="{{ $videos->hasMorePages() ? $videos->currentPage()+1 : NULL }}">
|
||||
<button class="btn btn-default">Confirm Delete</button>
|
||||
{{ csrf_field() }}
|
||||
</form>
|
||||
@else
|
||||
NONE!
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
94
resources/views/video/duplicates.blade.php
Normal file
94
resources/views/video/duplicates.blade.php
Normal file
@ -0,0 +1,94 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<?php $data = [
|
||||
'ID'=>'id',
|
||||
'Signature'=>'signature',
|
||||
'Date Created'=>'datecreated',
|
||||
'File Created'=>'created',
|
||||
'File Modified'=>'modified',
|
||||
'Filename'=>'filepath',
|
||||
'Filesize'=>'filesize',
|
||||
'Width'=>'width',
|
||||
'Height'=>'height',
|
||||
'Make'=>'make',
|
||||
'Model'=>'model',
|
||||
];
|
||||
|
||||
$form = [
|
||||
'duplicate',
|
||||
'flag',
|
||||
'remove',
|
||||
];
|
||||
|
||||
function changed($k,$v,$l=0)
|
||||
{
|
||||
static $changed = [];
|
||||
|
||||
if (! isset($changed[$l][$k]))
|
||||
$changed[$l][$k] = $v;
|
||||
|
||||
return $changed[$l][$k] === $v;
|
||||
} ?>
|
||||
|
||||
@foreach ($videos as $video)
|
||||
<?php $duplicates = $video->list_duplicate(TRUE); ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-11 col-md-offset-1">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Duplicate Video {{ $video->id }}
|
||||
</div>
|
||||
|
||||
<div class="text-center">{{ $videos->links() }}</div>
|
||||
<div class="panel-body">
|
||||
<form action="{{ url('/v/duplicates') }}" method="POST">
|
||||
<table class="table table-striped table-condensed table-hover">
|
||||
@foreach ($data as $k=>$v)
|
||||
<tr>
|
||||
<th>{{ $k }}</th>
|
||||
@foreach ($duplicates as $id)
|
||||
<?php
|
||||
$o = (new \App\Model\Video())->where('id',$id)->first();
|
||||
switch ($v) :
|
||||
case 'id': $x=$id; $y=sprintf('<a href="%s">%s</a>',url('/v/info/'.$o->id),$o->id); break;
|
||||
case 'signature': $x=$y=$o->signature(TRUE); break;
|
||||
case 'datecreated': $x=$y=$o->date_taken(); break;
|
||||
case 'created': $x=$y=$o->file_date('c',TRUE); break;
|
||||
case 'modified': $x=$y=$o->file_date('m',TRUE); break;
|
||||
case 'filepath': $x=$y=$o->file_path(TRUE); break;
|
||||
case 'filesize': $x=$y=$o->file_size(); break;
|
||||
case 'width': $x=$y=$o->width; break;
|
||||
case 'height': $x=$y=$o->height; break;
|
||||
case 'make': $x=$y=$o->make; break;
|
||||
case 'model': $x=$y=$o->model; break;
|
||||
endswitch ?>
|
||||
<td class="{{ changed($v,$x) ? '' : 'danger' }}"><?php echo $y; ?></td>
|
||||
@endforeach {{-- video --}}
|
||||
</tr>
|
||||
@endforeach {{-- data --}}
|
||||
@foreach ($form as $v)
|
||||
<tr>
|
||||
<th>{{ $v }}</th>
|
||||
@foreach ($duplicates as $id)
|
||||
<?php $o = (new \App\Model\Video())->where('id',$id)->first(); ?>
|
||||
<td><input type="checkbox" name="{{ sprintf('%s[%s]',$v,$o->id) }}" value="1" {{ $o->$v==1 ? 'checked="checked"' : '' }}></td>
|
||||
@endforeach {{-- video --}}
|
||||
</tr>
|
||||
@endforeach {{-- form --}}
|
||||
</table>
|
||||
@foreach ($duplicates as $id)
|
||||
<input type="hidden" name="video[]" value="{{ $id }}">
|
||||
@endforeach {{-- video --}}
|
||||
<input type="hidden" name="page" value="{{ $videos->currentPage() }}">
|
||||
<button class="btn btn-default">Update</button>
|
||||
{{ csrf_field() }}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endsection
|
80
resources/views/video/view.blade.php
Normal file
80
resources/views/video/view.blade.php
Normal file
@ -0,0 +1,80 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-10 col-md-offset-1">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Video {{ $video->id }}<?php if ($video->remove) : ?> - <strong>PENDING DELETE</strong><?php endif?>
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="col-md-2">
|
||||
<!--<a href="{{ url('/v/view/'.$video->id) }}"><img src="{{ url('/v/thumbnail/'.$video->id) }}" width="200px"></a>-->
|
||||
<div class="text-center">
|
||||
<ul class="pagination">
|
||||
<li <?php if (! $x = $video->previous()) : ?>class="disabled"<?php endif ?>><a href="{{ $x ? url('/v/info/'.$x->id) : '#' }}"><<</a></li>
|
||||
<li <?php if (! $x = $video->next()) : ?>class="disabled"<?php endif ?>><a href="{{ $x ? url('/v/info/'.$x->id) : '#' }}">>></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<div class="dl-horizontal">
|
||||
<dt>Signature</dt><dd>{{ $video->signature(TRUE) }}</dd>
|
||||
<dt>Filename</dt><dd>{{ $video->file_path(TRUE) }}<dd>
|
||||
<?php if ($video->shouldMove()) : ?>
|
||||
<dt>NEW Filename</dt><dd>{{ $video->file_path(TRUE,TRUE) }}<dd>
|
||||
<?php endif ?>
|
||||
<dt>Size</dt><dd>{{ $video->file_size() }}<dd>
|
||||
<dt>Dimensions</dt><dd>{{ $video->width }} x {{ $video->height }}<dd>
|
||||
<dt>Length</dt><dd>{{ $video->length }}<dd>
|
||||
<dt>Type</dt><dd>{{ $video->type }}<dd>
|
||||
<dt>Codec</dt><dd>{{ $video->codec }}<dd>
|
||||
<dt>Audio Channels</dt><dd>{{ $video->audiochannels }}<dd>
|
||||
<dt>Channels Mode</dt><dd>{{ $video->channelmode }}<dd>
|
||||
<dt>Sample Rate</dt><dd>{{ $video->samplerate }}<dd>
|
||||
<br/>
|
||||
<dt>Date Taken</dt><dd>{{ $video->date_taken() }}<dd>
|
||||
<dt>Camera</dt><dd>{{ $video->make }}<dd>
|
||||
<dt>Model</dt><dd>{{ $video->model }}<dd>
|
||||
<br/>
|
||||
<dt>Location</dt><dd>
|
||||
<?php if ($video->gps() == 'UNKNOWN') : ?>
|
||||
UNKNOWN
|
||||
<?php else : ?>
|
||||
<div id="map" style="width: 400px; height: 300px"></div>
|
||||
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
|
||||
<script type="text/javascript">
|
||||
var myLatLng = {lat: {{ $video->gps_lat }}, lng: {{ $video->gps_lon }}};
|
||||
var map = new google.maps.Map(document.getElementById("map"), {
|
||||
zoom: 16,
|
||||
center: myLatLng,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
});
|
||||
var marker = new google.maps.Marker({
|
||||
map: map,
|
||||
position: myLatLng,
|
||||
});
|
||||
</script>
|
||||
<?php endif ?>
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($video->remove) : ?>
|
||||
<form action="{{ url('/v/undelete/'.$video->id) }}" method="POST">
|
||||
<button class="btn btn-default">Undelete</button>
|
||||
<?php else : ?>
|
||||
<form action="{{ url('/v/delete/'.$video->id) }}" method="POST">
|
||||
<button class="btn btn-default">Delete</button>
|
||||
<?php endif ?>
|
||||
{{ csrf_field() }}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
Loading…
Reference in New Issue
Block a user