Added Tagging, Update to Laravel 5.5, Enabled Video

This commit is contained in:
Deon George 2018-01-10 08:10:14 +11:00
parent 3012004901
commit 96fadc5080
18 changed files with 1759 additions and 3344 deletions

View File

@ -67,6 +67,11 @@ class PhotoImport extends Command
{
$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
@ -74,6 +79,11 @@ class PhotoImport extends Command
{
$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;

128
app/Helpers/VideoStream.php Normal file
View File

@ -0,0 +1,128 @@
<?php
namespace App\Helpers;
/**
* Description of VideoStream
*
* @author Rana
* @link http://codesamplez.com/programming/php-html5-video-streaming-tutorial
**/
class VideoStream
{
private $path = '';
private $stream = '';
private $buffer = 102400;
private $start = -1;
private $end = -1;
private $size = 0;
function __construct($filePath)
{
$this->path = $filePath;
}
/**
* Open stream
**/
private function open()
{
if (! ($this->stream = fopen($this->path,'rb')) ) {
die('Could not open stream for reading');
}
}
/**
* Set proper header to serve the video content
**/
private function setHeader()
{
ob_get_clean();
header('Content-Type: video/mp4');
header('Cache-Control: max-age=2592000, public');
header('Expires: '.gmdate('D, d M Y H:i:s',time()+2592000) . ' GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s',@filemtime($this->path)) . ' GMT' );
$this->start = 0;
$this->size = filesize($this->path);
$this->end = $this->size - 1;
header('Accept-Ranges: 0-'.$this->end);
if (isset($_SERVER['HTTP_RANGE'])) {
$c_start = $this->start;
$c_end = $this->end;
list(,$range) = explode('=',$_SERVER['HTTP_RANGE'],2);
if (strpos($range,',') !== false) {
header('HTTP/1.1 416 Requested Range Not Satisfiable');
header("Content-Range: bytes $this->start-$this->end/$this->size");
exit;
}
if ($range == '-') {
$c_start = $this->size - substr($range,1);
}else{
$range = explode('-',$range);
$c_start = $range[0];
$c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end;
}
$c_end = ($c_end > $this->end) ? $this->end : $c_end;
if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) {
header('HTTP/1.1 416 Requested Range Not Satisfiable');
header("Content-Range: bytes $this->start-$this->end/$this->size");
exit;
}
$this->start = $c_start;
$this->end = $c_end;
$length = $this->end - $this->start + 1;
fseek($this->stream,$this->start);
header('HTTP/1.1 206 Partial Content');
header("Content-Length: ".$length);
header("Content-Range: bytes $this->start-$this->end/".$this->size);
}
else
{
header("Content-Length: ".$this->size);
}
}
/**
* close curretly opened stream
**/
private function end()
{
fclose($this->stream);
exit;
}
/**
* perform the streaming of calculated range
**/
private function stream()
{
$i = $this->start;
set_time_limit(0);
while(!feof($this->stream) && $i <= $this->end) {
$bytesToRead = $this->buffer;
if (($i+$bytesToRead) > $this->end) {
$bytesToRead = $this->end - $i + 1;
}
$data = fread($this->stream,$bytesToRead);
echo $data;
flush();
$i += $bytesToRead;
}
}
/**
* Start streaming video content
**/
function start()
{
$this->open();
$this->setHeader();
$this->stream();
$this->end();
}
}

View File

@ -6,9 +6,8 @@ use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesResources;
class Controller extends BaseController
{
use AuthorizesRequests, AuthorizesResources, DispatchesJobs, ValidatesRequests;
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

View File

@ -77,6 +77,7 @@ class PhotoController extends Controller
return redirect()->action('PhotoController@duplicates','?page='.$request->input('page'));
}
public function info($id)
{
return view('photo.view', ['photo'=> Photo::findOrFail($id)]);

View File

@ -8,6 +8,7 @@ use Illuminate\Http\Request;
use App\Http\Requests;
use App\Model\Video;
use App\Jobs\VideoDelete;
use App\Helpers\VideoStream;
class VideoController extends Controller
{
@ -34,13 +35,11 @@ class VideoController extends Controller
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)
@ -54,13 +53,11 @@ class VideoController extends Controller
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)
@ -99,9 +96,8 @@ class VideoController extends Controller
return redirect()->action('VideoController@info',[$id]);
}
//@todo
public function view($id)
{
return response(Video::findOrFail($id)->image())->header('Content-Type','video/mov');
(new VideoStream(Video::findOrFail($id)->file_path()))->start();
}
}

View File

@ -27,6 +27,7 @@ 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::get('/v/view/{id}', 'VideoController@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');

View File

@ -308,6 +308,11 @@ class Video extends Model
return strtolower($mime ? File::mime_by_ext(pathinfo($this->filename,PATHINFO_EXTENSION)) : pathinfo($this->filename,PATHINFO_EXTENSION));
}
public function view()
{
return sprintf('<video width="320" height="240" src="%s" controls></video>',url('/v/view/'.$this->id));
}
/**
* Find duplicate images based on some attributes of the current image
*/

View File

@ -21,9 +21,9 @@ class EventServiceProvider extends ServiceProvider
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @return void
*/
public function boot(DispatcherContract $events)
public function boot()
{
parent::boot($events);
parent::boot();
//
}

View File

@ -22,11 +22,11 @@ class RouteServiceProvider extends ServiceProvider
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function boot(Router $router)
public function boot()
{
//
parent::boot($router);
parent::boot();
}
/**

View File

@ -6,17 +6,10 @@
"type": "project",
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.2.*",
"laravel/framework": "5.5.*",
"james-heinrich/getid3": "^1.9"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~4.0",
"symfony/css-selector": "2.8.*|3.0.*",
"symfony/dom-crawler": "2.8.*|3.0.*",
"xethron/migrations-generator": "dev-l5",
"way/generators": "dev-feature/laravel-five-stable"
},
"autoload": {
"classmap": [
@ -49,11 +42,5 @@
},
"config": {
"preferred-install": "dist"
},
"repositories": {
"repo-name": {
"type": "git",
"url": "git@github.com:jamisonvalenta/Laravel-4-Generators.git"
}
}
}

4832
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -157,9 +157,6 @@ return [
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
Way\Generators\GeneratorsServiceProvider::class,
Xethron\MigrationsGenerator\MigrationsGeneratorServiceProvider::class,
],
/*

View File

@ -1,8 +1,8 @@
<?php
return [
'dir'=>'/var/www/sites/co.dlcm.p/store/photos',
'dir'=>'/photos',
'import'=>[
'accepted'=>['jpg'],
'accepted'=>['jpg','jpeg'],
],
];

View File

@ -1,9 +1,8 @@
<?php
return [
'dir'=>'/var/www/sites/co.dlcm.p/store/video',
'dir'=>'/videos',
'import'=>[
'accepted'=>['m4v','mov','mp4','avi'],
'log'=>'/tmp/import.log',
],
];

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreatePersonVideoTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('person_video', function(Blueprint $table)
{
$table->bigInteger('id', true);
$table->timestamps();
$table->integer('person_id');
$table->bigInteger('video_id')->index('fk_pp_ph_idx');
$table->unique(['person_id','video_id'], 'UNIQUE');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('person_video');
}
}

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateTagVideoTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('tag_video', function(Blueprint $table)
{
$table->bigInteger('id', true);
$table->timestamps();
$table->bigInteger('video_id');
$table->bigInteger('tag_id')->index('pt_t_idx');
$table->unique(['video_id','tag_id'], 'UNIQUE');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('tag_video');
}
}

View File

@ -3,7 +3,9 @@
@section('content')
<?php $data = [
'ID'=>'id',
'Video'=>'video',
'Signature'=>'signature',
'Length'=>'length',
'Date Created'=>'datecreated',
'File Created'=>'created',
'File Modified'=>'modified',
@ -53,6 +55,8 @@ function changed($k,$v,$l=0)
$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 'video': $x=$o->signature(TRUE);$y=$o->view();; break;
case 'length': $x=$y=$o->length; 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;

View File

@ -10,9 +10,9 @@
</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="col-md-4">
<div class="text-center">
{!! $video->view() !!}
<ul class="pagination">
<li <?php if (! $x = $video->previous()) : ?>class="disabled"<?php endif ?>><a href="{{ $x ? url('/v/info/'.$x->id) : '#' }}">&lt;&lt;</a></li>
<li <?php if (! $x = $video->next()) : ?>class="disabled"<?php endif ?>><a href="{{ $x ? url('/v/info/'.$x->id) : '#' }}">&gt;&gt;</a></li>
@ -20,7 +20,7 @@
</div>
</div>
<div class="col-md-10">
<div class="col-md-8">
<div class="dl-horizontal">
<dt>Signature</dt><dd>{{ $video->signature(TRUE) }}</dd>
<dt>Filename</dt><dd>{{ $video->file_path(TRUE) }}<dd>