Completed
Push — master ( 9b49f7...0d2bac )
by Song
03:00 queued 10s
created

ImageField   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 5

Importance

Changes 0
Metric Value
dl 0
loc 202
rs 10
c 0
b 0
f 0
wmc 25
lcom 2
cbo 5

8 Methods

Rating   Name   Duplication   Size   Complexity  
A defaultDirectory() 0 4 1
A callInterventionMethods() 0 15 3
A __call() 0 17 3
A render() 0 6 1
A thumbnail() 0 14 6
B destroyThumbnail() 0 24 6
A destroyThumbnailFile() 0 15 2
A uploadAndDeleteOriginalThumbnail() 0 32 3
1
<?php
2
3
namespace Encore\Admin\Form\Field;
4
5
use Illuminate\Support\Str;
6
use Intervention\Image\Constraint;
7
use Intervention\Image\Facades\Image as InterventionImage;
8
use Intervention\Image\ImageManagerStatic;
9
use Symfony\Component\HttpFoundation\File\UploadedFile;
10
11
trait ImageField
12
{
13
    /**
14
     * Intervention calls.
15
     *
16
     * @var array
17
     */
18
    protected $interventionCalls = [];
19
20
    /**
21
     * Thumbnail settings.
22
     *
23
     * @var array
24
     */
25
    protected $thumbnails = [];
26
27
    /**
28
     * Default directory for file to upload.
29
     *
30
     * @return mixed
31
     */
32
    public function defaultDirectory()
33
    {
34
        return config('admin.upload.directory.image');
35
    }
36
37
    /**
38
     * Execute Intervention calls.
39
     *
40
     * @param string $target
41
     *
42
     * @return mixed
43
     */
44
    public function callInterventionMethods($target)
45
    {
46
        if (!empty($this->interventionCalls)) {
47
            $image = ImageManagerStatic::make($target);
48
49
            foreach ($this->interventionCalls as $call) {
50
                call_user_func_array(
51
                    [$image, $call['method']],
52
                    $call['arguments']
53
                )->save($target);
54
            }
55
        }
56
57
        return $target;
58
    }
59
60
    /**
61
     * Call intervention methods.
62
     *
63
     * @param string $method
64
     * @param array  $arguments
65
     *
66
     * @throws \Exception
67
     *
68
     * @return $this
69
     */
70
    public function __call($method, $arguments)
71
    {
72
        if (static::hasMacro($method)) {
73
            return $this;
74
        }
75
76
        if (!class_exists(ImageManagerStatic::class)) {
77
            throw new \Exception('To use image handling and manipulation, please install [intervention/image] first.');
78
        }
79
80
        $this->interventionCalls[] = [
81
            'method'    => $method,
82
            'arguments' => $arguments,
83
        ];
84
85
        return $this;
86
    }
87
88
    /**
89
     * Render a image form field.
90
     *
91
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
92
     */
93
    public function render()
94
    {
95
        $this->options(['allowedFileTypes' => ['image'], 'msgPlaceholder' => trans('admin.choose_image')]);
0 ignored issues
show
Documentation Bug introduced by
The method options does not exist on object<Encore\Admin\Form\Field\ImageField>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
96
97
        return parent::render();
98
    }
99
100
    /**
101
     * @param string|array $name
102
     * @param int          $width
103
     * @param int          $height
104
     *
105
     * @return $this
106
     */
107
    public function thumbnail($name, int $width = null, int $height = null)
108
    {
109
        if (func_num_args() == 1 && is_array($name)) {
110
            foreach ($name as $key => $size) {
111
                if (count($size) >= 2) {
112
                    $this->thumbnails[$key] = $size;
113
                }
114
            }
115
        } elseif (func_num_args() == 3) {
116
            $this->thumbnails[$name] = [$width, $height];
117
        }
118
119
        return $this;
120
    }
121
122
    /**
123
     * Destroy original thumbnail files.
124
     *
125
     * @return void.
0 ignored issues
show
Documentation introduced by
The doc-type void. could not be parsed: Unknown type name "void." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
126
     */
127
    public function destroyThumbnail()
128
    {
129
        if ($this->retainable) {
0 ignored issues
show
Bug introduced by
The property retainable does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
130
            return;
131
        }
132
133
        foreach ($this->thumbnails as $name => $_) {
134
            /*  Refactoring actual remove lofic to another method destroyThumbnailFile()
135
            to make deleting thumbnails work with multiple as well as 
136
            single image upload. */
137
138
            if (is_array($this->original)) {
139
                if (empty($this->original)) {
0 ignored issues
show
Bug introduced by
The property original does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
140
                    continue;
141
                }
142
143
                foreach ($this->original as $original) {
144
                    $this->destroyThumbnailFile($original, $name);
145
                }
146
            } else {
147
                $this->destroyThumbnailFile($this->original, $name);
148
            }
149
        }
150
    }
151
152
    /**
153
     * Remove thumbnail file from disk.
154
     *
155
     * @return void.
0 ignored issues
show
Documentation introduced by
The doc-type void. could not be parsed: Unknown type name "void." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
156
     */
157
    public function destroyThumbnailFile($original, $name)
158
    {
159
160
        $ext = @pathinfo($original, PATHINFO_EXTENSION);
161
162
        // We remove extension from file name so we can append thumbnail type
163
        $path = @Str::replaceLast('.' . $ext, '', $original);
164
165
        // We merge original name + thumbnail name + extension
166
        $path = $path . '-' . $name . '.' . $ext;
167
168
        if ($this->storage->exists($path)) {
169
            $this->storage->delete($path);
0 ignored issues
show
Bug introduced by
The property storage does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
170
        }
171
    }
172
173
    /**
174
     * Upload file and delete original thumbnail files.
175
     *
176
     * @param UploadedFile $file
177
     *
178
     * @return $this
179
     */
180
    protected function uploadAndDeleteOriginalThumbnail(UploadedFile $file)
181
    {
182
        foreach ($this->thumbnails as $name => $size) {
183
            // We need to get extension type ( .jpeg , .png ...)
184
            $ext = pathinfo($this->name, PATHINFO_EXTENSION);
0 ignored issues
show
Bug introduced by
The property name does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
185
186
            // We remove extension from file name so we can append thumbnail type
187
            $path = Str::replaceLast('.' . $ext, '', $this->name);
188
189
            // We merge original name + thumbnail name + extension
190
            $path = $path . '-' . $name . '.' . $ext;
191
192
            /** @var \Intervention\Image\Image $image */
193
            $image = InterventionImage::make($file);
194
195
            $action = $size[2] ?? 'resize';
196
            // Resize image with aspect ratio
197
            $image->$action($size[0], $size[1], function (Constraint $constraint) {
198
                $constraint->aspectRatio();
199
            })->resizeCanvas($size[0], $size[1], 'center', false, '#ffffff');
200
201
            if (!is_null($this->storagePermission)) {
0 ignored issues
show
Bug introduced by
The property storagePermission does not seem to exist. Did you mean storage?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
202
                $this->storage->put("{$this->getDirectory()}/{$path}", $image->encode(), $this->storagePermission);
0 ignored issues
show
Bug introduced by
The property storagePermission does not seem to exist. Did you mean storage?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Documentation Bug introduced by
The method getDirectory does not exist on object<Encore\Admin\Form\Field\ImageField>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
203
            } else {
204
                $this->storage->put("{$this->getDirectory()}/{$path}", $image->encode());
0 ignored issues
show
Documentation Bug introduced by
The method getDirectory does not exist on object<Encore\Admin\Form\Field\ImageField>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
205
            }
206
        }
207
208
        $this->destroyThumbnail();
209
210
        return $this;
211
    }
212
}
213