Completed
Push — master ( 10f95b...bf15d4 )
by Michael
09:02
created

StatsModel::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
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\Models;
10
11
use Joomla\Database\DatabaseDriver;
12
use Joomla\Database\Query\LimitableInterface;
13
use Joomla\Model\{
14
	DatabaseModelInterface, DatabaseModelTrait
15
};
16
17
/**
18
 * Statistics database model
19
 *
20
 * @since  1.0
21
 */
22
class StatsModel implements DatabaseModelInterface
23
{
24
	use DatabaseModelTrait;
25
26
	/**
27
	 * The query batch size
28
	 *
29
	 * @var    integer
30
	 * @since  1.0
31
	 */
32
	private $batchSize = 25000;
33
34
	/**
35
	 * Instantiate the model.
36
	 *
37
	 * @param   DatabaseDriver  $db  The database driver.
38
	 *
39
	 * @since   1.0
40
	 */
41
	public function __construct(DatabaseDriver $db)
42
	{
43
		$this->setDb($db);
44
	}
45
46
	/**
47
	 * Loads the statistics data from the database.
48
	 *
49
	 * @param   string  $column  A single column to filter on
50
	 *
51
	 * @return  \Generator  A Generator containing the response data
52
	 *
53
	 * @since   1.0
54
	 * @throws  \InvalidArgumentException
55
	 */
56 3
	public function getItems(string $column = '') : \Generator
57
	{
58 3
		$db = $this->getDb();
59
60
		// To keep from running out of memory, we need to know how many records are in the database to be able to loop correctly
61 3
		$totalRecords = $db->setQuery(
62 3
			$db->getQuery(true)
63 3
				->select('COUNT(unique_id)')
64 3
				->from('#__jstats')
65 3
		)->loadResult();
66
67
		// Validate the requested column is actually in the table
68 3
		if ($column !== '')
69
		{
70 2
			$columnList = $db->getTableColumns('#__jstats');
71
72
			// The column should exist in the table and be part of the API
73 2
			if (!in_array($column, array_keys($columnList)) && !in_array($column, ['unique_id', 'modified']))
74
			{
75 1
				throw new \InvalidArgumentException('An invalid data source was requested.', 404);
76
			}
77
78 1
			$query = $db->getQuery(true)
79 1
				->select($column);
80
		}
81
		else
82
		{
83 1
			$query = $db->getQuery(true)
84 1
				->select(['php_version', 'db_type', 'db_version', 'cms_version', 'server_os']);
85
		}
86
87 2
		$query->from('#__jstats')
88 2
			->group('unique_id');
89
90 2
		$limitable = $query instanceof LimitableInterface;
91
92
		// We can't have this as a single array, we run out of memory... This is gonna get interesting...
93 2
		for ($offset = 0; $offset < $totalRecords; $offset + $this->batchSize)
94
		{
95 2
			if ($limitable)
96
			{
97
				$query->setLimit($this->batchSize, $offset);
98
99
				$db->setQuery($query);
100
			}
101
			else
102
			{
103 2
				$db->setQuery($query, $offset, $this->batchSize);
104
			}
105
106 2
			yield $db->loadAssocList();
107
108 2
			$offset += $this->batchSize;
109
		}
110
111
		// Disconnect the DB to free some memory
112 2
		$db->disconnect();
113
114
		// And unset some variables
115 2
		unset($db, $query, $offset, $totalRecords);
116 2
	}
117
118
	/**
119
	 * Saves the given data.
120
	 *
121
	 * @param   \stdClass  $data  Data object to save.
122
	 *
123
	 * @return  void
124
	 *
125
	 * @since   1.0
126
	 */
127 2
	public function save(\stdClass $data)
128
	{
129 2
		$db = $this->getDb();
130
131
		// Set the modified date of the record
132 2
		$data->modified = (new \DateTime('now', new \DateTimeZone('UTC')))->format($db->getDateFormat());
133
134
		// Check if a row exists for this unique ID and update the existing record if so
135 2
		$recordExists = $db->setQuery(
136 2
			$db->getQuery(true)
137 2
				->select('unique_id')
138 2
				->from('#__jstats')
139 2
				->where('unique_id = :unique_id')
140 2
				->bind('unique_id', $data->unique_id, \PDO::PARAM_STR)
141 2
		)->loadResult();
142
143 2
		if ($recordExists)
144
		{
145 1
			$db->updateObject('#__jstats', $data, ['unique_id']);
146
		}
147
		else
148
		{
149 1
			$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...
150
		}
151 2
	}
152
}
153