Passed
Push — master ( d4cbdc...769bad )
by
unknown
13:22
created

LogEntryRepository::findByConstraint()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Belog\Domain\Repository;
17
18
use TYPO3\CMS\Backend\Tree\View\PageTreeView;
19
use TYPO3\CMS\Belog\Domain\Model\Constraint;
20
use TYPO3\CMS\Belog\Domain\Model\LogEntry;
21
use TYPO3\CMS\Belog\Domain\Model\Workspace;
22
use TYPO3\CMS\Core\Authentication\GroupResolver;
23
use TYPO3\CMS\Core\Database\ConnectionPool;
24
use TYPO3\CMS\Core\Type\Bitmask\Permission;
25
use TYPO3\CMS\Core\Utility\GeneralUtility;
26
use TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface;
27
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
28
use TYPO3\CMS\Extbase\Persistence\Repository;
29
30
/**
31
 * Sys log entry repository
32
 * @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
33
 */
34
class LogEntryRepository extends Repository
35
{
36
    /**
37
     * Initialize some local variables to be used during creation of objects
38
     */
39
    public function initializeObject()
40
    {
41
        /** @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings */
42
        $defaultQuerySettings = $this->objectManager->get(QuerySettingsInterface::class);
43
        $defaultQuerySettings->setRespectStoragePage(false);
44
        $this->setDefaultQuerySettings($defaultQuerySettings);
45
    }
46
47
    /**
48
     * Finds all log entries that match all given constraints.
49
     *
50
     * @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
51
     * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
52
     */
53
    public function findByConstraint(Constraint $constraint)
54
    {
55
        $query = $this->createQuery();
56
        $queryConstraints = $this->createQueryConstraints($query, $constraint);
57
        if (!empty($queryConstraints)) {
58
            $query->matching($query->logicalAnd($queryConstraints));
59
        }
60
        $query->setOrderings(['uid' => QueryInterface::ORDER_DESCENDING]);
61
        $query->setLimit($constraint->getNumber());
62
        return $query->execute();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->execute() also could return the type array which is incompatible with the documented return type TYPO3\CMS\Extbase\Persistence\QueryResultInterface.
Loading history...
63
    }
64
65
    /**
66
     * Create an array of query constraints from constraint object
67
     *
68
     * @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
69
     * @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
70
     * @return array|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface[]
71
     */
72
    protected function createQueryConstraints(QueryInterface $query, Constraint $constraint)
73
    {
74
        $queryConstraints = [];
75
        // User / group handling
76
        $this->addUsersAndGroupsToQueryConstraints($constraint, $query, $queryConstraints);
77
        // Workspace
78
        if ($constraint->getWorkspaceUid() != Workspace::UID_ANY_WORKSPACE) {
79
            $queryConstraints[] = $query->equals('workspace', $constraint->getWorkspaceUid());
80
        }
81
        // Action (type):
82
        if ($constraint->getAction() > 0) {
83
            $queryConstraints[] = $query->equals('type', $constraint->getAction());
84
        } elseif ($constraint->getAction() == -1) {
85
            $queryConstraints[] = $query->equals('type', 5);
86
        }
87
        // Start / endtime handling: The timestamp calculation was already done
88
        // in the controller, since we need those calculated values in the view as well.
89
        $queryConstraints[] = $query->greaterThanOrEqual('tstamp', $constraint->getStartTimestamp());
90
        $queryConstraints[] = $query->lessThan('tstamp', $constraint->getEndTimestamp());
91
        // Page and level constraint if in page context
92
        $this->addPageTreeConstraintsToQuery($constraint, $query, $queryConstraints);
93
        return $queryConstraints;
94
    }
95
96
    /**
97
     * Adds constraints for the page(s) to the query; this could be one single page or a whole subtree beneath a given
98
     * page.
99
     *
100
     * @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
101
     * @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
102
     * @param array $queryConstraints the query constraints to add to, will be modified
103
     */
104
    protected function addPageTreeConstraintsToQuery(Constraint $constraint, QueryInterface $query, array &$queryConstraints)
105
    {
106
        $pageIds = [];
107
        // Check if we should get a whole tree of pages and not only a single page
108
        if ($constraint->getDepth() > 0) {
109
            /** @var \TYPO3\CMS\Backend\Tree\View\PageTreeView $pageTree */
110
            $pageTree = GeneralUtility::makeInstance(PageTreeView::class);
111
            $pageTree->init('AND ' . $GLOBALS['BE_USER']->getPagePermsClause(Permission::PAGE_SHOW));
112
            $pageTree->makeHTML = 0;
113
            $pageTree->fieldArray = ['uid'];
114
            $pageTree->getTree($constraint->getPageId(), $constraint->getDepth());
115
            $pageIds = $pageTree->ids;
116
        }
117
        if (!empty($constraint->getPageId())) {
118
            $pageIds[] = $constraint->getPageId();
119
        }
120
        if (!empty($pageIds)) {
121
            $queryConstraints[] = $query->in('eventPid', $pageIds);
122
        }
123
    }
124
125
    /**
126
     * Adds users and groups to the query constraints.
127
     *
128
     * @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
129
     * @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
130
     * @param array $queryConstraints the query constraints to add to, will be modified
131
     */
132
    protected function addUsersAndGroupsToQueryConstraints(Constraint $constraint, QueryInterface $query, array &$queryConstraints)
133
    {
134
        $userOrGroup = $constraint->getUserOrGroup();
135
        if ($userOrGroup === '') {
136
            return;
137
        }
138
        // Constraint for a group
139
        if (strpos($userOrGroup, 'gr-') === 0) {
140
            $groupId = (int)substr($userOrGroup, 3);
141
            $groupResolver = GeneralUtility::makeInstance(GroupResolver::class);
142
            $userIds = $groupResolver->findAllUsersInGroups([$groupId], 'be_groups', 'be_users');
143
            if (!empty($userIds)) {
144
                $userIds = array_column($userIds, 'uid');
145
                $userIds = array_map('intval', $userIds);
146
                $queryConstraints[] = $query->in('userid', $userIds);
147
            } else {
148
                // If there are no group members -> use -1 as constraint to not find anything
149
                $queryConstraints[] = $query->in('userid', [-1]);
150
            }
151
        } elseif (strpos($userOrGroup, 'us-') === 0) {
152
            $queryConstraints[] = $query->equals('userid', (int)substr($userOrGroup, 3));
153
        } elseif ($userOrGroup === '-1') {
154
            $queryConstraints[] = $query->equals('userid', (int)$GLOBALS['BE_USER']->user['uid']);
155
        }
156
    }
157
158
    /**
159
     * Deletes all messages which have the same message details
160
     *
161
     * @param LogEntry $logEntry
162
     * @return int
163
     */
164
    public function deleteByMessageDetails(LogEntry $logEntry): int
165
    {
166
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
167
            ->getQueryBuilderForTable('sys_log');
168
        $constraints = [];
169
        $constraints[] = $queryBuilder->expr()->eq('details', $queryBuilder->createNamedParameter($logEntry->getDetails()));
170
        // If the detailsNo is 11 or 12 we got messages that are heavily using placeholders. In this case
171
        // we need to compare both the message and the actual log data to not remove too many log entries.
172
        if (GeneralUtility::inList('11,12', (string)$logEntry->getDetailsNumber())) {
173
            $constraints[] = $queryBuilder->expr()->eq('log_data', $queryBuilder->createNamedParameter($logEntry->getLogData()));
174
        }
175
        return $queryBuilder->delete('sys_log')
176
            ->where(...$constraints)
177
            ->execute();
178
    }
179
}
180