Passed
Pull Request — master (#125)
by MusikAnimal
03:53
created

TopEdits::getTopEdits()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 15
nc 3
nop 0
dl 0
loc 23
ccs 15
cts 15
cp 1
crap 3
rs 9.0856
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the TopEdits class.
4
 */
5
6
namespace Xtools;
7
8
use Symfony\Component\DependencyInjection\Container;
9
use DateTime;
10
11
/**
12
 * TopEdits returns the top-edited pages by a user.
13
 */
14
class TopEdits extends Model
15
{
16
    /** @var Project The project. */
17
    protected $project;
18
19
    /** @var User The user. */
20
    protected $user;
21
22
    /** @var string[] Top edits object for quick caching, keyed by namespace ID. */
23
    protected $topEdits = [];
24
25
    /** @var int Number of rows to fetch. */
26
    protected $limit;
27
28
    /** @var int Which namespace we are querying for. */
29
    protected $namespace;
30
31
    const DEFAULT_LIMIT_SINGLE_NAMESPACE = 100;
32
    const DEFAULT_LIMIT_ALL_NAMESPACES = 20;
33
34
    /**
35
     * TopEdits constructor.
36
     * @param Project $project
37
     * @param User $user
38
     * @param string|int Namespace ID or 'all'.
0 ignored issues
show
Bug introduced by
The type Xtools\Namespace was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
39
     * @param int $limit Number of rows to fetch. This defaults to
40
     *   DEFAULT_LIMIT_SINGLE_NAMESPACE if $this->namespace is a single namespace (int),
41
     *   and DEFAULT_LIMIT_ALL_NAMESPACES if $this->namespace is 'all'.
42
     */
43 3
    public function __construct(Project $project, User $user, $namespace = 0, $limit = null)
44
    {
45 3
        $this->project = $project;
46 3
        $this->user = $user;
47 3
        $this->namespace = $namespace === 'all' ? 'all' : (int)$namespace;
0 ignored issues
show
Documentation Bug introduced by
It seems like $namespace === 'all' ? 'all' : (int)$namespace can also be of type string. However, the property $namespace is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
48
49 3
        if ($limit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $limit of type null|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
50 3
            $this->limit = $limit;
51
        } else {
52 1
            $this->limit = $this->namespace === 'all'
53 1
                ? self::DEFAULT_LIMIT_ALL_NAMESPACES
54 1
                : self::DEFAULT_LIMIT_SINGLE_NAMESPACE;
55
        }
56 3
    }
57
58
    /**
59
     * Get the limit set on number of rows to fetch.
60
     * @return int
61
     */
62 1
    public function getLimit()
63
    {
64 1
        return $this->limit;
65
    }
66
67
    /**
68
     * Get the namespace set on the instance.
69
     * @return int|string Namespace ID or 'all'.
70
     */
71 1
    public function getNamespace()
72
    {
73 1
        return $this->namespace;
74
    }
75
76
    /**
77
     * Get the top edits by a user in the given namespace, or 'all' namespaces.
78
     * This is the public function that should be used.
79
     * @return string[] Results of self::getTopEditsByNamespace(), keyed by namespace.
80
     */
81 2
    public function getTopEdits()
82
    {
83 2
        if (count($this->topEdits) > 0) {
84 1
            return $this->topEdits;
85
        }
86
87 2
        if ($this->namespace === 'all') {
88 1
            $pages = $this->getRepository()->getTopEditsAllNamespaces(
89 1
                $this->project,
90 1
                $this->user,
91 1
                $this->limit
92
            );
93
        } else {
94 1
            $pages = $this->getRepository()->getTopEditsNamespace(
1 ignored issue
show
Bug introduced by
The method getTopEditsNamespace() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\TopEditsRepository. ( Ignorable by Annotation )

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

94
            $pages = $this->getRepository()->/** @scrutinizer ignore-call */ getTopEditsNamespace(
Loading history...
95 1
                $this->project,
96 1
                $this->user,
97 1
                $this->namespace,
98 1
                $this->limit
99
            );
100
        }
101
102 2
        $this->topEdits = $this->formatTopPages($pages);
103 2
        return $this->topEdits;
104
    }
105
106
    /**
107
     * [formatTopPages description]
108
     * @param  string[] $pages As returned by TopEditsRepository::getTopEditsNamespace
109
     *                         or TopEditsRepository::getTopEditsAllNamespaces.
110
     * @return string[] Same as input but with 'displaytitle', and 'page_title_ns'.
111
     */
112 2
    private function formatTopPages($pages)
113
    {
114
        /** @var string[] The top edited pages, keyed by namespace ID. */
115 2
        $topEditedPages = [];
116
117
        /** @var string[] Display titles of the pages, which need to be fetched ahead of time. */
118 2
        $displayTitles = $this->getDisplayTitles($pages);
119
120 2
        foreach ($pages as $page) {
121 2
            $nsId = (int) $page['page_namespace'];
122 2
            $nsTitle = $nsId > 0 ? $this->project->getNamespaces()[$page['page_namespace']] . ':' : '';
123 2
            $pageTitle = $nsTitle . $page['page_title'];
124 2
            $page['displaytitle'] = $displayTitles[$pageTitle];
125
126
            // $page['page_title'] is retained without the namespace
127
            //  so we can link to TopEdits for that page.
128 2
            $page['page_title_ns'] = $pageTitle;
129
130 2
            if (isset($topEditedPages[$nsId])) {
131 2
                $topEditedPages[$nsId][] = $page;
132
            } else {
133 2
                $topEditedPages[$nsId] = [$page];
134
            }
135
        }
136
137 2
        return $topEditedPages;
138
    }
139
140
    /**
141
     * Get the display titles of the given pages.
142
     * @param  string[] $topPages As returned by $this->getRepository()->getTopEdits()
143
     * @return string[] Keys are the original supplied titles, and values are the display titles.
144
     */
145 2
    private function getDisplayTitles($topPages)
146
    {
147 2
        $namespaces = $this->project->getNamespaces();
148
149
        // First extract page titles including namespace.
150 2
        $pageTitles = array_map(function ($page) use ($namespaces) {
151
            // If non-mainspace, prepend namespace to the titles.
152 2
            $ns = $page['page_namespace'];
153 2
            $nsTitle = $ns > 0 ? $namespaces[$page['page_namespace']] . ':' : '';
154 2
            return $nsTitle . $page['page_title'];
155 2
        }, $topPages);
156
157 2
        return $this->getRepository()->getDisplayTitles($this->project, $pageTitles);
1 ignored issue
show
Bug introduced by
The method getDisplayTitles() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\TopEditsRepository. ( Ignorable by Annotation )

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

157
        return $this->getRepository()->/** @scrutinizer ignore-call */ getDisplayTitles($this->project, $pageTitles);
Loading history...
158
    }
159
}
160