Test Failed
Push — master ( e3c39f...fe570d )
by Mihail
07:20
created

Apps/View/Front/default/profile/show.php (8 issues)

1
<?php
2
3
use Apps\ActiveRecord\ProfileField;
4
use Ffcms\Core\Helper\Date;
5
use Ffcms\Core\Helper\Type\Any;
6
use Ffcms\Core\Helper\Type\Str;
7
use Ffcms\Templex\Url\Url;
0 ignored issues
show
This use statement conflicts with another class in this namespace, Url. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
8
9
/** @var Apps\ActiveRecord\User $user Target user object */
10
/** @var Apps\ActiveRecord\User $viewer Viewer user object */
11
/** @var Apps\ActiveRecord\WallPost $wallRecords */
12
/** @var \Apps\Model\Front\Profile\FormWallPost $wall */
13
/** @var array $notify */
14
/** @var bool $isSelf */
15
/** @var bool $ratingOn */
16
/** @var array $pagination */
17
/** @var Ffcms\Templex\Template\Template $this */
18
19
// $user is a target profile depended object(not current user!!!)
20
21
$name = $user->profile === null ? __('Unknown') : $user->profile->getNickname();
22
23
$this->layout('_layouts/default', [
24
    'title' => __('Profile') . ': ' . $name,
25
    'breadcrumbs' => [
26
        Url::to('/') => __('Home'),
27
        __('Profile') . ': ' . $name
28
    ]
29
]);
30
31
?>
32
<?php $this->start('body') ?>
33
<div class="row">
34
    <div class="col-md-12">
35
        <h1><?= $name ?> <sup><small>id: <?= $user->id; ?></small></sup></h1>
36
    </div>
37
</div>
38
<hr/>
39
<?php if (\App::$User->isAuth() && $user->inBlacklist($viewer->getId())): ?>
40
    <p class="alert alert-danger"><?= __('You are in blacklist of this user. Your access is limited.') ?></p>
41
<?php endif; ?>
42
<div class="row">
43
    <div class="col-md-4">
44
        <img src="<?= $user->profile->getAvatarUrl('big') ?>" class="img-fluid img-thumbnail" />
45
        <?php if ($ratingOn):
46
            $rateClass = 'btn-secondary';
47
            $rateValue = (int)$user->profile->rating;
48
            if ($user->profile->rating > 0) {
49
                $rateClass = 'btn-info';
50
            } elseif ($user->profile->rating < 0) {
51
                $rateClass = 'btn-warning';
52
            }
53
            ?>
54
            <?php if ($isSelf): ?>
55
            <div class="row">
56
                <div class="col-md-12">
57
                    <button type="button" href="javascript:void(0);" class="btn btn-block <?= $rateClass ?>">
58
                        <?= __('Rating') ?>: <span class="badge"><?= $rateValue ?></span>
59
                    </button>
60
                </div>
61
            </div>
62
            <?php else: ?>
63
                <div class="row">
64
                    <div class="col-md-8" style="padding-right: 0;">
65
                        <a href="javascript:void(0);" class="btn btn-block <?= $rateClass ?>">
66
                            <?= __('Rating') ?>:
67
                            <span class="badge"><?= $rateValue > 0 ? '+' : null ?>
68
                                <span id="ratingValue"><?= $rateValue ?></span>
69
                        </span>
70
                        </a>
71
                    </div>
72
                    <div class="col-md-2" style="padding-left: 1px;padding-right: 0;">
73
                        <button id="addRating" class="btn btn-block btn-success">+</button>
74
                    </div>
75
                    <div class="col-md-2" style="padding-left: 1px; padding-right: 0;">
76
                        <button class="btn btn-block btn-danger" id="reduceRating">-</button>
77
                    </div>
78
                </div>
79
            <?php endif; ?>
80
        <?php endif; ?>
81
        <?php
82
        $userMenu = $this->bootstrap()->nav('ul', ['class' => 'nav-tabs flex-column']);
83
        if ($isSelf) {
84
            $userMenu->menu(['link' => ['profile/feed'], 'text' => '<i class="fa fa-rss-square"></i> ' . __('Feed'), 'html' => true]);
85
            $userMenu->menu(['link' => ['profile/avatar'], 'text' => '<i class="fa fa-camera"></i> ' . __('Avatar'), 'html' => true]);
86
            $userMenu->menu(['link' => ['profile/messages'], 'text' => '<i class="fa fa-envelope"></i> ' . __('Messages') . ' <span class="badge pm-count-block">0</span>', 'html' => true]);
87
            $userMenu->menu(['link' => ['profile/settings'], 'text' => '<i class="fa fa-cogs"></i> ' . __('Settings'), 'html' => true]);
88
        } else if(\App::$User->isAuth()) {
89
            $userMenu->menu(['link' => ['profile/messages', null, ['newdialog' => $user->id]], 'text' => __('Write message')]);
90
            $userMenu->menu(['link' => ['profile/ignore', null, ['id' => $user->id]], 'text' => __('Block')]);
91
        }
92
        echo $userMenu->display();
93
        ?>
94
    </div>
95
    <div class="col-md-8">
96
        <h2><?= __('Profile data'); ?></h2>
97
        <div class="table-responsive">
98
            <table class="table table-striped">
99
                <tr>
100
                    <td><?= __('Group') ?></td>
101
                    <td><span class="badge badge-secondary" style="background-color: <?= $user->role->color ?>;"><?= $user->role->name ?></span></td>
102
                </tr>
103
                <tr>
104
                    <td><?= __('Join date'); ?></td>
105
                    <td><?= Date::convertToDatetime($user->created_at, Date::FORMAT_TO_DAY); ?></td>
0 ignored issues
show
Are you sure Ffcms\Core\Helper\Date::...er\Date::FORMAT_TO_DAY) of type false|string can be used in echo? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

105
                    <td><?= /** @scrutinizer ignore-type */ Date::convertToDatetime($user->created_at, Date::FORMAT_TO_DAY); ?></td>
Loading history...
106
                </tr>
107
                <?php if ($user->profile->birthday !== null && !Str::startsWith('0000-', $user->profile->birthday)): ?>
108
                    <tr>
109
                        <td><?= __('Birthday'); ?></td>
110
                        <td>
111
                            <?= Url::a(
112
                                ['profile/index', ['born', Date::convertToDatetime($user->profile->birthday, 'Y')]],
113
                                Date::convertToDatetime($user->profile->birthday, Date::FORMAT_TO_DAY)
0 ignored issues
show
It seems like Ffcms\Core\Helper\Date::...er\Date::FORMAT_TO_DAY) can also be of type false; however, parameter $text of Ffcms\Templex\Url\Url::a() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

113
                                /** @scrutinizer ignore-type */ Date::convertToDatetime($user->profile->birthday, Date::FORMAT_TO_DAY)
Loading history...
114
                            ) ?>
115
                        </td>
116
                    </tr>
117
                <?php endif; ?>
118
                <?php $sex = $user->profile->sex ?>
119
                <tr>
120
                    <td><?= __('Sex'); ?></td>
121
                    <td>
122
                        <?php
123
                        if ($sex == 1) { // could be string(1) "1" or int(1) 1
0 ignored issues
show
Unused Code Comprehensibility introduced by Mihail
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
124
                            echo __('Male');
125
                        } elseif ($sex == 2) {
126
                            echo __('Female');
127
                        } else {
128
                            echo __('Unknown');
129
                        }
130
                        ?>
131
                    </td>
132
                </tr>
133
                <?php if (!Str::likeEmpty($user->profile->phone)): ?>
134
                    <tr>
135
                        <td><?= __('Phone'); ?></td>
136
                        <td><?= $user->profile->phone ?></td>
137
                    </tr>
138
                <?php endif; ?>
139
                <?php if (!Str::likeEmpty($user->profile->url)): ?>
140
                    <tr>
141
                        <td><?= __('Website'); ?></td>
142
                        <td>
143
                            <a rel="nofollow" target="_blank" href="<?= $user->profile->url ?>"><?= __('Visit'); ?></a>
144
                        </td>
145
                    </tr>
146
                <?php endif; ?>
147
                <?php if (!Str::likeEmpty($user->profile->city)):
148
                    $city = trim($user->profile->city);
149
                    ?>
150
                    <tr>
151
                        <td><?= __('City') ?></td>
152
                        <td><?= Url::a(['profile/index', ['city', $city]], $city) ?></td>
153
                    </tr>
154
                <?php endif; ?>
155
                <?php if (!Str::likeEmpty($user->profile->hobby)): ?>
156
                    <tr>
157
                        <td><?= __('Interests'); ?></td>
158
                        <td>
159
                            <?php
160
                            $hobbyArray = explode(',', $user->profile->hobby);
161
                            foreach ($hobbyArray as $item) {
162
                                $item = \App::$Security->strip_tags($item);
163
                                if (!Str::likeEmpty($item)) {
164
                                    echo Url::a(['profile/index', ['hobby', trim($item, ' ')]], $item, ['class' => 'badge badge-secondary']) . ' ';
165
                                }
166
                            }
167
                            ?>
168
                        </td>
169
                    </tr>
170
                <?php endif; ?>
171
                <?php
172
                $customFields = $user->profile->custom_data;
173
                if ($customFields !== null && Any::isArray($customFields) && count($customFields) > 0): ?>
174
                    <?php foreach ($customFields as $cid => $value): ?>
175
                        <?php if (!Str::likeEmpty($value)): ?>
176
                            <tr>
177
                                <td><?= ProfileField::getNameById($cid) ?></td>
0 ignored issues
show
Are you sure Apps\ActiveRecord\ProfileField::getNameById($cid) of type array|null|string can be used in echo? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

177
                                <td><?= /** @scrutinizer ignore-type */ ProfileField::getNameById($cid) ?></td>
Loading history...
178
                                <td>
179
                                    <?php
180
                                    if (ProfileField::getTypeById($cid) === 'link') {
181
                                        echo Url::a($value, Str::sub($value, 30));
182
                                    } else {
183
                                        echo \App::$Security->strip_tags($value);
0 ignored issues
show
Are you sure App::Security->strip_tags($value) of type array|null|string can be used in echo? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

183
                                        echo /** @scrutinizer ignore-type */ \App::$Security->strip_tags($value);
Loading history...
184
                                    }
185
                                    ?>
186
                                </td>
187
                            </tr>
188
                        <?php endif; ?>
189
                    <?php endforeach; ?>
190
                <?php endif; ?>
191
            </table>
192
        </div>
193
        <h2><?= __('Wall') ?></h2>
194
        <?php if ($wall !== null): ?>
195
            <?php $form = $this->form($wall) ?>
196
            <?= $form->start() ?>
197
            <?= $form->field()->textarea('message', ['class' => 'form-control wysiwyg']) ?>
198
            <input type="submit" name="<?= $wall->getFormName() ?>[submit]" value="<?= __('Send') ?>" class="btn btn-primary" />
199
200
            <?php //Ffcms\Widgets\Ckeditor\Ckeditor::widget(['targetClass' => 'wysiwyg', 'config' => 'config-small', 'jsConfig' => ['height' => '80']]); ?>
0 ignored issues
show
Unused Code Comprehensibility introduced by zenn
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
201
            <?= $form->stop() ?>
202
        <?php endif; ?>
203
        <?php
204
        if ($wallRecords !== null):
205
            foreach ($wallRecords as $post):
206
                /** @var \Apps\ActiveRecord\WallPost $post */
207
                ?>
208
                <div class="row object-lightborder" id="wall-post-<?= $post->id ?>">
209
                    <div class="col-xs-4 col-md-2">
210
                        <div class="text-center">
211
                            <img class="img-fluid img-rounded" alt="Avatar of <?= $post->senderUser->profile->getNickname() ?>" src="<?= $post->senderUser->profile->getAvatarUrl('small') ?>" />
212
                        </div>
213
                    </div>
214
                    <div class="col-xs-8 col-md-10">
215
                        <div class="h5" style="margin-top: 0;margin-bottom: 5px;">
216
                            <i class="glyphicon glyphicon-user"></i>
217
                            <?= Url::a(['profile/show', [$post->sender_id]], $post->senderUser->profile->getNickname(), ['style' => 'color: ' . $post->senderUser->role->color]) ?>
218
                            <small class="float-right"><?= Date::humanize($post->updated_at); ?></small>
0 ignored issues
show
Are you sure Ffcms\Core\Helper\Date::...nize($post->updated_at) of type false|string can be used in echo? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

218
                            <small class="float-right"><?= /** @scrutinizer ignore-type */ Date::humanize($post->updated_at); ?></small>
Loading history...
219
                        </div>
220
                        <div class="object-text">
221
                            <?= $post->message ?>
222
                        </div>
223
                        <hr style="margin: 5px;" />
224
                        <div><i class="fa fa-comment"></i>
225
                            <a href="#wall-post-<?= $post->id ?>" id="wall-post-response-<?= $post->id ?>" class="show-wall-response">
226
                                <?= __('Answers') ?> (<span id="wall-post-response-count-<?= $post->id ?>">0</span>)
227
                            </a>
228
                            <?php if ($post->target_id === $viewer->id || $post->sender_id === $viewer->id): ?>
229
                                <?= Url::a(['profile/walldelete', [$post->id]], __('Delete'), ['class' => 'float-right']) ?>
230
                            <?php endif; ?>
231
                        </div>
232
                        <div id="wall-answer-dom-<?= $post->id; ?>" class="d-none"></div>
233
                    </div>
234
                </div>
235
            <?php
236
            endforeach;
237
        endif;
238
        ?>
239
        <?= $this->bootstrap()->pagination(['profile/show', [$user->id]], ['class' => 'pagination justify-content-center'])
240
            ->size($pagination['total'], $pagination['page'], $pagination['step'])
241
            ->display() ?>
242
    </div>
243
</div>
244
245
<!-- add answer dom template -->
246
<div id="add-answer-field" class="d-none">
247
    <hr style="margin: 5px;"/>
248
    <input type="text" id="make-answer" placeHolder="<?= __('Write comment') ?>" class="form-control wall-answer-text" maxlength="200"/>
249
    <a style="margin-top: 5px;" href="#wall-post" class="send-wall-answer btn btn-primary btn-sm" id="send-wall">
250
        <?= __('Send') ?>
251
    </a>
252
    <span class="float-right" id="answer-counter">200</span>
253
</div>
254
<div id="show-answer-list" class="d-none">
255
    <div class="row wall-answer">
256
        <div class="col-md-2 col-xs-4"><img id="wall-answer-avatar" src="<?= \App::$Alias->scriptUrl ?>/upload/user/avatar/small/default.jpg" alt="avatar" class="img-fluid img-rounded avatar" /></div>
257
        <div class="col-md-10 col-xs-8">
258
            <div class="answer-header">
259
                <a href="<?= \App::$Alias->baseUrl ?>/profile/index" id="wall-answer-userlink">unknown</a>
260
                <small class="float-right"><span id="wall-answer-date">01.01.1970</span>
261
                    <a href="#send-wall-object" class="delete-answer d-none" id="delete-answer"><i class="glyphicon glyphicon-remove"></i></a>
262
                </small>
263
            </div>
264
            <div id="wall-answer-text"></div>
265
        </div>
266
    </div>
267
</div>
268
269
270
<script>
271
    var hideAnswers = [];
272
    $(document).ready(function () {
273
        var elements = $('.object-lightborder');
274
        var viewer_id = 0;
275
        var target_id = 0;
276
        var is_self_profile = <?= $isSelf === true ? 'true' : 'false' ?>;
277
        <?php if (\App::$User->isAuth()): ?>
278
        viewer_id = <?= $viewer->getId() ?>;
279
        <?php endif; ?>
280
        target_id = <?= $user->getId() ?>;
281
        var postIds = [];
282
        $.each(elements, function (key, val) {
283
            postIds.push(val.id.replace('wall-post-', ''));
284
        });
285
286
        // load answers count via JSON
287
        if (postIds.length > 0) {
288
            $.getJSON(script_url + '/api/profile/wallanswercount/' + postIds.join(',') + '?lang=' + script_lang, function (json) {
289
                // data is successful loaded, lets parse it and set to exist dom elements as text value
290
                if (json.status === 1) {
291
                    $.each(json.data, function (key, val) {
292
                        $('#wall-post-response-count-' + key).text(val);
293
                    });
294
                }
295
            });
296
        }
297
298
        // load answers via JSON and add to current DOM
299
        loadAnswers = function (postId) {
300
            $.getJSON(script_url + '/api/profile/showwallanswers/' + postId + '?lang=' + script_lang, function (json) {
301
                if (json.status !== 1) {
302
                    return null;
303
                }
304
305
                var answerField = $('#add-answer-field').clone();
306
                var answerDom = $('#show-answer-list').clone();
307
                answerField.removeAttr('id').removeClass('d-none');
308
                answerDom.removeAttr('id').removeClass('d-none');
309
                // add hidden div with wall post object id
310
                answerField.prepend($('<div></div>').attr('id', 'send-wall-object-' + postId));
311
                // set make answer wall post object id
312
                answerField.find('#make-answer').attr('id', 'make-answer-' + postId);
313
                // build send submit button - set id and href to wall post object anchor
314
                answerField.find('#send-wall').attr('id', 'send-wall-' + postId).attr('href', '#wall-post-' + postId);
315
                // build counter (max chars in input = 200)
316
                answerField.find('#answer-counter').attr('id', 'answer-counter-' + postId);
317
318
                var addAnswerField = '';
319
                if (viewer_id > 0) {
320
                    addAnswerField = answerField.html();
321
                }
322
323
                var answers = '';
324
                $.each(json.data, function (idx, row) {
325
                    // clone general dom element
326
                    var dom = answerDom.clone();
327
                    // set avatar src
328
                    dom.find('#wall-answer-avatar')
329
                        .attr('src', row.user_avatar)
330
                        .removeAttr('id');
331
                    // set user link
332
                    dom.find('#wall-answer-userlink')
333
                        .attr('href', '<?= Url::to('profile/show') ?>/' + row.user_id).text(row.user_nick)
334
                        .attr('style', 'color: '+row.user_color)
335
                        .removeAttr('id');
336
                    // set date
337
                    dom.find('#wall-answer-date').text(row.answer_date).removeAttr('id');
338
                    // set message text
339
                    dom.find('#wall-answer-text').text(row.answer_message);
340
                    // check if this user can remove answers - answer writer or target user profile
341
                    if (is_self_profile || row.user_id === viewer_id) {
342
                        dom.find('#delete-answer')
343
                            .attr('href', '#send-wall-object-' + postId)
344
                            .attr('id', 'delete-answer-' + row.answer_id + '-' + postId)
345
                            .removeClass('d-none');
346
                    }
347
348
                    answers += dom.html();
349
                });
350
                $('#wall-answer-dom-' + postId).html(addAnswerField + answers);
351
            })
352
        };
353
354
        addAnswer = function (postId, message) {
355
            $.post(script_url + '/api/profile/sendwallanswer/' + postId + '?lang=' + script_lang, {message: message}, function (response) {
356
                if (response.status === 1) {
357
                    loadAnswers(postId);
358
                } else {
359
                    $('#send-wall-object-' + postId).html('<p class="alert alert-warning"><?= __('Comment send was failed! Try to send it later.') ?></p>');
360
                }
361
            }, 'json');
362
        };
363
364
365
        // if clicked on "Answers" - show it and send form
366
        $('.show-wall-response').on('click', function () {
367
            var postId = this.id.replace('wall-post-response-', '');
368
            // control hide-display on clicking to "Answers" link
369
            if (hideAnswers[postId] === true) {
370
                hideAnswers[postId] = false;
371
                $('#wall-answer-dom-' + postId).addClass('d-none');
372
                return null;
373
            } else {
374
                hideAnswers[postId] = true;
375
                $('#wall-answer-dom-' + postId).removeClass('d-none');
376
            }
377
            // load data and set html
378
            loadAnswers(postId);
379
        });
380
381
        // calc entered symbols
382
        $(document).on('keyup', '.wall-answer-text', function () {
383
            var postId = this.id.replace('make-answer-', '');
384
            var msglimit = 200;
385
            var msglength = $(this).val().length;
386
387
            var limitObject = $('#answer-counter-' + postId);
388
389
            if (msglength >= msglimit) {
390
                limitObject.html('<span class="badge badge-danger">0</span>');
391
            } else {
392
                limitObject.text(msglimit - msglength);
393
            }
394
        });
395
396
        $(document).on('click', '.delete-answer', function () {
397
            var answerIdPostId = this.id.replace('delete-answer-', '').split('-');
398
            $.getJSON(script_url + '/api/profile/deleteanswerowner/' + answerIdPostId[0] + '?lang=' + script_lang, function (response) {
399
                loadAnswers(answerIdPostId[1]);
400
            });
401
        });
402
403
        // delegate live event simple for add-ed dom element
404
        $(document).on('click', '.send-wall-answer', function () {
405
            var answerToId = this.id.replace('send-wall-', '');
406
            var message = $('#make-answer-' + answerToId).val();
407
            if (message == null || message.length < 3) {
408
                alert('<?= __('Message is too short') ?>');
409
                return null;
410
            }
411
412
            addAnswer(answerToId, message);
413
        });
414
415
        // work with + and - rating clicks
416
        changeRating = function (type) {
417
            // prevent some shits
418
            if (is_self_profile || viewer_id == 0) {
419
                return false;
420
            }
421
422
            $.post(script_url + '/api/profile/changerating?lang=' + script_lang, {type: type, target: target_id}, function (resp) {
423
                if (resp.status === 1) {
424
                    var rV = parseInt($('#ratingValue').text());
425
                    if (type == '+') {
426
                        $('#ratingValue').text(rV + 1);
427
                    } else {
428
                        $('#ratingValue').text(rV - 1);
429
                    }
430
                    alert('<?= __('Rating was successful changed') ?>');
431
                } else {
432
                    alert('<?= __('Rating cannot be changed') ?>');
433
                }
434
                $('#addRating').addClass('disabled');
435
                $('#reduceRating').addClass('disabled');
436
            }, 'json');
437
        };
438
439
        $('#addRating').on('click', function () {
440
            changeRating('+');
441
        });
442
        $('#reduceRating').on('click', function () {
443
            changeRating('-');
444
        });
445
    });
446
</script>
447
<?php $this->stop() ?>