Completed
Push — dev-master ( 408a96...99c448 )
by Vijay
03:59
created

Users::profileImageUrlDynamic()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 9.4285
1
<?php
2
3
namespace FFCMS\Mappers;
4
5
use FFCMS\{Traits, Models};
6
7
use FFMVC\Helpers;
8
9
/**
10
 * Users Mapper Class.
11
 *
12
 * @author Vijay Mahrra <[email protected]>
13
 * @copyright (c) Copyright 2016 Vijay Mahrra
14
 * @license GPLv3 (http://www.gnu.org/licenses/gpl-3.0.html)
15
 *
16
 * @property int    $id
17
 * @property string $uuid
18
 * @property string $password
19
 * @property string $email
20
 * @property string $firstname
21
 * @property string $lastname
22
 * @property string $scopes
23
 * @property string $status
24
 * @property string $password_question
25
 * @property string $password_answer
26
 * @property string $created
27
 * @property string $login_count
28
 * @property string $login_last
29
 */
30
class Users extends Mapper
31
{
32
    use Traits\UrlHelper;
33
34
    /**
35
     * Fields and their visibility to clients, boolean or string of visible field name
36
     *
37
     * @var array $fieldsVisible
38
     */
39
    public $fieldsVisible = [
40
        'uuid'              => 'id',
41
        'password'          => false,
42
        'scopes'            => false,
43
        'login_count'       => false,
44
    ];
45
46
    /**
47
     * Fields that are editable to clients, boolean or string of visible field name
48
     *
49
     * @var array $fieldsEditable
50
     */
51
    public $fieldsEditable = [
52
        'email',
53
        'firstname',
54
        'lastname',
55
        'password_question',
56
        'password_answer',
57
    ];
58
59
    /**
60
     * Filter rules for fields
61
     *
62
     * @var array $filterRules
63
     * @link https://github.com/Wixel/GUMP
64
     */
65
    public $filterRules = [
66
        'uuid'              => 'trim|sanitize_string|lower',
67
        'password'          => 'trim|sanitize_string',
68
        'email'             => 'trim|sanitize_string|sanitize_email|lower',
69
        'firstname'         => 'trim|sanitize_string',
70
        'lastname'          => 'trim|sanitize_string',
71
        'scopes'            => 'trim|sanitize_string|lower',
72
        'status'            => 'trim|sanitize_string|lower',
73
        'password_question' => 'trim|sanitize_string',
74
        'password_answer'   => 'trim|sanitize_string',
75
        'created'           => 'trim|sanitize_string',
76
        'login_count'       => 'sanitize_numbers|whole_number',
77
        'login_last'        => 'trim|sanitize_string',
78
    ];
79
80
    /**
81
     * Validation rules for fields
82
     *
83
     * @var array $validationRules
84
     * @link https://github.com/Wixel/GUMP
85
     */
86
    public $validationRules = [
87
        'uuid'              => 'alpha_dash',
88
        'email'             => 'valid_email',
89
        'firstname'         => 'valid_name',
90
    ];
91
92
    protected $profileImageFileName = 'profile.png';
93
94
    /**
95
     * Return the on-the-fly dynamic image generation URL path
96
     *
97
     * @param array $params params to url
98
     * @return string return the url path or false if not exists
99
     */
100
    public function profileImageUrlDynamic(array $params = []): string
101
    {
102
        $f3 = \Base::instance();
103
        return Helpers\Url::internal($f3->alias('profile_image', 'key=profile,uuid=' . $this->uuid), $params);
0 ignored issues
show
Documentation introduced by
'key=profile,uuid=' . $this->uuid is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
104
    }
105
106
    /**
107
     * Return the URL path to the image if exists or false
108
     *
109
     * @param null|string $uuid the user uuid
0 ignored issues
show
Bug introduced by
There is no parameter named $uuid. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
110
     * @return string return the url path or false if not exists
111
     */
112
    public function profileImageUrlPath($filename = null): string
113
    {
114
        if (empty($filename)) {
115
            $filename = $this->profileImageFileName;
116
        }
117
        $f3 = \Base::instance();
118
        return $f3->get('assets.url') . '/img/users/' . $this->uuid . '/' . $filename;
119
    }
120
121
    /**
122
     * Create if needed, and return the dir to the user profile image
123
     *
124
     * @return string $dir to the profile image
125
     */
126
    public function profileImageDirPath(): string
127
    {
128
        $f3  = \Base::instance();
129
        $dir = $f3->get('assets.dir') . '/img/users/' . $this->uuid;
130
        if (!file_exists($dir)) {
131
            mkdir($dir, 0777, true);
132
        }
133
        return $dir . '/';
134
    }
135
136
    /**
137
     * Create if needed, and return the path to the user profile image
138
     *
139
     * @param null|string $filename filename for image
140
     * @return string $path to the profile image
141
     */
142
    public function profileImageFilePath($filename = null): string
143
    {
144
        if (empty($filename)) {
145
            $filename = $this->profileImageFileName;
146
        }
147
        return $this->profileImageDirPath() . $filename;
148
    }
149
150
    /**
151
     * Return the URL path to the image if exists or false
152
     *
153
     * @param string $uuid the user uuid
0 ignored issues
show
Bug introduced by
There is no parameter named $uuid. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
154
     * @return null|string $path to the profile image
155
     * @return bool true if the profile image exists
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
156
     */
157
    public function profileImageExists($filename = null)
158
    {
159
        return file_exists($this->profileImageFilePath($filename));
160
    }
161
162
    /**
163
     * Return the URL path to the image if exists or false
164
     *
165
     * @param null|string $uuid the user uuid
0 ignored issues
show
Bug introduced by
There is no parameter named $uuid. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
166
     * @return false|string return the url path or false if not exists
167
     */
168
    public function profileImageUrl($filename = null)
169
    {
170
        $url = $this->profileImageExists($filename) ? $this->profileImageUrlPath($filename) : false;
171
        if (empty($url)) {
172
            return false;
173
        }
174
        return $url . '?' . filesize($this->profileImageFilePath($filename));
175
    }
176
177
178
    /**
179
     * Create profile image from given file
180
     *
181
     * @param string $file path to file
182
     * @return boolean if the file was written and and asset record created
0 ignored issues
show
Documentation introduced by
Should the return type not be false|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
183
     */
184
    public function profileImageCreate($file)
185
    {
186
        if (!file_exists($file)) {
187
            throw new Exceptions\Exception('Profile image creation file does not exist.');
188
        }
189
        $f3 = \Base::instance();
190
191
        // read exif metadata
192
        $reader = \PHPExif\Reader\Reader::factory(\PHPExif\Reader\Reader::TYPE_NATIVE);
193
        $exif = $reader->read($file);
194
        $metadata = $exif->getData();
195
        unset($exif);
196
197
        // load image
198
        $img = new \Image($file);
199
200
        // make sure maximum width/height not exceeded
201
        $max    = $f3->get('assets.image.max');
202
        $height = $img->height();
203
        $width  = $img->width();
204
        if ($width > $max['width'] || $height > $max['height']) {
205
            $height = $height > $max['height'] ? $max['height'] : $height;
206
            $width  = $width > $max['width'] ? $max['width'] : $width;
207
            $img->resize($width, $height);
208
        }
209
210
        // remove pre-existing cached-images
211
        $dirPath = $this->profileImageDirPath();
212
        foreach (glob($dirPath . '/*.jpg') as $file) {
213
            unlink($file);
214
        }
215
216
        // convert to .png, create new profile image file, overwrites existing
217
        $profileImagePath = $this->profileImageFilePath();
218
        if (!$f3->write($profileImagePath, $img->dump('png', $f3->get('assets.image.default.quality.png')))) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $f3->write($profileImage...default.quality.png'))) of type integer|false is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
219
            return false;
220
        }
221
222
        // create asset table entry
223
        $asset = new Assets;
224
225
        // load pre existing asset
226
        $asset->load(['users_uuid = ? AND ' . $this->db->quoteKey('key') . ' = ?', $this->uuid, 'profile']);
227
228
        // set values
229
        $asset->users_uuid = $this->uuid;
230
        $asset->filename = $profileImagePath;
231
        $asset->name = $this->firstname . ' ' . $this->lastname;
232
        $asset->description = $this->firstname . ' ' . $this->lastname . ' Profile Image';
233
        $asset->size = filesize($profileImagePath);
234
        $asset->url = $this->url($this->profileImageUrl());
0 ignored issues
show
Security Bug introduced by
It seems like $this->profileImageUrl() targeting FFCMS\Mappers\Users::profileImageUrl() can also be of type false; however, FFCMS\Traits\UrlHelper::url() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
235
        $asset->type = 'image/png';
236
        $asset->key = 'profile';
237
        $asset->groups = 'users';
238
        $asset->categories = 'profile';
0 ignored issues
show
Documentation introduced by
The property categories does not exist on object<FFCMS\Mappers\Assets>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
239
        $asset->tags = 'users,profile';
240
        $asset->metadata = json_encode($metadata, JSON_PRETTY_PRINT);
241
242
        return $asset->save();
243
    }
244
}
245