Completed
Push — master ( d4562c...6e7a7f )
by Garion
17s queued 12s
created

DMSDocument_Controller::index()   C

Complexity

Conditions 12
Paths 21

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 59
rs 6.4678
c 0
b 0
f 0
cc 12
nc 21
nop 1

How to fix   Long Method    Complexity   

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
class DMSDocument_Controller extends Controller
4
{
5
    /**
6
     * Mode to switch for testing. Does not return document download, just document URL.
7
     *
8
     * @var boolean
9
     */
10
    public static $testMode = false;
11
12
    private static $allowed_actions = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
13
        'index'
14
    );
15
16
    public function init()
17
    {
18
        Versioned::choose_site_stage();
19
        parent::init();
20
    }
21
22
    /**
23
     * Returns the document object from the request object's ID parameter.
24
     * Returns null, if no document found
25
     *
26
     * @param  SS_HTTPRequest $request
27
     * @return DMSDocument|null
28
     */
29
    protected function getDocumentFromID($request)
30
    {
31
        $doc = null;
0 ignored issues
show
Unused Code introduced by
$doc is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
32
33
        $id = Convert::raw2sql($request->param('ID'));
34
        if (strpos($id, 'version') === 0) {
35
            // Versioned document
36
            $id = $this->getDocumentIdFromSlug(str_replace('version', '', $id));
37
            $doc = DataObject::get_by_id('DMSDocument_versions', $id);
38
            $this->extend('updateVersionFromID', $doc, $request);
39
        } else {
40
            // Normal document
41
            $doc = DataObject::get_by_id('DMSDocument', $this->getDocumentIdFromSlug($id));
0 ignored issues
show
Bug introduced by
It seems like $id defined by \Convert::raw2sql($request->param('ID')) on line 33 can also be of type array; however, DMSDocument_Controller::getDocumentIdFromSlug() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
42
            $this->extend('updateDocumentFromID', $doc, $request);
43
        }
44
45
        return $doc;
46
    }
47
48
    /**
49
     * Get a document's ID from a "friendly" URL slug containing a numeric ID and slugged title
50
     *
51
     * @param  string $slug
52
     * @return int
53
     * @throws InvalidArgumentException if an invalid format is provided
54
     */
55
    protected function getDocumentIdFromSlug($slug)
56
    {
57
        $parts = (array) sscanf($slug, '%d-%s');
58
        $id = array_shift($parts);
59
        if (is_numeric($id)) {
60
            return (int) $id;
61
        }
62
        throw new InvalidArgumentException($slug . ' is not a valid DMSDocument URL');
63
    }
64
65
    /**
66
     * Access the file download without redirecting user, so we can block direct
67
     * access to documents.
68
     */
69
    public function index(SS_HTTPRequest $request)
70
    {
71
        $doc = $this->getDocumentFromID($request);
72
73
        if (!empty($doc)) {
74
            $canView = $doc->canView();
75
76
            if ($canView) {
77
                $path = $doc->getFullPath();
78
                if (is_file($path)) {
79
                    $fileBin = trim(`whereis file`);
80
                    if (function_exists('finfo_file')) {
81
                        // discover the mime type properly
82
                        $finfo = finfo_open(FILEINFO_MIME_TYPE);
83
                        $mime = finfo_file($finfo, $path);
84
                    } elseif (is_executable($fileBin)) {
85
                        $path = escapeshellarg($path);
86
                        // try to use the system tool
87
                        $mime = `$fileBin -i -b $path`;
88
                        $mime = explode(';', $mime);
89
                        $mime = trim($mime[0]);
90
                    } else {
91
                        // make do with what we have
92
                        $ext = $doc->getExtension();
93
                        if ($ext == 'pdf') {
94
                            $mime = 'application/pdf';
95
                        } elseif ($ext == 'html' || $ext =='htm') {
96
                            $mime = 'text/html';
97
                        } else {
98
                            $mime = 'application/octet-stream';
99
                        }
100
                    }
101
102
                    if (self::$testMode) {
103
                        return $path;
104
                    }
105
106
                    // set fallback if no config nor file-specific value
107
                    $disposition = 'attachment';
108
109
                    // file-specific setting
110
                    if ($doc->DownloadBehavior == 'open') {
111
                        $disposition = 'inline';
112
                    }
113
114
                    //if a DMSDocument can be downloaded and all the permissions/privileges has passed,
115
                    //its ViewCount should be increased by 1 just before the browser sending the file to front.
116
                    $doc->trackView();
117
118
                    return $this->sendFile($path, $mime, $doc->getFilenameWithoutID(), $disposition);
119
                }
120
            }
121
        }
122
123
        if (self::$testMode) {
124
            return 'This asset does not exist.';
125
        }
126
        $this->httpError(404, 'This asset does not exist.');
127
    }
128
129
    /**
130
     * @param string $path File path
131
     * @param string $mime File mime type
132
     * @param string $name File name
133
     * @param string $disposition Content dispositon
134
     */
135
    protected function sendFile($path, $mime, $name, $disposition)
136
    {
137
        header('Content-Type: ' . $mime);
138
        header('Content-Length: ' . filesize($path), null);
139
        if (!empty($mime) && $mime != "text/html") {
140
            header('Content-Disposition: '.$disposition.'; filename="'.addslashes($name).'"');
141
        }
142
        header('Content-transfer-encoding: 8bit');
143
        header('Expires: 0');
144
        header('Pragma: cache');
145
        header('Cache-Control: private');
146
        flush();
147
        readfile($path);
148
        exit;
149
    }
150
}
151