Completed
Push — master ( a84da5...01779b )
by Dmitry
05:09
created

File   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 172
ccs 0
cts 119
cp 0
rs 10
wmc 23
lcom 1
cbo 7

12 Methods

Rating   Name   Duplication   Size   Complexity  
A uploadPath() 0 4 1
A attributes() 0 17 1
A getHash() 0 4 1
A filePath() 0 5 1
A fileDir() 0 4 1
A getTempFolder() 0 4 1
A getTmpUrl() 0 5 1
A get_file_from_site() 0 20 4
A responseFile() 0 7 1
A get_file_from_api() 0 18 3
A renderFile() 0 9 3
B fileSave() 0 28 5
1
<?php
2
3
/*
4
 * HiPanel core package
5
 *
6
 * @link      https://hipanel.com/
7
 * @package   hipanel-core
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2014-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hipanel\models;
13
14
use hipanel\base\Err;
15
use Yii;
16
use yii\helpers\FileHelper;
17
use yii\helpers\Url;
18
use yii\web\NotFoundHttpException;
19
use yii\web\Response;
20
use yii\web\UploadedFile;
21
22
class File extends \hiqdev\hiart\ActiveRecord
23
{
24
    const MD5 = '76303fjsq06mcr234nc379z32x48';
25
    const SALT = 'salt';
26
27
    /**
28
     * @var string the directory to store uploaded files. You may use path alias here.
29
     * If not set, it will use the "upload" subdirectory under the application runtime path.
30
     */
31
    public $path = '@runtime/upload';
32
33
    /**
34
     * @param $key
35
     * @return bool|string
36
     */
37
    public static function uploadPath($key)
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

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

Loading history...
38
    {
39
        return Yii::getAlias('@runtime/upload/');
40
    }
41
42
    /**
43
     * @return array
44
     */
45
    public function attributes()
46
    {
47
        return [
48
            'id',
49
            'ids',
50
            'object_id',
51
            'object_ids',
52
            'object',
53
            'seller',
54
            'sellers',
55
            'url',
56
            'filename',
57
            'author_id',
58
            'filepath',
59
            'extension',
60
        ];
61
    }
62
63
    /**
64
     * @param $name
65
     * @return string
66
     */
67
    public static function getHash($name)
68
    {
69
        return md5(self::MD5 . $name . self::SALT);
70
    }
71
72
    public static function filePath($file_id)
73
    {
74
        return Yii::getAlias('@runtime/upload/' . substr($file_id, -2, 2) . DIRECTORY_SEPARATOR . $file_id);
75
//        return implode('/', [self::fileDir($md5), $md5]);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
76
    }
77
78
    public static function fileDir($md5)
79
    {
80
        return implode('/', ['var/files/tickets', substr($md5, 0, 2)]); // $GLOBALS['PRJ_DIR'],
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
81
    }
82
83
    /**
84
     * @return string
85
     */
86
    public static function getTempFolder()
87
    {
88
        return Yii::getAlias('@runtime/tmp');
89
    }
90
91
    /**
92
     * @param $temp_name
93
     * @return string
94
     */
95
    private static function getTmpUrl($temp_name)
96
    {
97
        $key = self::getHash($temp_name);
98
        return Url::to(['/file/temp-view', 'temp_file' => $temp_name, 'key' => $key], true);
99
    }
100
101
    /**
102
     * @param $file
103
     * @param null $file_id
104
     * @param null $object_id
105
     * @return array|bool
106
     */
107
    private static function get_file_from_site($file, $file_id = null, $object_id = null, $object_name = null, $render = true)
108
    {
109
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
110
        $mime_type = finfo_file($finfo, $file);
111
        finfo_close($finfo);
112
//        $data = file_get_contents($file);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
113
//        if (err::is($data))
114
//            return self::put_file_from_api($file_id, $object_id, $object_name, $render);
115
        if ($mime_type === 'text/plain') {
116
            $encoded = json_decode(file_get_contents($file), true);
117
            if (err::is($encoded)) {
118
                return self::get_file_from_api($file_id, $object_id, $object_name, $render);
0 ignored issues
show
Bug Compatibility introduced by
The expression self::get_file_from_api(...$object_name, $render); of type string|boolean adds the type string to the return on line 118 which is incompatible with the return type documented by hipanel\models\File::get_file_from_site of type array|boolean.
Loading history...
119
            }
120
        }
121
        if ($render) {
122
            return self::responseFile($file, $mime_type);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return self::responseFile($file, $mime_type); (string) is incompatible with the return type documented by hipanel\models\File::get_file_from_site of type array|boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
123
        } else {
124
            return $file;
125
        }
126
    }
127
128
    private static function responseFile($path, $content_type)
129
    {
130
        $response = Yii::$app->getResponse();
131
        $response->format = Response::FORMAT_RAW;
132
        $response->getHeaders()->add('content-type', $content_type);
133
        return file_get_contents($path);
134
    }
135
136
    private static function get_file_from_api($file_id, $object_id = null, $object_name = null, $render = true)
137
    {
138
        $data = self::perform('Get', ['id' => $file_id, 'object_id' => $object_id, 'object' => $object_name]);
139
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
140
        $mime_type = finfo_buffer($finfo, $data);
141
        finfo_close($finfo);
142
        $finalDestination = self::filePath($file_id);
143
        FileHelper::createDirectory(dirname($finalDestination));
144
        $file = file_put_contents($finalDestination, $data);
145
        if (!$file) {
146
            throw new NotFoundHttpException('File not found!');
147
        }
148
        if ($render) {
149
            return self::responseFile($finalDestination, $mime_type);
150
        } else {
151
            return $finalDestination;
152
        }
153
    }
154
155
    public static function renderFile($file_id, $object_id = null, $object_name = null, $render = true, $nocache = false)
156
    {
157
        if (is_file(self::filePath($file_id)) && !$nocache) {
158
            $res = self::get_file_from_site(self::filePath($file_id), $file_id, $object_id, $object_name, $render);
159
        } else {
160
            $res = self::get_file_from_api($file_id, $object_id, $object_name, $render);
161
        }
162
        return $res;
163
    }
164
165
    public static function fileSave(array $files)
166
    {
167
        $arr_ids = [];
168
        foreach ($files as $file) {
169
            if ($file instanceof UploadedFile) {
170
                // Move to temporary destination
171
                $tempDestination = self::getTempFolder() . DIRECTORY_SEPARATOR . uniqid() . '.' . $file->extension;
172
                FileHelper::createDirectory(dirname($tempDestination));
173
                $file->saveAs($tempDestination);
174
                // Prepare to final destination
175
                $url = self::getTmpUrl(basename($tempDestination));
176
                $response =  self::perform('Put', [
177
                    'url' => $url,
178
                    'filename' => basename($tempDestination),
179
                ]);
180
                $file_id = $arr_ids[] = $response['id'];
181
                $finalDestination = self::filePath($file_id);
182
                FileHelper::createDirectory(dirname($finalDestination));
183
                if (!rename($tempDestination, $finalDestination)) {
184
                    throw new \LogicException('rename function is not work');
185
                }
186
                if (is_file($tempDestination)) {
187
                    unlink($tempDestination);
188
                }
189
            }
190
        }
191
        return $arr_ids;
192
    }
193
}
194