Passed
Push — master ( 2c7b25...f52af3 )
by Mihail
05:14
created

Profile   F

Complexity

Total Complexity 78

Size/Duplication

Total Lines 536
Duplicated Lines 9.33 %

Coupling/Cohesion

Components 1
Dependencies 32

Importance

Changes 20
Bugs 4 Features 0
Metric Value
c 20
b 4
f 0
dl 50
loc 536
rs 1.3043
wmc 78
lcom 1
cbo 32

13 Methods

Rating   Name   Duplication   Size   Complexity  
C actionIndex() 0 63 12
C actionShow() 3 62 12
B actionAvatar() 0 25 4
D actionWalldelete() 0 36 10
A actionMessages() 0 8 2
B actionNotifications() 0 35 3
B actionSettings() 22 22 4
B actionPassword() 22 22 4
C actionIgnore() 0 48 7
A actionLog() 0 20 4
C actionUnblock() 3 29 8
B actionSearch() 0 41 4
B buildSitemapSchedule() 0 22 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Profile often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Profile, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Apps\Controller\Front;
4
5
use Apps\ActiveRecord\Blacklist;
6
use Apps\ActiveRecord\UserNotification;
7
use Apps\ActiveRecord\WallPost;
8
use Apps\Model\Front\Profile\EntityNotificationsList;
9
use Apps\Model\Front\Profile\FormAvatarUpload;
10
use Apps\Model\Front\Profile\FormIgnoreAdd;
11
use Apps\Model\Front\Profile\FormIgnoreDelete;
12
use Apps\Model\Front\Profile\FormPasswordChange;
13
use Apps\Model\Front\Profile\FormSettings;
14
use Apps\Model\Front\Profile\FormUserSearch;
15
use Apps\Model\Front\Profile\FormWallPostDelete;
16
use Apps\Model\Front\Profile\FormWallPost;
17
use Apps\Model\Front\Sitemap\EntityBuildMap;
18
use Extend\Core\Arch\FrontAppController;
19
use Ffcms\Core\App;
20
use Ffcms\Core\Exception\ForbiddenException;
21
use Ffcms\Core\Exception\NotFoundException;
22
use Ffcms\Core\Helper\HTML\SimplePagination;
23
use Ffcms\Core\Helper\Text;
24
use Ffcms\Core\Helper\Type\Obj;
25
use Ffcms\Core\Helper\Serialize;
26
use Ffcms\Core\Helper\Type\Str;
27
use Apps\ActiveRecord\Profile as ProfileRecords;
28
use Ffcms\Core\Helper\Url;
29
30
31
/**
32
 * Class Profile - user profiles interaction
33
 * @package Apps\Controller\Front
34
 */
35
class Profile extends FrontAppController
36
{
37
    const BLOCK_PER_PAGE = 10;
38
    const NOTIFY_PER_PAGE = 25;
39
40
    /**
41
     * List user profiles on website by defined filter
42
     * @param string $filter_name
43
     * @param null|string|int $filter_value
44
     * @return string
45
     * @throws \Ffcms\Core\Exception\NativeException
46
     * @throws NotFoundException
47
     * @throws \Ffcms\Core\Exception\SyntaxException
48
     */
49
    public function actionIndex($filter_name, $filter_value = null)
50
    {
51
        $records = null;
52
53
        // set current page and offset
54
        $page = (int)App::$Request->query->get('page', 0);
55
        $cfgs = Serialize::decode($this->application->configs);
56
        $userPerPage = (int)$cfgs['usersOnPage'];
57
        if ($userPerPage < 1) {
58
            $userPerPage = 1;
59
        }
60
        $offset = $page * $userPerPage;
61
62
        switch ($filter_name) {
63
            case 'rating': // rating list, order by rating DESC
64
                // check if rating is enabled
65
                if ((int)$cfgs['rating'] !== 1) {
66
                    throw new NotFoundException();
67
                }
68
                $records = (new ProfileRecords())->orderBy('rating', 'DESC');
69
                break;
70
            case 'hobby': // search by hobby
71
                if (Str::likeEmpty($filter_value)) {
0 ignored issues
show
Bug introduced by
It seems like $filter_value defined by parameter $filter_value on line 49 can also be of type integer or string; however, Ffcms\Core\Helper\Type\Str::likeEmpty() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
72
                    throw new NotFoundException();
73
                }
74
                $records = (new ProfileRecords())->where('hobby', 'like', '%' . $filter_value . '%');
75
                break;
76
            case 'city':
77
                if (Str::likeEmpty($filter_value)) {
0 ignored issues
show
Bug introduced by
It seems like $filter_value defined by parameter $filter_value on line 49 can also be of type integer or string; however, Ffcms\Core\Helper\Type\Str::likeEmpty() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
78
                    throw new NotFoundException();
79
                }
80
                $records = (new ProfileRecords())->where('city', '=', $filter_value);
81
                break;
82
            case 'born':
83
                if ($filter_value === null || !Obj::isLikeInt($filter_value)) {
84
                    throw new NotFoundException();
85
                }
86
                $records = (new ProfileRecords())->where('birthday', 'like', $filter_value . '-%');
87
                break;
88
            case 'all':
89
                $records = (new ProfileRecords())->orderBy('id', 'DESC');
90
                break;
91
            default:
92
                App::$Response->redirect('profile/index/all');
93
                break;
94
        }
95
96
        // build pagination
97
        $pagination = new SimplePagination([
98
            'url' => ['profile/index', $filter_name, $filter_value],
99
            'page' => $page,
100
            'step' => $userPerPage,
101
            'total' => $records->count()
102
        ]);
103
104
        return App::$View->render('index', [
105
            'records' => $records->skip($offset)->take($userPerPage)->get(),
106
            'pagination' => $pagination,
107
            'id' => $filter_name,
108
            'add' => $filter_value,
109
            'ratingOn' => (int)$cfgs['rating']
110
        ]);
111
    }
112
113
    /**
114
     * Show user profile: data, wall posts, other features
115
     * @param int $userId
116
     * @return string
117
     * @throws \Ffcms\Core\Exception\SyntaxException
118
     * @throws \Ffcms\Core\Exception\NativeException
119
     * @throws NotFoundException
120
     * @throws ForbiddenException
121
     */
122
    public function actionShow($userId)
123
    {
124
        $cfg = Serialize::decode($this->application->configs);
125 View Code Duplication
        if ((int)$cfg['guestView'] !== 1 && !App::$User->isAuth()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
126
            throw new ForbiddenException(__('You must login to view other profile'));
127
        }
128
        // check if target exists
129
        if (!App::$User->isExist($userId)) {
130
            throw new NotFoundException(__('This profile is not exist'));
131
        }
132
133
        $targetPersone = App::$User->identity($userId); // target user object instance of Apps\ActiveRecord\User
134
        $viewerPersone = App::$User->identity(); // current user object(viewer) instance of Apps\ActiveRecord\User
135
136
        $wallModel = null;
137
        // if current user is auth - allow to post messages on wall current user
138
        if (App::$User->isAuth() && $viewerPersone->getRole()->can('global/write')) {
139
            $wallModel = new FormWallPost();
140
            // check if request post is done and rules validated
141
            if ($wallModel->send() && $wallModel->validate()) {
142
                // maybe in blacklist?
143
                if (!Blacklist::check($viewerPersone->getId(), $targetPersone->getId())) {
144
                    App::$Session->getFlashBag()->add('error', __('This user are in your black list or you are in blacklist!'));
145
                } else {
146
                    // check if message added
147
                    if ($wallModel->makePost($targetPersone, $viewerPersone, (int)$cfg['delayBetweenPost'])) {
0 ignored issues
show
Bug introduced by
It seems like $targetPersone defined by \Ffcms\Core\App::$User->identity($userId) on line 133 can be null; however, Apps\Model\Front\Profile\FormWallPost::makePost() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
Bug introduced by
It seems like $viewerPersone defined by \Ffcms\Core\App::$User->identity() on line 134 can be null; however, Apps\Model\Front\Profile\FormWallPost::makePost() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
148
                        App::$Session->getFlashBag()->add('success', __('The message was successful posted!'));
149
                    } else {
150
                        App::$Session->getFlashBag()->add('warning', __('Posting message was failed! Please, wait few seconds'));
151
                    }
152
                }
153
            }
154
        }
155
156
        $query = $targetPersone->getWall(); // relation hasMany from users to walls
157
        // pagination and query params
158
        $wallPage = (int)App::$Request->query->get('page');
159
        $wallItems = (int)$cfg['wallPostOnPage'];
160
        $wallOffset = $wallPage * $wallItems;
161
162
        // build pagination
163
        $wallPagination = new SimplePagination([
164
            'url' => ['profile/show', $userId, null],
165
            'page' => $wallPage,
166
            'step' => $wallItems,
167
            'total' => $query->count()
168
        ]);
169
170
        // get wall messages
171
        $wallRecords = $query->orderBy('id', 'desc')->skip($wallOffset)->take($wallItems)->get();
172
173
        return App::$View->render('show', [
174
            'user' => $targetPersone,
175
            'viewer' => $viewerPersone,
176
            'isSelf' => ($viewerPersone !== null && $viewerPersone->id === $targetPersone->id),
0 ignored issues
show
Bug introduced by
Accessing id on the interface Ffcms\Core\Interfaces\iUser suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
177
            'wall' => !Obj::isObject($wallModel) ? null : $wallModel->filter(),
178
            'notify' => App::$Session->getFlashBag()->all(),
179
            'wallRecords' => $wallRecords,
180
            'pagination' => $wallPagination,
181
            'ratingOn' => (int)$cfg['rating'] === 1
182
        ]);
183
    }
184
185
    /**
186
     * User avatar management
187
     * @throws \Ffcms\Core\Exception\NativeException
188
     * @throws \Ffcms\Core\Exception\SyntaxException
189
     */
190
    public function actionAvatar()
191
    {
192
        if (!App::$User->isAuth()) {
193
            throw new ForbiddenException('You must be authorized user!');
194
        }
195
196
        // get user identity and model object
197
        $user = App::$User->identity();
198
        $model = new FormAvatarUpload(true);
0 ignored issues
show
Unused Code introduced by
The call to FormAvatarUpload::__construct() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
199
200
        // validate model post data
201
        if ($model->send()) {
202
            if ($model->validate()) {
203
                $model->copyFile($user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by \Ffcms\Core\App::$User->identity() on line 197 can be null; however, Apps\Model\Front\Profile...vatarUpload::copyFile() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
204
                App::$Session->getFlashBag()->add('success', __('Avatar is successful changed'));
205
            } else {
206
                App::$Session->getFlashBag()->add('error', __('File upload is failed!'));
207
            }
208
        }
209
210
        return App::$View->render('avatar', [
211
            'user' => $user,
212
            'model' => $model
213
        ]);
214
    }
215
216
    /**
217
     * Allow post owners and targets delete
218
     * @param int $postId
219
     * @return string
220
     * @throws \Ffcms\Core\Exception\SyntaxException
221
     * @throws \Ffcms\Core\Exception\NativeException
222
     * @throws ForbiddenException
223
     * @throws NotFoundException
224
     */
225
    public function actionWalldelete($postId)
226
    {
227
        // is user auth?
228
        if (!App::$User->isAuth()) {
229
            throw new ForbiddenException();
230
        }
231
232
        // is postId is integer?
233
        if (!Obj::isLikeInt($postId) || $postId < 1) {
234
            throw new NotFoundException();
235
        }
236
237
        // try to find the wall post
238
        $wallPost = WallPost::find($postId);
239
        if (null === $wallPost || false === $wallPost) {
240
            throw new NotFoundException();
241
        }
242
243
        // get user and check if he can delete this post
244
        $user = App::$User->identity();
245
        if ($wallPost->sender_id !== $user->id && $wallPost->target_id !== $user->id) {
0 ignored issues
show
Bug introduced by
Accessing id on the interface Ffcms\Core\Interfaces\iUser suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
246
            throw new ForbiddenException();
247
        }
248
249
        // check if submit sended
250
        $wallModel = new FormWallPostDelete($wallPost);
0 ignored issues
show
Compatibility introduced by
$wallPost of type object<Ffcms\Core\Arch\ActiveModel> is not a sub-type of object<Apps\ActiveRecord\WallPost>. It seems like you assume a child class of the class Ffcms\Core\Arch\ActiveModel to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
251
        if ($wallModel->send() && $wallModel->validate()) {
252
            $wallModel->make();
253
            App::$Response->redirect('profile/show/' . $wallPost->target_id);
254
        }
255
256
        return App::$View->render('wall_delete', [
257
            'post' => $wallPost,
258
            'model' => $wallModel->filter()
259
        ]);
260
    }
261
262
    /**
263
     * Show user messages (based on ajax, all in template)
264
     * @return string
265
     * @throws \Ffcms\Core\Exception\SyntaxException
266
     * @throws \Ffcms\Core\Exception\NativeException
267
     * @throws ForbiddenException
268
     */
269
    public function actionMessages()
270
    {
271
        if (!App::$User->isAuth()) {
272
            throw new ForbiddenException();
273
        }
274
275
        return App::$View->render('messages');
276
    }
277
278
    public function actionNotifications($type = 'all')
279
    {
280
        if (!App::$User->isAuth()) {
281
            throw new ForbiddenException();
282
        }
283
284
        // get page index and current user object
285
        $page = (int)App::$Request->query->get('page', 0);
286
        $offset = $page * static::NOTIFY_PER_PAGE;
287
        $user = App::$User->identity();
288
289
        // try to find notifications in database as active record
290
        $query = UserNotification::where('user_id', '=', $user->id)
0 ignored issues
show
Bug introduced by
Accessing id on the interface Ffcms\Core\Interfaces\iUser suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
291
            ->orderBy('created_at', 'DESC');
292
        if ($type === 'unread') {
293
            $query = $query->where('readed', '=', 0);
294
        }
295
296
        $pagination = new SimplePagination([
297
            'url' => ['profile/notifications'],
298
            'page' => $page,
299
            'step' => static::NOTIFY_PER_PAGE,
300
            'total' => $query->count()
301
        ]);
302
303
        // get current records as object and build response
304
        $records = $query->skip($offset)->take(static::NOTIFY_PER_PAGE)->get();
305
        $model = new EntityNotificationsList($records);
306
        $model->make();
307
308
        return App::$View->render('notifications', [
309
            'model' => $model,
310
            'pagination' => $pagination
311
        ]);
312
    }
313
314
    /**
315
     * User profile settings
316
     * @return string
317
     * @throws \Ffcms\Core\Exception\SyntaxException
318
     * @throws \Ffcms\Core\Exception\NativeException
319
     * @throws ForbiddenException
320
     */
321 View Code Duplication
    public function actionSettings()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
322
    {
323
        // check if auth
324
        if (!App::$User->isAuth()) {
325
            throw new ForbiddenException();
326
        }
327
        // get user object
328
        $user = App::$User->identity();
329
        // create model and pass user object
330
        $model = new FormSettings($user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by \Ffcms\Core\App::$User->identity() on line 328 can be null; however, Apps\Model\Front\Profile...Settings::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
331
332
        // check if form is submited
333
        if ($model->send() && $model->validate()) {
334
            $model->save();
335
            App::$Session->getFlashBag()->add('success', __('Profile data are successful updated'));
336
        }
337
338
        // render view
339
        return App::$View->render('settings', [
340
            'model' => $model->filter()
341
        ]);
342
    }
343
344
    /**
345
     * Action change user password
346
     * @return string
347
     * @throws \Ffcms\Core\Exception\SyntaxException
348
     * @throws \Ffcms\Core\Exception\NativeException
349
     * @throws ForbiddenException
350
     */
351 View Code Duplication
    public function actionPassword()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
352
    {
353
        // check if user is authed
354
        if (!App::$User->isAuth()) {
355
            throw new ForbiddenException();
356
        }
357
358
        // get user object and create model with user object
359
        $user = App::$User->identity();
360
        $model = new FormPasswordChange($user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by \Ffcms\Core\App::$User->identity() on line 359 can be null; however, Apps\Model\Front\Profile...rdChange::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
361
362
        // check if form is submited and validation is passed
363
        if ($model->send() && $model->validate()) {
364
            $model->make();
365
            App::$Session->getFlashBag()->add('success', __('Password is successful changed'));
366
        }
367
368
        // set response output
369
        return App::$View->render('password', [
370
            'model' => $model->filter()
371
        ]);
372
    }
373
374
    /**
375
     * Show users in blacklist and allow add new users
376
     * @return string
377
     * @throws \Ffcms\Core\Exception\SyntaxException
378
     * @throws \Ffcms\Core\Exception\NativeException
379
     * @throws ForbiddenException
380
     */
381
    public function actionIgnore()
382
    {
383
        // check if not auth
384
        if (!App::$User->isAuth()) {
385
            throw new ForbiddenException();
386
        }
387
388
        // get user object and init model of it
389
        $user = App::$User->identity();
390
        $model = new FormIgnoreAdd($user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by \Ffcms\Core\App::$User->identity() on line 389 can be null; however, Apps\Model\Front\Profile...gnoreAdd::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
391
392
        // set user id from ?id= get param if form not sended
393
        if (!$model->send()) {
394
            $uid = (int)App::$Request->query->get('id');
395
            if ($uid > 0) {
396
                $model->id = $uid;
397
            }
398
        }
399
400
        // sended new block add?
401
        if ($model->send() && $model->validate()) {
402
            if ($model->save()) {
403
                App::$Session->getFlashBag()->add('success', __('User was successful blocked!'));
404
            } else {
405
                App::$Session->getFlashBag()->add('error', __('This user is always in ignore list'));
406
            }
407
        }
408
409
        // get blocked users
410
        $records = Blacklist::where('user_id', '=', $user->getId());
411
412
        $page = (int)App::$Request->query->get('page');
413
        $offset = $page * self::BLOCK_PER_PAGE;
414
415
        // build pagination
416
        $pagination = new SimplePagination([
417
            'url' => ['profile/ignore'],
418
            'page' => $page,
419
            'step' => self::BLOCK_PER_PAGE,
420
            'total' => $records->count()
421
        ]);
422
423
        return App::$View->render('ignore', [
424
            'records' => $records->skip($offset)->take(self::BLOCK_PER_PAGE)->get(),
425
            'model' => $model->filter(),
426
            'pagination' => $pagination
427
        ]);
428
    }
429
430
    /**
431
     * Show user logs
432
     * @return string
433
     * @throws \Ffcms\Core\Exception\SyntaxException
434
     * @throws \Ffcms\Core\Exception\NativeException
435
     * @throws ForbiddenException
436
     */
437
    public function actionLog()
438
    {
439
        // check if user is authorized
440
        if (!App::$User->isAuth()) {
441
            throw new ForbiddenException();
442
        }
443
444
        // get user object
445
        $user = App::$User->identity();
446
447
        // get log records
448
        $records = $user->getLogs();
449
        if ($records !== null && $records->count() > 0) {
450
            $records = $records->orderBy('id', 'DESC');
451
        }
452
453
        return App::$View->render('log', [
454
            'records' => $records
455
        ]);
456
    }
457
458
    /**
459
     * Unblock always blocked user
460
     * @param string $target_id
461
     * @return string
462
     * @throws \Ffcms\Core\Exception\SyntaxException
463
     * @throws \Ffcms\Core\Exception\NativeException
464
     * @throws ForbiddenException
465
     * @throws NotFoundException
466
     */
467
    public function actionUnblock($target_id)
468
    {
469
        // check if user is auth
470
        if (!App::$User->isAuth()) {
471
            throw new ForbiddenException();
472
        }
473
474
        // check if target is defined
475 View Code Duplication
        if (!Obj::isLikeInt($target_id) || $target_id < 1 || !App::$User->isExist($target_id)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
476
            throw new NotFoundException();
477
        }
478
479
        $user = App::$User->identity();
480
481
        // check if target user in blacklist of current user
482
        if (!Blacklist::have($user->getId(), $target_id)) {
483
            throw new NotFoundException();
484
        }
485
486
        $model = new FormIgnoreDelete($user, $target_id);
0 ignored issues
show
Bug introduced by
It seems like $user defined by \Ffcms\Core\App::$User->identity() on line 479 can be null; however, Apps\Model\Front\Profile...reDelete::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
487
        if ($model->send() && $model->validate()) {
488
            $model->make();
489
            App::$Response->redirect(Url::to('profile/ignore'));
490
        }
491
492
        return App::$View->render('unblock', [
493
            'model' => $model->filter()
494
        ]);
495
    }
496
497
    /**
498
     * Search users
499
     * @return string
500
     * @throws \Ffcms\Core\Exception\SyntaxException
501
     * @throws \Ffcms\Core\Exception\NativeException
502
     */
503
    public function actionSearch()
504
    {
505
        // create model object
506
        $model = new FormUserSearch();
507
        $model->setSubmitMethod('GET');
508
509
        // get app configs
510
        $cfgs = Serialize::decode($this->application->configs);
511
512
        $records = null;
513
        $pagination = null;
514
        // check if request is sended
515
        if ($model->send() && $model->validate()) {
516
            // get records from db
517
            $records = ProfileRecords::where('nick', 'like', '%' . $model->query . '%');
518
            $page = (int)App::$Request->query->get('page');
519
            $userPerPage = (int)$cfgs['usersOnPage'];
520
            if ($userPerPage < 1) {
521
                $userPerPage = 1;
522
            }
523
            $offset = $page * $userPerPage;
524
            // build pagination
525
            $pagination = new SimplePagination([
526
                'url' => ['profile/search', null, null, [$model->getFormName().'[query]' => $model->query, $model->getFormName().'[submit]' => true]],
527
                'page' => $page,
528
                'step' => $userPerPage,
529
                'total' => $records->count()
530
            ]);
531
            // make query finally
532
            $records = $records->skip($offset)->take($userPerPage)->get();
533
534
        }
535
536
        // display response
537
        return App::$View->render('search', [
538
            'model' => $model->filter(),
539
            'records' => $records,
540
            'pagination' => $pagination,
541
            'ratingOn' => (int)$cfgs['rating']
542
        ]);
543
    }
544
545
    /**
546
     * Cron schedule - build user profiles sitemap
547
     */
548
    public static function buildSitemapSchedule()
549
    {
550
        // get not empty user profiles
551
        $profiles = ProfileRecords::whereNotNull('nick');
552
        if ($profiles->count() < 1) {
553
            return;
554
        }
555
556
        // get languages if multilanguage enabled
557
        $langs = null;
558
        if (App::$Properties->get('multiLanguage')) {
559
            $langs = App::$Properties->get('languages');
560
        }
561
562
        // build sitemap from content items via business model
563
        $sitemap = new EntityBuildMap($langs);
564
        foreach ($profiles->get() as $user) {
565
            $sitemap->add('profile/show/' . $user->user_id, $user->updated_at, 'weekly', 0.2);
566
        }
567
568
        $sitemap->save('profile');
569
    }
570
}