Completed
Push — develop ( 70d143...82ceb9 )
by Schlaefer
02:46
created

ThreadsComponent::_getCurrentUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Saito - The Threaded Web Forum
7
 *
8
 * @copyright Copyright (c) the Saito Project Developers
9
 * @link https://github.com/Schlaefer/Saito
10
 * @license http://opensource.org/licenses/MIT
11
 */
12
13
namespace App\Controller\Component;
14
15
use App\Controller\AppController;
16
use App\Model\Table\EntriesTable;
17
use Cake\Controller\Component;
18
use Cake\Controller\Component\PaginatorComponent;
19
use Cake\Core\Configure;
20
use Cake\ORM\Entity;
21
use Cake\ORM\TableRegistry;
22
use Saito\Posting\Posting;
23
use Saito\User\CurrentUser\CurrentUserInterface;
24
use Stopwatch\Lib\Stopwatch;
25
26
/**
27
 * Class ThreadsComponent
28
 *
29
 * @property PaginatorComponent $Paginator
30
 * @property AuthUserComponent $AuthUser
31
 */
32
class ThreadsComponent extends Component
33
{
34
35
    public $components = ['AuthUser', 'Paginator'];
36
37
    /**
38
     * Entries table
39
     *
40
     * @var EntriesTable
41
     */
42
    private $Entries;
43
44
    /**
45
     * Load paginated threads
46
     *
47
     * @param mixed $order order to apply
48
     * @return array
49
     */
50
    public function paginate($order)
51
    {
52
        /** @var EntriesTable */
53
        $EntriesTable = TableRegistry::getTableLocator()->get('Entries');
54
        $this->Entries = $EntriesTable;
55
56
        /** @var AppController */
57
        $controller = $this->getController();
58
        $CurrentUser = $controller->CurrentUser;
59
        $initials = $this->_getInitialThreads($CurrentUser, $order);
60
        $threads = $this->Entries->treesForThreads($initials, $order);
61
62
        return $threads;
63
    }
64
65
    /**
66
     * Gets thread ids for paginated entries/index.
67
     *
68
     * @param CurrentUserInterface $User current-user
69
     * @param array $order sort order
70
     * @return array thread ids
71
     */
72
    protected function _getInitialThreads(CurrentUserInterface $User, $order)
73
    {
74
        Stopwatch::start('Entries->_getInitialThreads() Paginate');
75
        $categories = $User->getCategories()->getCurrent('read');
76
        if (empty($categories)) {
77
            // no readable categories for user (e.g. no public categories
78
            return [];
79
        }
80
81
        ////! Check DB performance after changing conditions/sorting!
82
        $customFinderOptions = [
83
            'conditions' => [
84
                'Entries.category_id IN' => $categories
85
            ],
86
            // @td sanitize input?
87
            'limit' => Configure::read('Saito.Settings.topics_per_page'),
88
            'order' => $order,
89
            // Performance: Custom counter from categories counter-cache;
90
            // avoids a costly COUNT(*) DB call counting all pages for pagination.
91
            'counter' => function ($query) use ($categories) {
0 ignored issues
show
Unused Code introduced by
The parameter $query is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
92
                $results = $this->Entries->Categories->find('all')
93
                ->select(['thread_count'])
94
                ->where(['id IN' => $categories])
95
                ->all();
96
                $count = array_reduce(
97
                    $results->toArray(),
98
                    function ($carry, Entity $entity) {
99
                        return $carry + $entity->get('thread_count');
100
                    },
101
                    0
102
                );
103
104
                return $count;
105
            }
106
        ];
107
108
        $settings = [
109
            'finder' => ['indexPaginator' => $customFinderOptions],
110
        ];
111
112
        // use setConfig on Component to not merge but overwrite/set the config
113
        $this->Paginator->setConfig('whitelist', ['page'], false);
114
        $initialThreads = $this->Paginator->paginate($this->Entries, $settings);
115
116
        $initialThreadsNew = [];
117
        foreach ($initialThreads as $k => $v) {
118
            $initialThreadsNew[$k] = $v['id'];
119
        }
120
        Stopwatch::stop('Entries->_getInitialThreads() Paginate');
121
122
        return $initialThreadsNew;
123
    }
124
125
    /**
126
     * Increment views for posting if posting doesn't belong to current user.
127
     *
128
     * @param Posting $posting posting
129
     * @param string $type type
130
     * - 'null' increment single posting
131
     * - 'thread' increment all postings in thread
132
     *
133
     * @return void
134
     */
135
    public function incrementViews(Posting $posting, $type = null)
136
    {
137
        if ($this->AuthUser->isBot()) {
138
            return;
139
        }
140
141
        /** @var EntriesTable */
142
        $Entries = TableRegistry::getTableLocator()->get('Entries');
143
        /** @var AppController */
144
        $controller = $this->getController();
145
        $CurrentUser = $controller->CurrentUser;
146
147
        if ($type === 'thread') {
148
            $where = ['tid' => $posting->get('tid')];
149
            if ($CurrentUser->isLoggedIn()) {
150
                $where['user_id !='] = $CurrentUser->getId();
151
            }
152
            $Entries->increment($where, 'views');
153
154
            return;
155
        }
156
157
        if ($CurrentUser->isLoggedIn()
158
            && ($posting->get('user_id') === $CurrentUser->getId())) {
159
            return;
160
        }
161
162
        $Entries->increment($posting->get('id'), 'views');
163
    }
164
}
165