Passed
Push — master ( 8c7a21...873684 )
by IT
03:23
created

StreamController::streamAction()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 2
Metric Value
cc 7
eloc 17
nc 8
nop 2
dl 0
loc 24
rs 6.7272
c 5
b 0
f 2
1
<?php
2
3
namespace AppBundle\Controller;
4
5
use AppBundle\Entity\Video;
6
use AppBundle\Exception\VideoEncodingErrorException;
7
use AppBundle\Exception\VideoEncodingPendingException;
8
use AppBundle\Exception\VideoNotEncodedException;
9
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
10
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
11
use Symfony\Component\Filesystem\Filesystem;
12
use Symfony\Component\HttpFoundation\BinaryFileResponse;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
15
16
class StreamController extends Controller
17
{
18
    use ControllerUtilsTrait;
19
20
    /**
21
     * @see https://symfony.com/doc/current/components/http_foundation.html#serving-files
22
     * @see apache mod_xsendfile: https://tn123.org/mod_xsendfile/
23
     * @see nginx X-accel: https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/
24
     * @param Request $request
25
     * @param Video $video
26
     * @return BinaryFileResponse
27
     * @throws \Exception
28
     */
29
    public function downloadAction(Request $request, Video $video)
30
    {
31
        $videoPath = $this->get('vich_uploader.storage')->resolvePath($video, 'videoFile');
32
        $response = new BinaryFileResponse($videoPath);
33
        if (filter_var(getenv('USE_X_SENDFILE_MODE'), FILTER_VALIDATE_BOOLEAN)) {
34
            BinaryFileResponse::trustXSendfileTypeHeader();
35
            $serverSoftware = $request->server->get('SERVER_SOFTWARE');
36
            //determine header according to server software to serve file faster directly by server instead of using php
37
            if (preg_match('/nginx/', $serverSoftware)) {
38
                if (!$nginxLocationXSendFile = getenv('NGINX_LOCATION_X_SEND_FILE')) {
39
                    throw new ParameterNotFoundException('nginx_location_x_send_file');
40
                }
41
                // slash management in lginx stream location
42
                $nginxLocationXSendFile = substr($nginxLocationXSendFile, -1) === '/' ? $nginxLocationXSendFile : $nginxLocationXSendFile . '/';
0 ignored issues
show
Bug introduced by
It seems like $nginxLocationXSendFile can also be of type array; however, parameter $string of substr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

42
                $nginxLocationXSendFile = substr(/** @scrutinizer ignore-type */ $nginxLocationXSendFile, -1) === '/' ? $nginxLocationXSendFile : $nginxLocationXSendFile . '/';
Loading history...
Bug introduced by
Are you sure $nginxLocationXSendFile of type string|array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

42
                $nginxLocationXSendFile = substr($nginxLocationXSendFile, -1) === '/' ? $nginxLocationXSendFile : /** @scrutinizer ignore-type */ $nginxLocationXSendFile . '/';
Loading history...
43
                $nginxLocationXSendFile = substr($nginxLocationXSendFile, 0, 1) === '/' ? $nginxLocationXSendFile : '/' . $nginxLocationXSendFile;
44
                $response->headers->set('X-Accel-Redirect', $nginxLocationXSendFile . 'video/' . basename(pathinfo($videoPath)['dirname']) . '/' . pathinfo($videoPath)['basename']);
45
            } elseif (preg_match('/apache/', $serverSoftware)) {
46
                $response->headers->set('X-Sendfile', $videoPath);
47
            } else {
48
                throw  new \Exception(sprintf('server "%s" not supported', $serverSoftware));
49
            }
50
            $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE, basename($videoPath));
51
        }
52
        return $response;
53
    }
54
55
56
    /**
57
     * secure the HLS m3u8 and segment download
58
     * @param Request $request
59
     * @param Video $video
60
     * @param $file
61
     * @return BinaryFileResponse
62
     */
63
    public function downloadHlsPlaylistFileAction(Request $request, Video $video, $file)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

63
    public function downloadHlsPlaylistFileAction(/** @scrutinizer ignore-unused */ Request $request, Video $video, $file)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
64
    {
65
        $videoPath = $this->get('vich_uploader.storage')->resolvePath($video, 'videoFile');
66
        $filePath = pathinfo($videoPath)['dirname'] . '/' . $file;
67
        $response = new BinaryFileResponse($filePath);
68
        $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE, basename($filePath));
69
        return $response;
70
    }
71
72
    /**
73
     * Http Live Streaming
74
     * @see https://en.wikipedia.org/wiki/HTTP_Live_Streaming
75
     * @param Request $request
76
     * @param Video $video
77
     * @return \Symfony\Component\HttpFoundation\Response
78
     */
79
    public function HlsAction(Request $request, Video $video)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

79
    public function HlsAction(/** @scrutinizer ignore-unused */ Request $request, Video $video)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
80
    {
81
82
        $videoPath = $this->get('vich_uploader.storage')->resolvePath($video, 'videoFile');
83
        $fs = new Filesystem();
84
        $playlistFile = getenv('HLS_PLAYLIST_NAME');
85
        $playlistFileLocation = pathinfo($videoPath)['dirname'] . '/' . $playlistFile;
0 ignored issues
show
Bug introduced by
Are you sure $playlistFile of type false|string|array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

85
        $playlistFileLocation = pathinfo($videoPath)['dirname'] . '/' . /** @scrutinizer ignore-type */ $playlistFile;
Loading history...
86
        $errorFileLocation = pathinfo($videoPath)['dirname'] . '/' . 'error';
87
        $lockFileLocation = pathinfo($videoPath)['dirname'] . '/' . 'lock';
88
        $error = false;
89
90
        if ($fs->exists($errorFileLocation)) {
91
            $error = $this->get('translator')->trans('encoding.error', [], 'stream');
92
            $this->flashMessage(ControllerUtilsTrait::$flashDanger, $error);
93
        }elseif ($fs->exists($lockFileLocation)) {
94
            $error = $this->get('translator')->trans('encoding.pending', [], 'stream');
95
            $this->flashMessage(ControllerUtilsTrait::$flashInfo, $error);
96
        }elseif(!$fs->exists($playlistFileLocation)) {
97
            $error = $this->get('translator')->trans('encoding.no-playlist', [], 'stream');
98
            $this->flashMessage(ControllerUtilsTrait::$flashDanger, $error);
99
        }
100
101
102
        return $this->render('stream/hls.html.twig', array(
103
            'error' => $error,
104
            'video' => $video,
105
            'playlistFileLocation' => $playlistFileLocation,
106
        ));
107
    }
108
}