My first Open source pull request
One feature is missing in Cakebox compared to the legacy version. The possibility to move easily to the next/previous video file in the same folder.
My developement enviroment is Mac OSX, MAMP Pro, Apache 2, PHP 5.5.26, NodeJS 2.11.3, PHPStorm 9.0.2.
I wrote a post about how to setup Cakebox to the latest (developement) version 2.0.0.
Backend
In order to browse server file, we will use the great Finder component from SensioLabs.
Dependency
We edit our dependencies,
back/composer.json
{
"name": "cakebox",
"type": "project",
"description": "",
"require": {
"php": ">=5.4.0",
"silex/silex": "~1.3",
"symfony/finder": "~2.7"
},
"autoload": {
"psr-0": {"Cakebox": "src/"}
}
}
Controller
The file controller back/src/Cakebox/Controller/FileController.php
must be edited to fetch next and previous readable video file in the same folder.
<?php
namespace Cakebox\Controller;
use Silex\Application;
use SPLFileInfo;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* FileController
*/
class FileController {
/**
* Get file informations (size, name ...)
*
* @param Application $app Silex Application
* @param Request $request Request parameters
*
* @return JsonResponse Object containing file informations
*/
public function get(Application $app, Request $request) {
if ($app["rights.canPlayMedia"] == false) {
$app->abort(403, "This user doesn't have the rights to retrieve file informations");
}
$filepath = $app['service.main']->checkPath($app['cakebox.root'], $request->get('path'));
if (!isset($filepath)) {
$app->abort(400, "Missing parameters");
}
$file = new SPLFileInfo("{$app['cakebox.root']}/{$filepath}");
$fileinfo = [];
$fileinfo["name"] = $file->getBasename("." . $file->getExtension());
$fileinfo["fullname"] = $file->getFilename();
$fileinfo["mimetype"] = mime_content_type($file->getPathName());
$fileinfo["access"] =
str_replace('%2F', '/', rawurlencode("{$app['cakebox.access']}/{$filepath}"));
$fileinfo["size"] = $file->getSize();
$arrDirectory = $this->getCurrentDirectoryFiles($file, $app);
if (count($arrDirectory) > 1) {
$fileinfo['previousFile'] =
$this->arrayKeyRelative($arrDirectory, $file->getRealPath(), -1);
if ($fileinfo['previousFile']) {
$fileinfo['previousFile'] =
str_replace($app['cakebox.root'], '', $fileinfo['previousFile']);
}
$fileinfo['nextFile'] = $this->arrayKeyRelative($arrDirectory, $file->getRealPath(), 1);
if ($fileinfo['nextFile']) {
$fileinfo['nextFile'] =
str_replace($app['cakebox.root'], '', $fileinfo['nextFile']);
}
}
return $app->json($fileinfo, 200);
}
/**
* Get files in the current $file directory
*
* @param SPLFileInfo $file
* @param Application $app
*
* @return array
*/
private function getCurrentDirectoryFiles(SPLFileInfo $file, Application $app) {
$finder = new Finder();
$finder->files()->in($file->getPath())->depth('== 0')->ignoreVCS(true)
->ignoreDotFiles($app['directory.ignoreDotFiles'])->notName($app["directory.ignore"])
->filter(function ($curFile) use ($app) {
/**
* @var SPLFileInfo $curFile
*/
if ($curFile->isReadable()
&& in_array(strtolower($curFile->getExtension()), $app['extension.video'])
) {
return true;
}
return false;
})->sortByType();
return iterator_to_array($finder->getIterator());
}
/**
* Get desired offset in an array
*
* @param array $array
* @param int|string $current_key
* @param int $offset
* @param bool $strict
*
* @return mixed return desired offset, if in array, or false if not
*/
private function arrayKeyRelative($array, $current_key, $offset = 1, $strict = true) {
$keys = array_keys($array);
$current_key_index = array_search($current_key, $keys, $strict);
if (isset($keys[$current_key_index + $offset])) {
return $keys[$current_key_index + $offset];
}
return false;
}
}
Model
Fetch and convert file path to url in the Angular controller.
front/src/app/play/play.controller.js
$scope.fileinfo = File.get({'path': $routeParams.path}, function(data) {
if ($scope.bsConfig.apikey) {
$scope.betaseries = Betaseries.get({'filename': data.name});
}
if (data.previousFile) {
$scope.prevplay = '#/play' + data.previousFile;
}
if (data.nextFile) {
$scope.nextplay = '#/play' + data.nextFile;
}
});
Display
Display them in the view.
front/src/app/play/play.html
<div class="row">
<div class="col-sm-6">
<a ng-href="{{ prevplay }}" ng-show="prevplay" translate>PLAY_PAGE.PREV</a>
</div>
<div class="col-sm-6">
<a ng-href="{{ nextplay }}" ng-show="nextplay" translate>PLAY_PAGE.NEXT</a>
</div>
</div>
And finally create translation.
front/src/assets/languages/locale-*.json
{
"PREV": "Previous video",
"NEXT": "Next video"
}