Passed
Push — master ( 02a4a5...02a4a5 )
by Mihail
04:38
created

Profile::cleanupTablesSchedule()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
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 0
dl 0
loc 7
rs 9.4285
1
<?php
2
3
namespace Apps\Controller\Front;
4
5
use Apps\ActiveRecord\Blacklist;
6
use Apps\ActiveRecord\UserLog;
7
use Apps\ActiveRecord\UserNotification;
8
use Apps\ActiveRecord\WallPost;
9
use Apps\Model\Front\Profile\EntityNotificationsList;
10
use Apps\Model\Front\Profile\FormAvatarUpload;
11
use Apps\Model\Front\Profile\FormIgnoreAdd;
12
use Apps\Model\Front\Profile\FormIgnoreDelete;
13
use Apps\Model\Front\Profile\FormPasswordChange;
14
use Apps\Model\Front\Profile\FormSettings;
15
use Apps\Model\Front\Profile\FormUserSearch;
16
use Apps\Model\Front\Profile\FormWallPostDelete;
17
use Apps\Model\Front\Profile\FormWallPost;
18
use Apps\Model\Front\Sitemap\EntityBuildMap;
19
use Extend\Core\Arch\FrontAppController;
20
use Ffcms\Core\App;
21
use Ffcms\Core\Exception\ForbiddenException;
22
use Ffcms\Core\Exception\NotFoundException;
23
use Ffcms\Core\Helper\HTML\SimplePagination;
24
use Ffcms\Core\Helper\Text;
25
use Ffcms\Core\Helper\Type\Obj;
26
use Ffcms\Core\Helper\Serialize;
27
use Ffcms\Core\Helper\Type\Str;
28
use Apps\ActiveRecord\Profile as ProfileRecords;
29
use Ffcms\Core\Helper\Url;
30
31
32
/**
33
 * Class Profile - user profiles interaction
34
 * @package Apps\Controller\Front
35
 */
36
class Profile extends FrontAppController
37
{
38
    const BLOCK_PER_PAGE = 10;
39
    const NOTIFY_PER_PAGE = 25;
40
41
    /**
42
     * List user profiles on website by defined filter
43
     * @param string $filter_name
44
     * @param null|string|int $filter_value
45
     * @return string
46
     * @throws \Ffcms\Core\Exception\NativeException
47
     * @throws NotFoundException
48
     * @throws \Ffcms\Core\Exception\SyntaxException
49
     */
50
    public function actionIndex($filter_name, $filter_value = null)
51
    {
52
        $records = null;
53
54
        // set current page and offset
55
        $page = (int)App::$Request->query->get('page', 0);
56
        $cfgs = Serialize::decode($this->application->configs);
57
        $userPerPage = (int)$cfgs['usersOnPage'];
58
        if ($userPerPage < 1) {
59
            $userPerPage = 1;
60
        }
61
        $offset = $page * $userPerPage;
62
63
        switch ($filter_name) {
64
            case 'rating': // rating list, order by rating DESC
65
                // check if rating is enabled
66
                if ((int)$cfgs['rating'] !== 1) {
67
                    throw new NotFoundException();
68
                }
69
                $records = (new ProfileRecords())->orderBy('rating', 'DESC');
70
                break;
71
            case 'hobby': // search by hobby
72
                if (Str::likeEmpty($filter_value)) {
0 ignored issues
show
Bug introduced by
It seems like $filter_value defined by parameter $filter_value on line 50 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...
73
                    throw new NotFoundException();
74
                }
75
                $records = (new ProfileRecords())->where('hobby', 'like', '%' . $filter_value . '%');
76
                break;
77
            case 'city':
78
                if (Str::likeEmpty($filter_value)) {
0 ignored issues
show
Bug introduced by
It seems like $filter_value defined by parameter $filter_value on line 50 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...
79
                    throw new NotFoundException();
80
                }
81
                $records = (new ProfileRecords())->where('city', '=', $filter_value);
82
                break;
83
            case 'born':
84
                if ($filter_value === null || !Obj::isLikeInt($filter_value)) {
85
                    throw new NotFoundException();
86
                }
87
                $records = (new ProfileRecords())->where('birthday', 'like', $filter_value . '-%');
88
                break;
89
            case 'all':
90
                $records = (new ProfileRecords())->orderBy('id', 'DESC');
91
                break;
92
            default:
93
                App::$Response->redirect('profile/index/all');
94
                break;
95
        }
96
97
        // build pagination
98
        $pagination = new SimplePagination([
99
            'url' => ['profile/index', $filter_name, $filter_value],
100
            'page' => $page,
101
            'step' => $userPerPage,
102
            'total' => $records->count()
103
        ]);
104
105
        return App::$View->render('index', [
106
            'records' => $records->skip($offset)->take($userPerPage)->get(),
107
            'pagination' => $pagination,
108
            'id' => $filter_name,
109
            'add' => $filter_value,
110
            'ratingOn' => (int)$cfgs['rating']
111
        ]);
112
    }
113
114
    /**
115
     * Show user profile: data, wall posts, other features
116
     * @param int $userId
117
     * @return string
118
     * @throws \Ffcms\Core\Exception\SyntaxException
119
     * @throws \Ffcms\Core\Exception\NativeException
120
     * @throws NotFoundException
121
     * @throws ForbiddenException
122
     */
123
    public function actionShow($userId)
124
    {
125
        $cfg = Serialize::decode($this->application->configs);
126 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...
127
            throw new ForbiddenException(__('You must login to view other profile'));
128
        }
129
        // check if target exists
130
        if (!App::$User->isExist($userId)) {
131
            throw new NotFoundException(__('This profile is not exist'));
132
        }
133
134
        $targetPersone = App::$User->identity($userId); // target user object instance of Apps\ActiveRecord\User
135
        $viewerPersone = App::$User->identity(); // current user object(viewer) instance of Apps\ActiveRecord\User
136
137
        $wallModel = null;
138
        // if current user is auth - allow to post messages on wall current user
139
        if (App::$User->isAuth() && $viewerPersone->getRole()->can('global/write')) {
140
            $wallModel = new FormWallPost();
141
            // check if request post is done and rules validated
142
            if ($wallModel->send() && $wallModel->validate()) {
143
                // maybe in blacklist?
144
                if (!Blacklist::check($viewerPersone->getId(), $targetPersone->getId())) {
145
                    App::$Session->getFlashBag()->add('error', __('This user are in your black list or you are in blacklist!'));
146
                } else {
147
                    // check if message added
148
                    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 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...
Bug introduced by
It seems like $viewerPersone defined by \Ffcms\Core\App::$User->identity() on line 135 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...
149
                        App::$Session->getFlashBag()->add('success', __('The message was successful posted!'));
150
                    } else {
151
                        App::$Session->getFlashBag()->add('warning', __('Posting message was failed! Please, wait few seconds'));
152
                    }
153
                }
154
            }
155
        }
156
157
        $query = $targetPersone->getWall(); // relation hasMany from users to walls
158
        // pagination and query params
159
        $wallPage = (int)App::$Request->query->get('page');
160
        $wallItems = (int)$cfg['wallPostOnPage'];
161
        $wallOffset = $wallPage * $wallItems;
162
163
        // build pagination
164
        $wallPagination = new SimplePagination([
165
            'url' => ['profile/show', $userId, null],
166
            'page' => $wallPage,
167
            'step' => $wallItems,
168
            'total' => $query->count()
169
        ]);
170
171
        // get wall messages
172
        $wallRecords = $query->orderBy('id', 'desc')->skip($wallOffset)->take($wallItems)->get();
173
174
        return App::$View->render('show', [
175
            'user' => $targetPersone,
176
            'viewer' => $viewerPersone,
177
            '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...
178
            'wall' => !Obj::isObject($wallModel) ? null : $wallModel->filter(),
179
            'notify' => App::$Session->getFlashBag()->all(),
180
            'wallRecords' => $wallRecords,
181
            'pagination' => $wallPagination,
182
            'ratingOn' => (int)$cfg['rating'] === 1
183
        ]);
184
    }
185
186
    /**
187
     * User avatar management
188
     * @throws \Ffcms\Core\Exception\NativeException
189
     * @throws \Ffcms\Core\Exception\SyntaxException
190
     */
191
    public function actionAvatar()
192
    {
193
        if (!App::$User->isAuth()) {
194
            throw new ForbiddenException('You must be authorized user!');
195
        }
196
197
        // get user identity and model object
198
        $user = App::$User->identity();
199
        $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...
200
201
        // validate model post data
202
        if ($model->send()) {
203
            if ($model->validate()) {
204
                $model->copyFile($user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by \Ffcms\Core\App::$User->identity() on line 198 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...
205
                App::$Session->getFlashBag()->add('success', __('Avatar is successful changed'));
206
            } else {
207
                App::$Session->getFlashBag()->add('error', __('File upload is failed!'));
208
            }
209
        }
210
211
        return App::$View->render('avatar', [
212
            'user' => $user,
213
            'model' => $model
214
        ]);
215
    }
216
217
    /**
218
     * Allow post owners and targets delete
219
     * @param int $postId
220
     * @return string
221
     * @throws \Ffcms\Core\Exception\SyntaxException
222
     * @throws \Ffcms\Core\Exception\NativeException
223
     * @throws ForbiddenException
224
     * @throws NotFoundException
225
     */
226
    public function actionWalldelete($postId)
227
    {
228
        // is user auth?
229
        if (!App::$User->isAuth()) {
230
            throw new ForbiddenException();
231
        }
232
233
        // is postId is integer?
234
        if (!Obj::isLikeInt($postId) || $postId < 1) {
235
            throw new NotFoundException();
236
        }
237
238
        // try to find the wall post
239
        $wallPost = WallPost::find($postId);
240
        if (null === $wallPost || false === $wallPost) {
241
            throw new NotFoundException();
242
        }
243
244
        // get user and check if he can delete this post
245
        $user = App::$User->identity();
246
        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...
247
            throw new ForbiddenException();
248
        }
249
250
        // check if submit sended
251
        $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...
252
        if ($wallModel->send() && $wallModel->validate()) {
253
            $wallModel->make();
254
            App::$Response->redirect('profile/show/' . $wallPost->target_id);
255
        }
256
257
        return App::$View->render('wall_delete', [
258
            'post' => $wallPost,
259
            'model' => $wallModel->filter()
260
        ]);
261
    }
262
263
    /**
264
     * Show user messages (based on ajax, all in template)
265
     * @return string
266
     * @throws \Ffcms\Core\Exception\SyntaxException
267
     * @throws \Ffcms\Core\Exception\NativeException
268
     * @throws ForbiddenException
269
     */
270
    public function actionMessages()
271
    {
272
        if (!App::$User->isAuth()) {
273
            throw new ForbiddenException();
274
        }
275
276
        return App::$View->render('messages');
277
    }
278
279
    /**
280
     * Show user notifications
281
     * @param string $type
282
     * @return string
283
     * @throws \Ffcms\Core\Exception\NativeException
284
     * @throws ForbiddenException
285
     * @throws \Ffcms\Core\Exception\SyntaxException
286
     */
287
    public function actionNotifications($type = 'all')
288
    {
289
        if (!App::$User->isAuth()) {
290
            throw new ForbiddenException();
291
        }
292
293
        // get page index and current user object
294
        $page = (int)App::$Request->query->get('page', 0);
295
        $offset = $page * static::NOTIFY_PER_PAGE;
296
        $user = App::$User->identity();
297
298
        // try to find notifications in database as active record
299
        $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...
300
            ->orderBy('created_at', 'DESC');
301
        if ($type === 'unread') {
302
            $query = $query->where('readed', '=', 0);
303
        }
304
305
        $pagination = new SimplePagination([
306
            'url' => ['profile/notifications'],
307
            'page' => $page,
308
            'step' => static::NOTIFY_PER_PAGE,
309
            'total' => $query->count()
310
        ]);
311
312
        // get current records as object and build response
313
        $records = $query->skip($offset)->take(static::NOTIFY_PER_PAGE);
314
        $data = $records->get();
315
        $model = new EntityNotificationsList($data);
316
        $model->make();
317
318
        // update reader records
319
        $records->update(['readed' => 1]);
320
321
        return App::$View->render('notifications', [
322
            'model' => $model,
323
            'pagination' => $pagination
324
        ]);
325
    }
326
327
    /**
328
     * User profile settings
329
     * @return string
330
     * @throws \Ffcms\Core\Exception\SyntaxException
331
     * @throws \Ffcms\Core\Exception\NativeException
332
     * @throws ForbiddenException
333
     */
334 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...
335
    {
336
        // check if auth
337
        if (!App::$User->isAuth()) {
338
            throw new ForbiddenException();
339
        }
340
        // get user object
341
        $user = App::$User->identity();
342
        // create model and pass user object
343
        $model = new FormSettings($user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by \Ffcms\Core\App::$User->identity() on line 341 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...
344
345
        // check if form is submited
346
        if ($model->send() && $model->validate()) {
347
            $model->save();
348
            App::$Session->getFlashBag()->add('success', __('Profile data are successful updated'));
349
        }
350
351
        // render view
352
        return App::$View->render('settings', [
353
            'model' => $model->filter()
354
        ]);
355
    }
356
357
    /**
358
     * Action change user password
359
     * @return string
360
     * @throws \Ffcms\Core\Exception\SyntaxException
361
     * @throws \Ffcms\Core\Exception\NativeException
362
     * @throws ForbiddenException
363
     */
364 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...
365
    {
366
        // check if user is authed
367
        if (!App::$User->isAuth()) {
368
            throw new ForbiddenException();
369
        }
370
371
        // get user object and create model with user object
372
        $user = App::$User->identity();
373
        $model = new FormPasswordChange($user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by \Ffcms\Core\App::$User->identity() on line 372 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...
374
375
        // check if form is submited and validation is passed
376
        if ($model->send() && $model->validate()) {
377
            $model->make();
378
            App::$Session->getFlashBag()->add('success', __('Password is successful changed'));
379
        }
380
381
        // set response output
382
        return App::$View->render('password', [
383
            'model' => $model->filter()
384
        ]);
385
    }
386
387
    /**
388
     * Show users in blacklist and allow add new users
389
     * @return string
390
     * @throws \Ffcms\Core\Exception\SyntaxException
391
     * @throws \Ffcms\Core\Exception\NativeException
392
     * @throws ForbiddenException
393
     */
394
    public function actionIgnore()
395
    {
396
        // check if not auth
397
        if (!App::$User->isAuth()) {
398
            throw new ForbiddenException();
399
        }
400
401
        // get user object and init model of it
402
        $user = App::$User->identity();
403
        $model = new FormIgnoreAdd($user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by \Ffcms\Core\App::$User->identity() on line 402 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...
404
405
        // set user id from ?id= get param if form not sended
406
        if (!$model->send()) {
407
            $uid = (int)App::$Request->query->get('id');
408
            if ($uid > 0) {
409
                $model->id = $uid;
410
            }
411
        }
412
413
        // sended new block add?
414
        if ($model->send() && $model->validate()) {
415
            if ($model->save()) {
416
                App::$Session->getFlashBag()->add('success', __('User was successful blocked!'));
417
            } else {
418
                App::$Session->getFlashBag()->add('error', __('This user is always in ignore list'));
419
            }
420
        }
421
422
        // get blocked users
423
        $records = Blacklist::where('user_id', '=', $user->getId());
424
425
        $page = (int)App::$Request->query->get('page');
426
        $offset = $page * self::BLOCK_PER_PAGE;
427
428
        // build pagination
429
        $pagination = new SimplePagination([
430
            'url' => ['profile/ignore'],
431
            'page' => $page,
432
            'step' => self::BLOCK_PER_PAGE,
433
            'total' => $records->count()
434
        ]);
435
436
        return App::$View->render('ignore', [
437
            'records' => $records->skip($offset)->take(self::BLOCK_PER_PAGE)->get(),
438
            'model' => $model->filter(),
439
            'pagination' => $pagination
440
        ]);
441
    }
442
443
    /**
444
     * Show user logs
445
     * @return string
446
     * @throws \Ffcms\Core\Exception\SyntaxException
447
     * @throws \Ffcms\Core\Exception\NativeException
448
     * @throws ForbiddenException
449
     */
450
    public function actionLog()
451
    {
452
        // check if user is authorized
453
        if (!App::$User->isAuth()) {
454
            throw new ForbiddenException();
455
        }
456
457
        // get user object
458
        $user = App::$User->identity();
459
460
        // get log records
461
        $records = $user->getLogs();
462
        if ($records !== null && $records->count() > 0) {
463
            $records = $records->orderBy('id', 'DESC');
464
        }
465
466
        return App::$View->render('log', [
467
            'records' => $records
468
        ]);
469
    }
470
471
    /**
472
     * Unblock always blocked user
473
     * @param string $target_id
474
     * @return string
475
     * @throws \Ffcms\Core\Exception\SyntaxException
476
     * @throws \Ffcms\Core\Exception\NativeException
477
     * @throws ForbiddenException
478
     * @throws NotFoundException
479
     */
480
    public function actionUnblock($target_id)
481
    {
482
        // check if user is auth
483
        if (!App::$User->isAuth()) {
484
            throw new ForbiddenException();
485
        }
486
487
        // check if target is defined
488 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...
489
            throw new NotFoundException();
490
        }
491
492
        $user = App::$User->identity();
493
494
        // check if target user in blacklist of current user
495
        if (!Blacklist::have($user->getId(), $target_id)) {
496
            throw new NotFoundException();
497
        }
498
499
        $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 492 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...
500
        if ($model->send() && $model->validate()) {
501
            $model->make();
502
            App::$Response->redirect(Url::to('profile/ignore'));
503
        }
504
505
        return App::$View->render('unblock', [
506
            'model' => $model->filter()
507
        ]);
508
    }
509
510
    /**
511
     * Search users
512
     * @return string
513
     * @throws \Ffcms\Core\Exception\SyntaxException
514
     * @throws \Ffcms\Core\Exception\NativeException
515
     */
516
    public function actionSearch()
517
    {
518
        // create model object
519
        $model = new FormUserSearch();
520
        $model->setSubmitMethod('GET');
521
522
        // get app configs
523
        $cfgs = Serialize::decode($this->application->configs);
524
525
        $records = null;
526
        $pagination = null;
527
        // check if request is sended
528
        if ($model->send() && $model->validate()) {
529
            // get records from db
530
            $records = ProfileRecords::where('nick', 'like', '%' . $model->query . '%');
531
            $page = (int)App::$Request->query->get('page');
532
            $userPerPage = (int)$cfgs['usersOnPage'];
533
            if ($userPerPage < 1) {
534
                $userPerPage = 1;
535
            }
536
            $offset = $page * $userPerPage;
537
            // build pagination
538
            $pagination = new SimplePagination([
539
                'url' => ['profile/search', null, null, [$model->getFormName().'[query]' => $model->query, $model->getFormName().'[submit]' => true]],
540
                'page' => $page,
541
                'step' => $userPerPage,
542
                'total' => $records->count()
543
            ]);
544
            // make query finally
545
            $records = $records->skip($offset)->take($userPerPage)->get();
546
547
        }
548
549
        // display response
550
        return App::$View->render('search', [
551
            'model' => $model->filter(),
552
            'records' => $records,
553
            'pagination' => $pagination,
554
            'ratingOn' => (int)$cfgs['rating']
555
        ]);
556
    }
557
558
    /**
559
     * Cron schedule - build user profiles sitemap
560
     */
561
    public static function buildSitemapSchedule()
562
    {
563
        // get not empty user profiles
564
        $profiles = ProfileRecords::whereNotNull('nick');
565
        if ($profiles->count() < 1) {
566
            return;
567
        }
568
569
        // get languages if multilanguage enabled
570
        $langs = null;
571
        if (App::$Properties->get('multiLanguage')) {
572
            $langs = App::$Properties->get('languages');
573
        }
574
575
        // build sitemap from content items via business model
576
        $sitemap = new EntityBuildMap($langs);
577
        foreach ($profiles->get() as $user) {
578
            $sitemap->add('profile/show/' . $user->user_id, $user->updated_at, 'weekly', 0.2);
579
        }
580
581
        $sitemap->save('profile');
582
    }
583
584
    /**
585
     * Cleanup tables as scheduled action
586
     */
587
    public static function cleanupTablesSchedule()
588
    {
589
        // calculate date (now - 1week) for sql query 
590
        $date = (new \DateTime('now'))->modify('-1 week')->format('Y-m-d');
591
        UserNotification::where('created_at', '<=', $date)->delete();
592
        UserLog::where('created_at', '<=', $date)->delete();
593
    }
594
}