Passed
Push — main ( 35f9ac...082ac6 )
by Sugeng
03:53
created

ModelTrait::getFilePresignedUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
namespace diecoding\flysystem\traits;
4
5
use League\Flysystem\UnableToDeleteFile;
6
use League\Flysystem\UnableToWriteFile;
7
use Yii;
8
use yii\web\UploadedFile;
9
10
/**
11
 * Trait ModelTrait for Model
12
 * 
13
 * @package diecoding\flysystem\traits
14
 * 
15
 * @link      https://sugengsulistiyawan.my.id/
16
 * @author    Sugeng Sulistiyawan <[email protected]>
17
 * @copyright Copyright (c) 2023
18
 */
19
trait ModelTrait
20
{
21
    /**
22
     * @return \diecoding\flysystem\AbstractComponent
23
     */
24
    public function getFsComponent()
25
    {
26
        return Yii::$app->get('fs');
0 ignored issues
show
Bug Best Practice introduced by
The expression return Yii::app->get('fs') also could return the type mixed which is incompatible with the documented return type diecoding\flysystem\AbstractComponent.
Loading history...
27
    }
28
29
    /**
30
     * Save UploadedFile to AWS S3.
31
     * ! Important: This function uploads this model filename to keep consistency of the model.
32
     * 
33
     * @param UploadedFile $file Uploaded file to save
34
     * @param string $attribute Attribute name where the uploaded filename name will be saved
35
     * @param string $fileName Name which file will be saved. If empty will use the name from $file
36
     * @param bool $autoExtension `true` to automatically append or replace the extension to the file name. Default is `true`
37
     * @param array $config
38
     * 
39
     * @return bool `true` for Uploaded full path of filename on success or `false` in failure.
40
     */
41
    public function saveUploadedFile(UploadedFile $file, $attribute, $fileName = '', $autoExtension = true, $config = [])
42
    {
43
        if ($this->hasError) {
44
            return false;
45
        }
46
        if (empty($fileName)) {
47
            $fileName = $file->name;
48
        }
49
        if ($autoExtension) {
50
            $_file = (string) pathinfo($fileName, PATHINFO_FILENAME);
51
            $fileName = $_file . '.' . $file->extension;
52
        }
53
        $filePath = $this->getAttributePath($attribute) . $fileName;
54
        try {
55
            $localPath = $file->tempName;
56
            $handle    = fopen($localPath, 'r');
57
            $contents  = fread($handle, filesize($localPath));
58
            fclose($handle);
59
            
60
            $filesystem = $this->getFsComponent();
61
            $filesystem->write($filesystem->normalizePath($filePath), $contents, $config);
62
63
            return true;
64
        } catch (UnableToWriteFile $exception) {
65
66
            Yii::error([
67
                'message' => $exception->getMessage(),
68
                'trace' => $exception->getTraceAsString(),
69
            ]);
70
71
            return false;
72
        }
73
    }
74
75
    /**
76
     * Delete model file attribute from AWS S3.
77
     * 
78
     * @param string $attribute Attribute name which holds the filename
79
     * 
80
     * @return bool `true` on success or if file doesn't exist.
81
     */
82
    public function removeFile($attribute)
83
    {
84
        if (empty($this->{$attribute})) {
85
            return true;
86
        }
87
        $filePath = $this->getAttributePath($attribute) . $this->{$attribute};
88
        try {
89
            $filesystem = $this->getFsComponent();
90
            $filesystem->delete($this->normalizePath($filePath));
0 ignored issues
show
Bug introduced by
It seems like normalizePath() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

90
            $filesystem->delete($this->/** @scrutinizer ignore-call */ normalizePath($filePath));
Loading history...
91
92
            $this->{$attribute} = null;
93
94
            return true;
95
        } catch (UnableToDeleteFile $exception) {
96
97
            Yii::error([
98
                'message' => $exception->getMessage(),
99
                'trace' => $exception->getTraceAsString(),
100
            ]);
101
102
            return false;
103
        }
104
    }
105
106
    /**
107
     * Retrieves the URL for a given model file attribute.
108
     * 
109
     * @param string $attribute Attribute name which holds the filename
110
     * 
111
     * @return string URL to access file
112
     */
113
    public function getFileUrl($attribute)
114
    {
115
        if (empty($this->{$attribute})) {
116
            return '';
117
        }
118
119
        return $this->getFsComponent()->getUrl($this->getAttributePath($attribute) . $this->{$attribute});
0 ignored issues
show
Bug introduced by
The method getUrl() does not exist on diecoding\flysystem\AbstractComponent. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

119
        return $this->getFsComponent()->/** @scrutinizer ignore-call */ getUrl($this->getAttributePath($attribute) . $this->{$attribute});
Loading history...
120
    }
121
122
    /**
123
     * Retrieves the presigned URL for a given model file attribute.
124
     * 
125
     * @param string $attribute Attribute name which holds the filename
126
     * 
127
     * @return string Presigned URL to access file
128
     */
129
    public function getFilePresignedUrl($attribute)
130
    {
131
        if (empty($this->{$attribute})) {
132
            return '';
133
        }
134
135
        return $this->getFsComponent()->getPresignedUrl(
0 ignored issues
show
Bug introduced by
The method getPresignedUrl() does not exist on diecoding\flysystem\AbstractComponent. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

135
        return $this->getFsComponent()->/** @scrutinizer ignore-call */ getPresignedUrl(
Loading history...
136
            $this->getAttributePath($attribute) . $this->{$attribute},
137
            $this->getPresignedUrlDuration($attribute)
138
        );
139
    }
140
141
    /**
142
     * Retrieves the URL signature expiration.
143
     * 
144
     * @param string $attribute Attribute name which holds the duration
145
     * 
146
     * @return mixed URL expiration
147
     */
148
    public function getPresignedUrlDuration($attribute)
0 ignored issues
show
Unused Code introduced by
The parameter $attribute 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

148
    public function getPresignedUrlDuration(/** @scrutinizer ignore-unused */ $attribute)

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...
149
    {
150
        return '+30 minutes';
151
    }
152
153
    /**
154
     * List the paths on AWS S3 to each model file attribute.
155
     * It must be a Key-Value array, where Key is the attribute name and Value is the base path for the file in S3.
156
     * Override this method for saving each attribute in its own "folder".
157
     * 
158
     * @return array Key-Value of attributes and its paths.
159
     */
160
    public function attributePaths()
161
    {
162
        return [];
163
    }
164
165
    /**
166
     * Retrieves the base path on AWS S3 for a given attribute.
167
     * @see attributePaths()
168
     * 
169
     * @param string $attribute Attribute to get its path
170
     * 
171
     * @return string The path where all file of that attribute should be stored. Returns empty string if the attribute isn't in the list.
172
     */
173
    public function getAttributePath($attribute)
174
    {
175
        $paths = $this->attributePaths();
176
        if (array_key_exists($attribute, $paths)) {
177
            return $paths[$attribute];
178
        }
179
180
        return '';
181
    }
182
}
183