Completed
Push — master ( eff997...1abf17 )
by Mathieu
03:34
created

AbstractTimeGraphWidget   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 340
Duplicated Lines 20 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 35
c 1
b 0
f 0
lcom 1
cbo 2
dl 68
loc 340
rs 9

20 Methods

Rating   Name   Duplication   Size   Complexity  
A setGroupingType() 0 17 4
A groupingType() 0 4 1
A setDateFormat() 0 10 2
A dateFormat() 0 4 1
A setSqlDateFormat() 0 10 2
A sqlDateFormat() 0 4 1
A setStartDate() 19 19 4
A startDate() 0 4 1
A setEndDate() 19 19 4
A endDate() 0 4 1
A setDateInterval() 0 13 3
A dateInterval() 0 4 1
A setGroupingTypeByHour() 10 10 1
A setGroupingTypeByDay() 10 10 1
A setGroupingTypeByMonth() 10 10 1
B dbRows() 0 44 3
A fillRows() 0 20 4
objType() 0 1 ?
seriesOptions() 0 1 ?
categoryFunction() 0 1 ?

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
namespace Charcoal\Admin\Widget\Graph;
3
4
// Dependencies from `PHP`
5
use \DateInterval;
6
use \DateTime;
7
use \DateTimeInterface;
8
use \InvalidArgumentException;
9
use \PDO;
10
11
// Dependencies from `charcoal-core`
12
use \Charcoal\Model\ModelFactory;
13
14
// From `charcoal-admin`
15
use \Charcoal\Admin\Widget\Graph\AbstractGraphWidget;
16
use \Charcoal\Amin\Widget\Graph\GraphWidgetInterface;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Charcoal\Admin\Widget\Graph\GraphWidgetInterface.

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...
17
18
/**
19
 * Base Graph widget
20
 */
21
abstract class AbstractTimeGraphWidget extends AbstractGraphWidget implements TimeGraphWidgetInterface
22
{
23
    /**
24
     * @var array $dbRows
25
     */
26
    private $dbRows;
27
28
    /**
29
     * @var string $groupingType
30
     */
31
    private $groupingType;
32
33
    /**
34
     * @var strubg $dateFirnat
35
     */
36
    private $dateFormat;
37
38
    /**
39
     * @var string $sqlDateFormat
40
     */
41
    private $sqlDateFormat;
42
43
    /**
44
     * @var DateTimeInterface $startDate
45
     */
46
    private $startDate;
47
48
    /**
49
     * @var DateTimeInterface $endDate
50
     */
51
    private $endDate;
52
53
    /**
54
     * @var DateInterval $dateInterval
55
     */
56
    private $dateInterval;
57
58
    /**
59
     * @param string $type The group type.
60
     * @throws InvalidArgumentException If the group type is not a valid type.
61
     */
62
    public function setGroupingType($type)
63
    {
64
        if ($type == 'hour') {
65
            $this->groupingType = 'hour';
66
            return $this->setGroupingTypeByHour();
67
        } elseif ($type == 'day') {
68
            $this->groupingType = 'day';
69
            return $this->setGroupingTypeByDay();
70
        } elseif ($type == 'month') {
71
            $this->groupingType = 'month';
72
            return $this->setGroupingTypeByMonth();
73
        } else {
74
            throw new InvalidArgumentException(
75
                'Invalid group type: can be "hour", "day" or "month".'
76
            );
77
        }
78
    }
79
80
    /**
81
     * @return string
82
     */
83
    public function groupingType()
84
    {
85
        return $this->groupingType;
86
    }
87
88
    /**
89
     * @param string $format The date format.
90
     * @throws InvalidArgumentException If the format argument is not a string.
91
     * @return UserTimeGraphWidget Chainable
92
     */
93
    public function setDateFormat($format)
94
    {
95
        if (!is_string($format)) {
96
            throw new InvalidArgumentException(
97
                'Date format must be a string'
98
            );
99
        }
100
        $this->dateFormat = $format;
0 ignored issues
show
Documentation Bug introduced by
It seems like $format of type string is incompatible with the declared type object<Charcoal\Admin\Widget\Graph\strubg> of property $dateFormat.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
101
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Charcoal\Admin\Widget\Gr...AbstractTimeGraphWidget) is incompatible with the return type declared by the interface Charcoal\Admin\Widget\Gr...nterface::setDateFormat of type Charcoal\Admin\Widget\Graph\UserTimeGraphWidget.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
102
    }
103
104
    /**
105
     * @return string
106
     */
107
    public function dateFormat()
108
    {
109
        return $this->dateFormat;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->dateFormat; (Charcoal\Admin\Widget\Graph\strubg) is incompatible with the return type declared by the interface Charcoal\Admin\Widget\Gr...etInterface::dateFormat of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
110
    }
111
112
    /**
113
     * @param string $format The date format.
114
     * @throws InvalidArgumentException If the format argument is not a string.
115
     * @return UserTimeGraphWidget Chainable
116
     */
117
    public function setSqlDateFormat($format)
118
    {
119
        if (!is_string($format)) {
120
            throw new InvalidArgumentException(
121
                'SQL date format must be a string'
122
            );
123
        }
124
        $this->sqlDateFormat = $format;
125
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Charcoal\Admin\Widget\Gr...AbstractTimeGraphWidget) is incompatible with the return type declared by the interface Charcoal\Admin\Widget\Gr...rface::setSqlDateFormat of type Charcoal\Admin\Widget\Graph\UserTimeGraphWidget.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
126
    }
127
128
    /**
129
     * @return string
130
     */
131
    public function sqlDateFormat()
132
    {
133
        return $this->sqlDateFormat;
134
    }
135
136
    /**
137
     * @param string|DateTimeInterface $ts The start date.
138
     * @throws InvalidArgumentException If the date is not a valid datetime format.
139
     * @return UserTimeGraphWidget Chainable
140
     */
141 View Code Duplication
    public function setStartDate($ts)
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...
142
    {
143
        if (is_string($ts)) {
144
            try {
145
                $ts = new DateTime($ts);
146
            } catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The class Charcoal\Admin\Widget\Graph\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
147
                throw new InvalidArgumentException(
148
                    'Invalid start date: '.$e->getMessage()
149
                );
150
            }
151
        }
152
        if (!($ts instanceof DateTimeInterface)) {
153
            throw new InvalidArgumentException(
154
                'Invalid "Start Date" value. Must be a date/time string or a DateTime object.'
155
            );
156
        }
157
        $this->startDate = $ts;
158
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Charcoal\Admin\Widget\Gr...AbstractTimeGraphWidget) is incompatible with the return type declared by the interface Charcoal\Admin\Widget\Gr...Interface::setStartDate of type Charcoal\Admin\Widget\Graph\UserTimeGraphWidget.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
159
    }
160
161
    /**
162
     * @return DateTimeInterface
163
     */
164
    public function startDate()
165
    {
166
        return $this->startDate;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->startDate; (DateTimeInterface) is incompatible with the return type declared by the interface Charcoal\Admin\Widget\Gr...getInterface::startDate of type Charcoal\Admin\Widget\Graph\DateTimeInterface.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
167
    }
168
169
    /**
170
     * @param string|DateTimeInterface $ts The end date.
171
     * @throws InvalidArgumentException If the date is not a valid datetime format.
172
     * @return UserTimeGraphWidget Chainable
173
     */
174 View Code Duplication
    public function setEndDate($ts)
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...
175
    {
176
        if (is_string($ts)) {
177
            try {
178
                $ts = new DateTime($ts);
179
            } catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The class Charcoal\Admin\Widget\Graph\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
180
                throw new InvalidArgumentException(
181
                    'Invalid end date: '.$e->getMessage()
182
                );
183
            }
184
        }
185
        if (!($ts instanceof DateTimeInterface)) {
186
            throw new InvalidArgumentException(
187
                'Invalid "End Date" value. Must be a date/time string or a DateTime object.'
188
            );
189
        }
190
        $this->endDate = $ts;
191
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Charcoal\Admin\Widget\Gr...AbstractTimeGraphWidget) is incompatible with the return type declared by the interface Charcoal\Admin\Widget\Gr...etInterface::setEndDate of type Charcoal\Admin\Widget\Graph\UserTimeGraphWidget.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
192
    }
193
194
    /**
195
     * @return DateTimeInterface
196
     */
197
    public function endDate()
198
    {
199
        return $this->endDate;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->endDate; (DateTimeInterface) is incompatible with the return type declared by the interface Charcoal\Admin\Widget\Gr...idgetInterface::endDate of type Charcoal\Admin\Widget\Graph\DateTimeInterface.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
200
    }
201
202
    /**
203
     * @param string|DateInterval $interval The date interval, between "categories".
204
     * @throws InvalidArgumentException If the argument is not a string or an interval object.
205
     * @return UserTimeGraphWidget Chainable
206
     */
207
    public function setDateInterval($interval)
208
    {
209
        if (is_string($interval)) {
210
            $this->dateInterval = DateInterval::createfromdatestring($interval);
211
        } elseif ($interval instanceof DateInterval) {
212
            $this->dateInterval = $interval;
213
        } else {
214
            throw new InvalidArgumentException(
215
                'Can not set date interval.'
216
            );
217
        }
218
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Charcoal\Admin\Widget\Gr...AbstractTimeGraphWidget) is incompatible with the return type declared by the interface Charcoal\Admin\Widget\Gr...erface::setDateInterval of type Charcoal\Admin\Widget\Graph\UserTimeGraphWidget.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
219
    }
220
221
    /**
222
     * @return DateInterval
223
     */
224
    public function dateInterval()
225
    {
226
        return $this->dateInterval;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->dateInterval; (DateInterval) is incompatible with the return type declared by the interface Charcoal\Admin\Widget\Gr...Interface::dateInterval of type Charcoal\Admin\Widget\Graph\DateInterval.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
227
    }
228
229
     /**
230
      * @return UserTimeGraphWidget Chainable
231
      */
232 View Code Duplication
    protected function setGroupingTypeByHour()
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...
233
    {
234
        $this->setDateFormat('Y-m-d H:i');
235
        $this->setSqlDateFormat('%Y-%m-%d %H:%i');
236
        $this->setStartDate('-24 hours');
237
        $this->setEndDate('now');
238
        $this->setDateInterval('+1 hour');
239
240
        return $this;
241
    }
242
243
    /**
244
     * @return UserTimeGraphWidget Chainable
245
     */
246 View Code Duplication
    protected function setGroupingTypeByDay()
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...
247
    {
248
        $this->setDateFormat('Y-m-d');
249
        $this->setSqlDateFormat('%Y-%m-%d');
250
        $this->setStartDate('-30 days');
251
        $this->setEndDate('now');
252
        $this->setDateInterval('+1 day');
253
254
        return $this;
255
    }
256
257
    /**
258
     * @return UserTimeGraphWidget Chainable
259
     */
260 View Code Duplication
    protected function setGroupingTypeByMonth()
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...
261
    {
262
        $this->setDateFormat('Y-m');
263
        $this->setSqlDateFormat('%Y-%m');
264
        $this->setStartDate('-12 months');
265
        $this->setEndDate('now');
266
        $this->setDateInterval('+1 month');
267
268
        return $this;
269
    }
270
271
    /**
272
     * @return array
273
     */
274
    protected function dbRows()
275
    {
276
        if ($this->dbRows === null) {
277
            $factory = new ModelFactory([
0 ignored issues
show
Unused Code introduced by
The call to ModelFactory::__construct() has too many arguments starting with array('logger' => $this->logger).

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...
278
                'logger' => $this->logger
279
            ]);
280
281
            $model = $factory->create($this->objType(), [
282
                'logger' => $this->logger
283
            ]);
284
285
            $sql = [];
286
            $seriesOptions = $this->seriesOptions();
287
            foreach ($seriesOptions as $serieId => $serieOpts) {
288
                $sql[] = $serieOpts['function'].' as '.$serieId;
289
            }
290
291
            $q = sprintf(
292
                '
293
                SELECT
294
                    %1$s as x,
295
                    '.implode(
296
                    ', ',
297
                    $sql
298
                ).'
299
                FROM
300
                    %2$s
301
                WHERE
302
                    %1$s BETWEEN  :start_date AND :end_date
303
                GROUP BY
304
                    %1$s
305
                ORDER BY
306
                    %1$s ASC',
307
                $this->categoryFunction(),
308
                $model->source()->table()
309
            );
310
            $res = $model->source()->dbQuery($q, [
311
                'start_date'    => $this->startDate()->format($this->dateFormat()),
312
                'end_date'      => $this->endDate()->format($this->dateFormat())
313
            ]);
314
            $this->dbRows = $res->fetchAll((PDO::FETCH_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC));
315
        }
316
        return $this->dbRows;
317
    }
318
319
    /**
320
     * Fill all rows with 0 value for all series, when it is unset.
321
     *
322
     * @param array $rows The row structure to fill.
323
     * @return array
324
     */
325
    protected function fillRows(array $rows)
326
    {
327
        $row = [];
328
        $seriesOptions = $this->seriesOptions();
329
        foreach ($seriesOptions as $serieId => $serieOpts) {
330
            $row[$serieId] = '0';
331
        }
332
333
        $starts = clone($this->startDate());
334
        $ends = $this->endDate();
335
        while ($starts < $ends) {
336
            $x = $starts->format($this->dateFormat());
337
            if (!isset($rows[$x])) {
338
                $rows[$x] = $row;
339
            }
340
            $starts->add($this->dateInterval());
341
        }
342
        ksort($rows);
343
        return $rows;
344
    }
345
346
    /**
347
     * @return string
348
     */
349
    abstract protected function objType();
350
351
    /**
352
     * @return array
353
     */
354
    abstract protected function seriesOptions();
355
356
        /**
357
         * @return string
358
         */
359
    abstract protected function categoryFunction();
360
}
361