Completed
Push — master ( 6ad9be...50614b )
by George
02:18
created

StatisticsRepository::save()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 13
cts 13
cp 1
rs 9.552
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 * Joomla! Statistics Server
4
 *
5
 * @copyright  Copyright (C) 2013 - 2017 Open Source Matters, Inc. All rights reserved.
6
 * @license    http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
7
 */
8
9
namespace Joomla\StatsServer\Repositories;
10
11
use Joomla\Database\DatabaseInterface;
12
use Joomla\Database\ParameterType;
13
14
/**
15
 * Statistics repository
16
 */
17
class StatisticsRepository
18
{
19
	/**
20
	 * Array containing the allowed sources
21
	 *
22
	 * @var  string[]
23
	 */
24
	public const ALLOWED_SOURCES = ['php_version', 'db_type', 'db_version', 'cms_version', 'server_os', 'cms_php_version', 'db_type_version'];
25
26
	/**
27
	 * The database driver.
28
	 *
29
	 * @var    DatabaseInterface
30
	 * @since  1.3.0
31
	 */
32
	private $db;
33
34
	/**
35
	 * Instantiate the repository.
36
	 *
37
	 * @param   DatabaseInterface  $db  The database driver.
38
	 */
39 14
	public function __construct(DatabaseInterface $db)
40
	{
41 14
		$this->db = $db;
42 14
	}
43
44
	/**
45
	 * Loads the statistics data from the database.
46
	 *
47
	 * @param   string  $column  A single column to filter on
48
	 *
49
	 * @return  array  An array containing the response data
50
	 *
51
	 * @throws  \InvalidArgumentException
52
	 */
53 6
	public function getItems(string $column = ''): array
54
	{
55
		// Validate the requested column is actually in the table
56 6
		if ($column !== '')
57
		{
58
			// The column should exist in the table and be part of the API
59 3
			if (!\in_array($column, self::ALLOWED_SOURCES))
60
			{
61 1
				throw new \InvalidArgumentException('An invalid data source was requested.', 404);
62
			}
63
64 2
			return $this->db->setQuery(
65 2
				$this->db->getQuery(true)
66 2
					->select('*')
67 2
					->from($this->db->quoteName('#__jstats_counter_' . $column))
68 2
			)->loadAssocList();
69
		}
70
71 3
		$return = [];
72
73 3
		foreach (self::ALLOWED_SOURCES as $column)
74
		{
75 3
			$return[$column] = $this->db->setQuery(
76 3
				$this->db->getQuery(true)
77 3
					->select('*')
78 3
					->from($this->db->quoteName('#__jstats_counter_' . $column))
79 3
			)->loadAssocList();
80
		}
81
82 3
		return $return;
83
	}
84
85
	/**
86
	 * Loads the recently updated statistics data from the database.
87
	 *
88
	 * Recently updated is an arbitrary 90 days, submit a pull request for a different behavior.
89
	 *
90
	 * @return  array  An array containing the response data
91
	 */
92 1
	public function getRecentlyUpdatedItems(): array
93
	{
94 1
		$return = [];
95
96 1
		foreach (self::ALLOWED_SOURCES as $column)
97
		{
98 1
			if (($column !== 'cms_php_version') && ($column !== 'db_type_version'))
99
			{
100 1
				$return[$column] = $this->db->setQuery(
101 1
					$this->db->getQuery(true)
102 1
						->select($column)
103 1
						->select('COUNT(' . $column . ') AS count')
104 1
						->from($this->db->quoteName('#__jstats'))
105 1
						->where('modified BETWEEN DATE_SUB(NOW(), INTERVAL 90 DAY) AND NOW()')
106 1
						->group($column)
107 1
				)->loadAssocList();
108 1
				continue;
109
			}
110
111 1
			if ($column === 'cms_php_version')
112
			{
113 1
				$return['cms_php_version'] = $this->db->setQuery(
114 1
					$this->db->getQuery(true)
115 1
						->select('CONCAT(' . $this->db->quoteName('cms_version') . ', ' . $this->db->quote(' - ') . ', ' . $this->db->quoteName('php_version') . ') AS cms_php_version')
116 1
						->select('COUNT(*) AS count')
117 1
						->from($this->db->quoteName('#__jstats'))
118 1
						->where('modified BETWEEN DATE_SUB(NOW(), INTERVAL 90 DAY) AND NOW()')
119 1
						->group('CONCAT(' . $this->db->quoteName('cms_version') . ', ' . $this->db->quote(' - ') . ', ' . $this->db->quoteName('php_version') . ')')
120 1
				)->loadAssocList();
121 1
				continue;
122
			}
123
124 1
			if ($column === 'db_type_version')
125
			{
126 1
				$return['db_type_version'] = $this->db->setQuery(
127 1
					$this->db->getQuery(true)
128 1
						->select('CONCAT(' . $this->db->quoteName('db_type') . ', ' . $this->db->quote(' - ') . ', ' . $this->db->quoteName('db_version') . ') AS db_type_version')
129 1
						->select('COUNT(*) AS count')
130 1
						->from($this->db->quoteName('#__jstats'))
131 1
						->where('modified BETWEEN DATE_SUB(NOW(), INTERVAL 90 DAY) AND NOW()')
132 1
						->group('CONCAT(' . $this->db->quoteName('db_type') . ', ' . $this->db->quote(' - ') . ', ' . $this->db->quoteName('db_version') . ')')
133 1
				)->loadAssocList();
134 1
				continue;
135
			}
136
		}
137
138 1
		return $return;
139
	}
140
141
	/**
142
	 * Saves the given data.
143
	 *
144
	 * @param   \stdClass  $data  Data object to save.
145
	 *
146
	 * @return  void
147
	 */
148 5
	public function save(\stdClass $data): void
149
	{
150
		// Set the modified date of the record
151 5
		$data->modified = (new \DateTime('now', new \DateTimeZone('UTC')))->format($this->db->getDateFormat());
152
153
		// Check if a row exists for this unique ID and update the existing record if so
154 5
		$recordExists = $this->db->setQuery(
155 5
			$this->db->getQuery(true)
156 5
				->select('unique_id')
157 5
				->from('#__jstats')
158 5
				->where('unique_id = :unique_id')
159 5
				->bind(':unique_id', $data->unique_id, ParameterType::STRING)
160 5
		)->loadResult();
161
162 5
		if ($recordExists)
163
		{
164 1
			$this->db->updateObject('#__jstats', $data, ['unique_id']);
165
		}
166
		else
167
		{
168 4
			$this->db->insertObject('#__jstats', $data, ['unique_id']);
0 ignored issues
show
Documentation introduced by
array('unique_id') is of type array<integer,string,{"0":"string"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
169
		}
170 5
	}
171
}
172