ModelTrait   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 183
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 1
Metric Value
wmc 17
eloc 45
c 7
b 0
f 1
dl 0
loc 183
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getFsComponent() 0 3 1
A getFilePresignedUrl() 0 9 2
A removeFile() 0 10 2
A getAttributePath() 0 8 2
A getPresignedUrlDuration() 0 10 2
A getFileUrl() 0 9 2
A attributePaths() 0 3 1
A saveUploadedFile() 0 25 5
1
<?php
2
3
namespace diecoding\flysystem\traits;
4
5
use Yii;
6
use yii\web\UploadedFile;
7
8
/**
9
 * Trait ModelTrait for Model
10
 * 
11
 * @link      https://sugengsulistiyawan.my.id/
12
 * @author    Sugeng Sulistiyawan <[email protected]>
13
 * @copyright Copyright (c) 2023
14
 */
15
trait ModelTrait
16
{
17
    /**
18
     * @return \diecoding\flysystem\AbstractComponent|mixed
19
     */
20
    public function getFsComponent()
21
    {
22
        return Yii::$app->get('fs');
23
    }
24
25
    /**
26
     * Save UploadedFile.
27
     * ! Important: This function uploads this model filename to keep consistency of the model.
28
     * 
29
     * @param UploadedFile $file Uploaded file to save
30
     * @param string $attribute Attribute name where the uploaded filename name will be saved
31
     * @param string $fileName Name which file will be saved. If empty will use the name from $file
32
     * @param bool $autoExtension `true` to automatically append or replace the extension to the file name. Default is `true`
33
     * 
34
     * @return void
35
     */
36
    public function saveUploadedFile(UploadedFile $file, $attribute, $fileName = '', $autoExtension = true)
37
    {
38
        if ($this->hasErrors()) {
39
            return;
40
        }
41
        if (empty($fileName)) {
42
            $fileName = $file->name;
43
        }
44
        if ($autoExtension) {
45
            $_file = (string) pathinfo($fileName, PATHINFO_FILENAME);
46
            $fileName = $_file . '.' . $file->extension;
47
        }
48
49
        $this->{$attribute} = $fileName;
50
        if (!$this->validate($attribute)) {
51
            return;
52
        }
53
        $filePath = $this->getAttributePath($attribute) . '/' . $fileName;
54
        $localPath = $file->tempName;
55
        $handle = fopen($localPath, 'r');
56
        $contents = fread($handle, filesize($localPath));
57
        fclose($handle);
58
59
        $filesystem = $this->getFsComponent();
60
        $filesystem->write($filesystem->normalizePath($filePath), $contents);
61
    }
62
63
    /**
64
     * Delete model file attribute.
65
     * 
66
     * @param string $attribute Attribute name which holds the filename
67
     * 
68
     * @return void
69
     */
70
    public function removeFile($attribute)
71
    {
72
        if (empty($this->{$attribute})) {
73
            return;
74
        }
75
        $filePath = $this->getAttributePath($attribute) . '/' . $this->{$attribute};
76
        $filesystem = $this->getFsComponent();
77
        $filesystem->delete($filesystem->normalizePath($filePath));
78
79
        $this->{$attribute} = null;
80
    }
81
82
    /**
83
     * Retrieves the URL for a given model file attribute.
84
     * 
85
     * @param string $attribute Attribute name which holds the filename
86
     * 
87
     * @return string URL to access file
88
     */
89
    public function getFileUrl($attribute)
90
    {
91
        if (empty($this->{$attribute})) {
92
            return '';
93
        }
94
        $filePath = $this->getAttributePath($attribute) . '/' . $this->{$attribute};
95
        $filesystem = $this->getFsComponent();
96
97
        return $filesystem->publicUrl($filesystem->normalizePath($filePath));
98
    }
99
100
    /**
101
     * Retrieves the presigned URL for a given model file attribute.
102
     * 
103
     * @param string $attribute Attribute name which holds the filename
104
     * 
105
     * @return string Presigned URL to access file
106
     */
107
    public function getFilePresignedUrl($attribute)
108
    {
109
        if (empty($this->{$attribute})) {
110
            return '';
111
        }
112
        $filePath = $this->getAttributePath($attribute) . '/' . $this->{$attribute};
113
        $filesystem = $this->getFsComponent();
114
115
        return $filesystem->temporaryUrl($filesystem->normalizePath($filePath), $this->getPresignedUrlDuration($attribute));
116
    }
117
118
    /**
119
     * List the paths on filesystem to each model file attribute.
120
     * It must be a Key-Value array, where Key is the attribute name and Value is the base path for the file in filesystem.
121
     * Override this method for saving each attribute in its own "folder".
122
     * 
123
     * @return array Key-Value of attributes and its paths.
124
     */
125
    protected function attributePaths()
126
    {
127
        return [];
128
    }
129
130
    /**
131
     * Retrieves the URL signature expiration.
132
     * 
133
     * @param string $attribute Attribute name which holds the duration
134
     * 
135
     * @return \DateTimeInterface URL expiration
136
     */
137
    protected function getPresignedUrlDuration($attribute)
138
    {
139
        $filesystem = $this->getFsComponent();
140
        $dateValue = '+5 Minutes';
141
142
        if (empty($this->{$attribute})) {
143
            $dateValue = 'now';
144
        }
145
146
        return $filesystem->convertToDateTime($dateValue);
147
    }
148
149
    /**
150
     * Retrieves the base path on filesystem for a given attribute.
151
     * see `attributePaths()`
152
     * 
153
     * @param string $attribute Attribute to get its path
154
     * 
155
     * @return string The path where all file of that attribute should be stored. Returns empty string if the attribute isn't in the list.
156
     */
157
    protected function getAttributePath($attribute)
158
    {
159
        $paths = $this->attributePaths();
160
        if (array_key_exists($attribute, $paths)) {
161
            return $paths[$attribute];
162
        }
163
164
        return '';
165
    }
166
167
    /**
168
     * Returns a value indicating whether there is any validation error.
169
     * @param string|null $attribute attribute name. Use null to check all attributes.
170
     * @return bool whether there is any error.
171
     */
172
    abstract public function hasErrors($attribute = null);
173
174
    /**
175
     * Performs the data validation.
176
     *
177
     * This method executes the validation rules applicable to the current [[scenario]].
178
     * The following criteria are used to determine whether a rule is currently applicable:
179
     *
180
     * - the rule must be associated with the attributes relevant to the current scenario;
181
     * - the rules must be effective for the current scenario.
182
     *
183
     * This method will call [[beforeValidate()]] and [[afterValidate()]] before and
184
     * after the actual validation, respectively. If [[beforeValidate()]] returns false,
185
     * the validation will be cancelled and [[afterValidate()]] will not be called.
186
     *
187
     * Errors found during the validation can be retrieved via [[getErrors()]],
188
     * [[getFirstErrors()]] and [[getFirstError()]].
189
     *
190
     * @param string[]|string|null $attributeNames attribute name or list of attribute names
191
     * that should be validated. If this parameter is empty, it means any attribute listed in
192
     * the applicable validation rules should be validated.
193
     * @param bool $clearErrors whether to call [[clearErrors()]] before performing validation
194
     * @return bool whether the validation is successful without any error.
195
     * @throws InvalidArgumentException if the current scenario is unknown.
196
     */
197
    abstract public function validate($attributeNames = null, $clearErrors = true);
198
}
199