Passed
Push — master ( 28a360...d194a0 )
by Mihail
11:20
created

FormSocialAuth::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 4
c 1
b 1
f 0
nc 1
nop 2
dl 0
loc 6
rs 9.4285
1
<?php
2
3
namespace Apps\Model\Front\User;
4
5
use Apps\ActiveRecord\UserProvider;
6
use Apps\Model\Front\Profile\FormAvatarUpload;
7
use Ffcms\Core\App;
8
use Ffcms\Core\Arch\Model;
9
use Ffcms\Core\Exception\ForbiddenException;
10
use Ffcms\Core\Helper\FileSystem\File;
11
use Ffcms\Core\Helper\Type\Arr;
12
use Ffcms\Core\Helper\Type\Str;
13
use Ffcms\Core\Helper\Url;
14
use Ffcms\Core\Interfaces\iUser;
15
use \Symfony\Component\HttpFoundation\File\File as FileObject;
16
17
/**
18
 * Class FormSocialAuth. Model of social authorization and registering on top layer of register model.
19
 * @package Apps\Model\Front\User
20
 */
21
class FormSocialAuth extends FormRegister
22
{
23
    /** @var string */
24
    public $profileLink;
25
26
    /** @var string */
27
    private $_provider_name;
28
    private $_provider_id;
29
    /** @var \Hybrid_User_Profile */
30
    private $_identity;
31
    /** @var UserProvider */
32
    private $_record;
33
34
    /**
35
     * FormSocialAuth constructor. Pass provider name as string and identity as object of hybrid auth
36
     * @param bool $provider
37
     * @param $identity
38
     */
39
    public function __construct($provider, $identity)
40
    {
41
        $this->_provider_name = (string)$provider;
42
        $this->_identity = $identity;
43
        parent::__construct(false);
44
    }
45
46
    /**
47
    * Parse user identifier to attributes
48
    */
49
    public function before()
50
    {
51
        // set unique user id from provider response
52
        $this->_provider_id = $this->_identity->identifier;
53
54
        // grab some data from identity provider
55
        if ($this->email === null) {
56
            $this->email = $this->_identity->email;
57
        }
58
        $this->profileLink = $this->_identity->profileURL;
59
60
        // get record info from db for this identifier if exists
61
        $this->_record = UserProvider::where('provider_name', '=', $this->_provider_name)
0 ignored issues
show
Documentation Bug introduced by
It seems like \Apps\ActiveRecord\UserP...>_provider_id)->first() can also be of type object<Ffcms\Core\Arch\ActiveModel>. However, the property $_record is declared as type object<Apps\ActiveRecord\UserProvider>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
62
            ->where('provider_id', '=', $this->_provider_id)
63
            ->first();
64
    }
65
66
    /**
67
     * Check if this identity always exists
68
     * @return bool
69
     */
70
    public function identityExists()
71
    {
72
        return ($this->_record !== null && $this->_record->count() === 1);
73
    }
74
75
    /**
76
     * Make user authorization from social identity to website session
77
     * @return bool
78
     * @throws \Ffcms\Core\Exception\ForbiddenException
79
     */
80
    public function makeAuth()
81
    {
82
        if ($this->_record === null) {
83
            return false;
84
        }
85
        // get user from belongsTo relation
86
        $user = $this->_record->user;
0 ignored issues
show
Documentation introduced by
The property user does not exist on object<Apps\ActiveRecord\UserProvider>. 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...
87
        // maybe user was deleted without data provider record?
88
        if (!$user instanceof iUser) {
89
            throw new ForbiddenException(__('User related to this social account was deleted'));
90
        }
91
        // initialize login model
92
        $loginModel = new FormLogin();
93
        // open session & return status
94
        return $loginModel->openSession($user);
95
    }
96
97
    /**
98
     * Override default registration function with social auth data compatability
99
     * @param bool $activation
100
     * @return bool
101
     */
102
    public function tryRegister($activation = false)
103
    {
104
        // try to complete register process
105
        $success = parent::tryRegister($activation);
106
        if ($success && $this->_userObject !== null) {
107
            // save remote auth data to relation table
108
            $provider = new UserProvider();
109
            $provider->provider_name = $this->_provider_name;
110
            $provider->provider_id = $this->_provider_id;
111
            $provider->user_id = $this->_userObject->id;
112
            $provider->save();
113
114
            // get profile object from attr
115
            $profile = $this->_profileObject;
116
            // set nickname from remote service
117
            if (!Str::likeEmpty($this->_identity->displayName)) {
118
                $profile->nick = $this->_identity->displayName;
119
            }
120
            // set profile as user website
121
            $profile->url = $this->_identity->profileURL;
122
            // try to get gender (sex)
123
            if ($this->_identity->gender !== null) {
124
                $profile->sex = $this->_identity->gender === 'female' ? 2 : 1;
125
            }
126
            // set birthday if available
127
            if ($this->_identity->birthDay !== null && $this->_identity->birthMonth !== null && $this->_identity->birthYear !== null) {
128
                $profile->birthday = $this->_identity->birthYear . '-' . $this->_identity->birthMonth . '-' . $this->_identity->birthDay;
129
            }
130
131
            // try to parse avatar from remote service
132
            if ($this->_identity->photoURL !== null) {
133
                $this->parseAvatar($this->_identity->photoURL, $this->_userObject->id);
134
            }
135
136
            // save profile data
137
            $profile->save();
138
        }
139
140
        return $success;
141
    }
142
143
    /**
144
     * Try to download and parse remote avatar
145
     * @param string $url
146
     * @param int $userId
147
     */
148
    protected function parseAvatar($url, $userId)
149
    {
150
        // check if user is defined
151
        if ((int)$userId < 1) {
152
            return;
153
        }
154
155
        // check remote image extension
156
        $imageExtension = Str::lastIn($url, '.', true);
157
        if (!Arr::in($imageExtension, ['png', 'gif', 'jpg', 'jpeg'])) {
0 ignored issues
show
Security Bug introduced by
It seems like $imageExtension defined by \Ffcms\Core\Helper\Type\...lastIn($url, '.', true) on line 156 can also be of type false; however, Ffcms\Core\Helper\Type\Arr::in() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
158
            return;
159
        }
160
161
        // try to get image binary data
162
        $imageContent = Url::download($url);
0 ignored issues
show
Bug introduced by
The method download() does not seem to exist on object<Ffcms\Core\Helper\Url>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
163
        if ($imageContent === null || Str::likeEmpty($imageContent)) {
164
            return;
165
        }
166
167
        // write image to filesystem
168
        $imagePath = '/upload/user/avatar/original/' . $userId . '.' . $imageExtension;
169
        $write = File::write($imagePath, $imageContent);
170
        if ($write === false) {
171
            return;
172
        }
173
174
        // try to write and resize file
175
        try {
176
            $fileObject = new FileObject(root . $imagePath);
177
            $avatarUpload = new FormAvatarUpload();
178
            $avatarUpload->resizeAndSave($fileObject, $userId, 'small');
179
            $avatarUpload->resizeAndSave($fileObject, $userId, 'medium');
180
            $avatarUpload->resizeAndSave($fileObject, $userId, 'big');
181
        } catch (\Exception $e) {
182
            if (App::$Debug) {
183
                App::$Debug->addException($e);
184
            }
185
        }
186
    }
187
}