Completed
Push — master ( c844fc...ec9d92 )
by Jan
21:21
created

ImageController::getImage()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 86
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 10
Bugs 1 Features 1
Metric Value
c 10
b 1
f 1
dl 0
loc 86
rs 6.5286
cc 7
eloc 27
nc 6
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Media controller
4
 * 
5
 * Basic controller for media functions
6
 * 
7
 * @category Controller
8
 * @subpackage Media
9
 * @package Olapus
10
 * @author Jan Drda <[email protected]>
11
 * @copyright Jan Drda
12
 * @license https://opensource.org/licenses/MIT MIT
13
 */
14
15
namespace App\Http\Controllers\Media;
16
17
use App\Helpers;
18
use Illuminate\Http\Request;
19
20
use App\Http\Controllers\Controller;
21
use App\Image;
22
use Illuminate\Support\Facades\Response;
23
use Illuminate\Support\Facades\App;
24
use Illuminate\Support\Facades\Cache;
25
use Illuminate\Support\Facades\Storage;
26
use Carbon\Carbon;
27
28
class ImageController extends Controller
29
{
30
   
31
   /**
32
    * Get image from storage
33
    * 
34
    * @param Request $request
35
    * @return file
36
    */
37
    public function getImage(Request $request)
0 ignored issues
show
Coding Style introduced by
getImage uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
38
    {  
39
        /**
40
         * Check the cache
41
         */
42
        $cacheKey = 'image:' . $request->imageName . ':' . $request->imageExtension;
43
        
44
        /**
45
         * File cached
46
         */
47
        if (Cache::has($cacheKey)) {
48
            
49
            $imageMeta = Cache::get($cacheKey);
50
        }
51
        
52
        /**
53
         * File not cached
54
         */
55
        else{
56
            
57
            /**
58
             * Get META information
59
             */
60
            $imageMeta = Image::where(['url' => $request->imageName, 'image_extension' => $request->imageExtension])->first(['image_mime_type', 'image_size', 'id', 'updated_at', 'image_etag']);
61
            
62
            /**
63
             * File does not exist
64
             */
65
            if(empty($imageMeta) == TRUE){
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
66
                App::abort(404);
67
            }
68
            
69
            /**
70
             * Save meta information to cache
71
             */
72
            Cache::forever($cacheKey, $imageMeta);
73
        }
74
        
75
        /**
76
         * Get filename
77
         */
78
        $filename = Helpers::getStorageFilename(env('APP_IMAGE_STORAGE_DIRECTORY', 'images'), $imageMeta->id);
79
        
80
        /**
81
         * Prepare stream
82
         */
83
        $stream = Storage::readStream($filename);
84
85
      
86
        /**
87
         * File headers
88
         */
89
        $headers = array(
90
            'Content-Description'       => 'File Transfer',
91
            'Content-Type'              => $imageMeta->image_mime_type,
92
            'Content-Transfer-Encoding' => 'binary',
93
            'Pragma'                    => 'public',
94
            'Expires'                   => Carbon::createFromTimestamp(time()+3600)->toRfc2822String(),
95
            'Last-Modified'             => $imageMeta->updated_at->toRfc2822String(),
96
            'Etag'                      => $imageMeta->image_etag,
97
        );
98
        
99
        /**
100
         * Response code cached
101
         */
102
        if( (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $imageMeta->image_etag)
103
                || (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && @$_SERVER['HTTP_IF_MODIFIED_SINCE'] == $imageMeta->updated_at->toRfc2822String()) ){
104
            
105
            $responseCode = 304;
106
        }
107
        
108
        /**
109
         * Response code not cached, but OK
110
         */
111
        else{
112
            
113
            $responseCode = 200;
114
        }
115
116
        /**
117
         * Stream to browser
118
         */
119
        return Response::stream(function() use ($stream) {
120
                    fpassthru($stream);
121
                }, $responseCode, $headers);
122
    }
123
}
124