This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | $defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1; |
||
3 | |||
4 | |||
5 | /* |
||
6 | * We give access to plenty of statistics through this class |
||
7 | * Statistics should be non-intrusive and not change any |
||
8 | * rows in our database to ensure data integrity for the backend |
||
9 | **/ |
||
10 | class Statistics extends Base { |
||
11 | protected $table = 'statistics_shares'; |
||
12 | protected $table_user_stats = 'statistics_users'; |
||
13 | private $getcache = true; |
||
14 | |||
15 | // Disable fetching values from cache |
||
16 | public function setGetCache($set=false) { |
||
17 | $this->getcache = $set; |
||
18 | } |
||
19 | public function getGetCache() { |
||
20 | return $this->getcache; |
||
21 | } |
||
22 | public function getAllUserMiningStats() { |
||
23 | return $this->allUserMiningStats; |
||
0 ignored issues
–
show
|
|||
24 | } |
||
25 | public function getUserStatsTableName() { |
||
26 | return $this->table_user_stats; |
||
27 | } |
||
28 | |||
29 | /** |
||
30 | * Get our first block found |
||
31 | * |
||
32 | **/ |
||
33 | public function getFirstBlockFound() { |
||
34 | $this->debug->append("STA " . __METHOD__, 4); |
||
35 | if ($data = $this->memcache->get(__FUNCTION__)) return $data; |
||
0 ignored issues
–
show
The property
memcache does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
36 | $stmt = $this->mysqli->prepare(" |
||
37 | SELECT IFNULL(MIN(time), 0) AS time FROM " . $this->block->getTableName()); |
||
0 ignored issues
–
show
The property
block does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
38 | if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) |
||
39 | return $result->fetch_object()->time; |
||
40 | return false; |
||
41 | } |
||
42 | |||
43 | /** |
||
44 | * Fetch last found blocks by time |
||
45 | **/ |
||
46 | function getLastBlocksbyTime() { |
||
0 ignored issues
–
show
|
|||
47 | $this->debug->append("STA " . __METHOD__, 4); |
||
48 | if ($data = $this->memcache->get(__FUNCTION__)) return $data; |
||
49 | $stmt = $this->mysqli->prepare(" |
||
50 | SELECT |
||
51 | COUNT(id) AS Total, |
||
52 | IFNULL(SUM(IF(confirmations > 0, 1, 0)), 0) AS TotalValid, |
||
53 | IFNULL(SUM(IF(confirmations = -1, 1, 0)), 0) AS TotalOrphan, |
||
54 | IFNULL(SUM(IF(confirmations > 0, difficulty, 0)), 0) AS TotalDifficulty, |
||
55 | IFNULL(SUM(IF(confirmations > -1, shares, 0)), 0) AS TotalShares, |
||
56 | IFNULL(SUM(IF(confirmations > -1, amount, 0)), 0) AS TotalAmount, |
||
57 | IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), 1, 0)), 0) AS 1HourTotal, |
||
58 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), 1, 0)), 0) AS 1HourValid, |
||
59 | IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), 1, 0)), 0) AS 1HourOrphan, |
||
60 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), difficulty, 0)), 0) AS 1HourDifficulty, |
||
61 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), shares, 0)), 0) AS 1HourShares, |
||
62 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), amount, 0)), 0) AS 1HourAmount, |
||
63 | IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), 1, 0)), 0) AS 24HourTotal, |
||
64 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), 1, 0)), 0) AS 24HourValid, |
||
65 | IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), 1, 0)), 0) AS 24HourOrphan, |
||
66 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), difficulty, 0)), 0) AS 24HourDifficulty, |
||
67 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), shares, 0)), 0) AS 24HourShares, |
||
68 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), amount, 0)), 0) AS 24HourAmount, |
||
69 | IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), 1, 0)), 0) AS 7DaysTotal, |
||
70 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), 1, 0)), 0) AS 7DaysValid, |
||
71 | IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), 1, 0)), 0) AS 7DaysOrphan, |
||
72 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), difficulty, 0)), 0) AS 7DaysDifficulty, |
||
73 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), shares, 0)), 0) AS 7DaysShares, |
||
74 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), amount, 0)), 0) AS 7DaysAmount, |
||
75 | IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), 1, 0)), 0) AS 4WeeksTotal, |
||
76 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), 1, 0)), 0) AS 4WeeksValid, |
||
77 | IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), 1, 0)), 0) AS 4WeeksOrphan, |
||
78 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), difficulty, 0)), 0) AS 4WeeksDifficulty, |
||
79 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), shares, 0)), 0) AS 4WeeksShares, |
||
80 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), amount, 0)), 0) AS 4WeeksAmount, |
||
81 | IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), 1, 0)), 0) AS 12MonthTotal, |
||
82 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), 1, 0)), 0) AS 12MonthValid, |
||
83 | IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), 1, 0)), 0) AS 12MonthOrphan, |
||
84 | IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), difficulty, 0)), 0) AS 12MonthDifficulty, |
||
85 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), shares, 0)), 0) AS 12MonthShares, |
||
86 | IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), amount, 0)), 0) AS 12MonthAmount |
||
87 | FROM " . $this->block->getTableName()); |
||
88 | if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) { |
||
89 | $aData = $result->fetch_assoc(); |
||
90 | $aData['TotalEstimatedShares'] = $this->coin->calcEstaimtedShares($aData['TotalDifficulty']); |
||
0 ignored issues
–
show
The property
coin does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
91 | $aData['1HourEstimatedShares'] = $this->coin->calcEstaimtedShares($aData['1HourDifficulty']); |
||
92 | $aData['24HourEstimatedShares'] = $this->coin->calcEstaimtedShares($aData['24HourDifficulty']); |
||
93 | $aData['7DaysEstimatedShares'] = $this->coin->calcEstaimtedShares($aData['7DaysDifficulty']); |
||
94 | $aData['4WeeksEstimatedShares'] = $this->coin->calcEstaimtedShares($aData['4WeeksDifficulty']); |
||
95 | $aData['12MonthEstimatedShares'] = $this->coin->calcEstaimtedShares($aData['12MonthDifficulty']); |
||
96 | return $this->memcache->setCache(__FUNCTION__, $aData); |
||
97 | } |
||
98 | return $this->sqlError(); |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * Get our last $limit blocks found |
||
103 | * @param limit int Last limit blocks |
||
104 | * @return array |
||
105 | **/ |
||
106 | View Code Duplication | public function getBlocksFound($limit=10) { |
|
0 ignored issues
–
show
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. ![]() |
|||
107 | $this->debug->append("STA " . __METHOD__, 4); |
||
108 | if ($data = $this->memcache->get(__FUNCTION__ . $limit)) return $data; |
||
109 | $stmt = $this->mysqli->prepare(" |
||
110 | SELECT |
||
111 | b.*, |
||
112 | a.username AS finder, |
||
113 | a.is_anonymous AS is_anonymous, |
||
114 | ROUND(difficulty * POW(2, 32 - " . $this->coin->getTargetBits() . "), " . $this->coin->getShareDifficultyPrecision() . ") AS estshares |
||
115 | FROM " . $this->block->getTableName() . " AS b |
||
116 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
0 ignored issues
–
show
The property
user does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
117 | ON b.account_id = a.id |
||
118 | ORDER BY height DESC LIMIT ?"); |
||
119 | if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result()) |
||
120 | return $this->memcache->setCache(__FUNCTION__ . $limit, $result->fetch_all(MYSQLI_ASSOC), 5); |
||
121 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getBlocksFound of type array .
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 ![]() |
|||
122 | } |
||
123 | |||
124 | /** |
||
125 | * Get our last $limit blocks found by height |
||
126 | * @param limit int Last limit blocks |
||
127 | * @return array |
||
128 | **/ |
||
129 | public function getBlocksFoundHeight($iHeight=0, $limit=10) { |
||
130 | $this->debug->append("STA " . __METHOD__, 4); |
||
131 | if ($data = $this->memcache->get(__FUNCTION__ . $iHeight . $limit)) return $data; |
||
132 | $stmt = $this->mysqli->prepare(" |
||
133 | SELECT |
||
134 | b.*, |
||
135 | a.username AS finder, |
||
136 | a.is_anonymous AS is_anonymous, |
||
137 | ROUND(difficulty * POW(2, 32 - " . $this->coin->getTargetBits() . "), 4) AS estshares |
||
138 | FROM " . $this->block->getTableName() . " AS b |
||
139 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
140 | ON b.account_id = a.id |
||
141 | WHERE b.height <= ? |
||
142 | ORDER BY height DESC LIMIT ?"); |
||
143 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $iHeight, $limit) && $stmt->execute() && $result = $stmt->get_result()) |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
144 | return $this->memcache->setCache(__FUNCTION__ . $iHeight . $limit, $result->fetch_all(MYSQLI_ASSOC), 5); |
||
145 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getBlocksFoundHeight of type array .
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 ![]() |
|||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Get SUM of blocks found and generated Coins for each Account |
||
150 | * @param limit int Last limit blocks |
||
151 | * @return array |
||
152 | **/ |
||
153 | public function getBlocksSolvedbyAccount($limit=25) { |
||
154 | $this->debug->append("STA " . __METHOD__, 4); |
||
155 | if ($data = $this->memcache->get(__FUNCTION__ . $limit)) return $data; |
||
156 | $stmt = $this->mysqli->prepare(" |
||
157 | SELECT |
||
158 | b.*, |
||
159 | a.username AS finder, |
||
160 | a.is_anonymous AS is_anonymous, |
||
161 | COUNT(b.id) AS solvedblocks, |
||
162 | SUM(b.amount) AS generatedcoins |
||
163 | FROM " . $this->block->getTableName() . " AS b |
||
164 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
165 | ON b.account_id = a.id |
||
166 | WHERE confirmations > 0 |
||
167 | GROUP BY finder |
||
168 | ORDER BY solvedblocks DESC LIMIT ?"); |
||
169 | if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result()) |
||
170 | return $this->memcache->setCache(__FUNCTION__ . $limit, $result->fetch_all(MYSQLI_ASSOC), 5); |
||
171 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getBlocksSolvedbyAccount of type array .
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 ![]() |
|||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Get SUM of blocks found and generated Coins for each worker |
||
176 | * @param limit int Last limit blocks |
||
177 | * @return array |
||
178 | **/ |
||
179 | public function getBlocksSolvedbyWorker($account_id, $limit=25) { |
||
180 | $this->debug->append("STA " . __METHOD__, 4); |
||
181 | if ($data = $this->memcache->get(__FUNCTION__ . $account_id . $limit)) return $data; |
||
182 | $stmt = $this->mysqli->prepare(" |
||
183 | SELECT |
||
184 | worker_name AS finder, |
||
185 | COUNT(id) AS solvedblocks, |
||
186 | SUM(amount) AS generatedcoins |
||
187 | FROM " . $this->block->getTableName() . " |
||
188 | WHERE account_id = ? AND worker_name != 'unknown' |
||
189 | GROUP BY finder |
||
190 | ORDER BY solvedblocks DESC LIMIT ?"); |
||
191 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $account_id, $limit) && $stmt->execute() && $result = $stmt->get_result()) |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
192 | return $this->memcache->setCache(__FUNCTION__ . $account_id . $limit, $result->fetch_all(MYSQLI_ASSOC), 5); |
||
193 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getBlocksSolvedbyWorker of type array .
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 ![]() |
|||
194 | } |
||
195 | |||
196 | /** |
||
197 | * Currently the only function writing to the database |
||
198 | * Stored per block user statistics of valid and invalid shares |
||
199 | * @param aStats array Array with user id, valid and invalid shares |
||
200 | * @param iBlockId int Block ID as store in the Block table |
||
201 | * @return bool |
||
202 | **/ |
||
203 | public function updateShareStatistics($aStats, $iBlockId) { |
||
204 | $this->debug->append("STA " . __METHOD__, 4); |
||
205 | $stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, valid, invalid, block_id) VALUES (?, ?, ?, ?)"); |
||
206 | if ($this->checkStmt($stmt) && $stmt->bind_param('iddi', $aStats['id'], $aStats['valid'], $aStats['invalid'], $iBlockId) && $stmt->execute()) return true; |
||
207 | return $this->sqlError(); |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * insert user round and pplns shares merged array |
||
212 | **/ |
||
213 | public function insertPPLNSStatistics($aStats, $iBlockId) { |
||
214 | $this->debug->append("STA " . __METHOD__, 4); |
||
215 | $stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, valid, invalid, pplns_valid, pplns_invalid, block_id) VALUES (?, ?, ?, ?, ?, ?)"); |
||
216 | if ($this->checkStmt($stmt) && $stmt->bind_param('iddddi', $aStats['id'], $aStats['valid'], $aStats['invalid'], $aStats['pplns_valid'], $aStats['pplns_invalid'], $iBlockId) && $stmt->execute()) return true; |
||
217 | return $this->sqlError(); |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * Get our current pool hashrate for the past 10 minutes across both |
||
222 | * shares and shares_archive table |
||
223 | * @param none |
||
224 | * @return data object Return our hashrateas an object |
||
225 | **/ |
||
226 | public function getCurrentHashrate($interval=180) { |
||
227 | $this->debug->append("STA " . __METHOD__, 4); |
||
228 | if ($this->getGetCache() && $data = $this->memcache->getStatic(__FUNCTION__)) return $data; |
||
229 | $stmt = $this->mysqli->prepare(" |
||
230 | SELECT |
||
231 | ( |
||
232 | ( |
||
233 | SELECT IFNULL(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS shares |
||
0 ignored issues
–
show
The property
config does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
234 | FROM " . $this->share->getTableName() . " |
||
0 ignored issues
–
show
The property
share does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
235 | WHERE time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
236 | AND our_result = 'Y' |
||
237 | ) + ( |
||
238 | SELECT IFNULL(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS shares |
||
239 | FROM " . $this->share->getArchiveTableName() . " |
||
240 | WHERE time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
241 | AND our_result = 'Y' |
||
242 | ) |
||
243 | ) AS shares |
||
244 | FROM DUAL"); |
||
245 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $interval, $interval) && $stmt->execute() && $result = $stmt->get_result() ) { |
||
246 | $hashrate = $this->coin->calcHashrate($result->fetch_object()->shares, $interval); |
||
247 | return $this->memcache->setStaticCache(__FUNCTION__, $hashrate); |
||
248 | } |
||
249 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getCurrentHashrate of type data .
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 ![]() |
|||
250 | } |
||
251 | |||
252 | /** |
||
253 | * Same as getCurrentHashrate but for Shares |
||
254 | * @param none |
||
255 | * @return data object Our share rate in shares per second |
||
256 | **/ |
||
257 | View Code Duplication | public function getCurrentShareRate($interval=180) { |
|
0 ignored issues
–
show
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. ![]() |
|||
258 | $this->debug->append("STA " . __METHOD__, 4); |
||
259 | if ($data = $this->memcache->getStatic(__FUNCTION__)) return $data; |
||
260 | $stmt = $this->mysqli->prepare(" |
||
261 | SELECT |
||
262 | ( |
||
263 | ( |
||
264 | SELECT ROUND(SUM(difficulty) / ?, " . $this->coin->getShareDifficultyPrecision() . ") AS sharerate |
||
265 | FROM " . $this->share->getTableName() . " |
||
266 | WHERE time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
267 | AND our_result = 'Y' |
||
268 | ) + ( |
||
269 | SELECT ROUND(SUM(difficulty) / ?, " . $this->coin->getShareDifficultyPrecision() . ") AS sharerate |
||
270 | FROM " . $this->share->getArchiveTableName() . " |
||
271 | WHERE time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
272 | AND our_result = 'Y' |
||
273 | ) |
||
274 | ) AS sharerate |
||
275 | FROM DUAL"); |
||
276 | if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $interval, $interval, $interval, $interval) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setStaticCache(__FUNCTION__, $result->fetch_object()->sharerate); |
||
277 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getCurrentShareRate of type data .
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 ![]() |
|||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Get total shares for this round, since last block found |
||
282 | * @param none |
||
283 | * @return data array invalid and valid shares |
||
284 | **/ |
||
285 | public function getRoundShares() { |
||
286 | $this->debug->append("STA " . __METHOD__, 4); |
||
287 | // Try the statistics cron cache, then function cache, then fallback to SQL |
||
288 | if ($data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) { |
||
289 | $this->debug->append("Found data in statistics cache", 2); |
||
290 | $total = array('valid' => 0, 'invalid' => 0); |
||
291 | foreach ($data['data'] as $aUser) { |
||
292 | $total['valid'] += $aUser['valid']; |
||
293 | $total['invalid'] += $aUser['invalid']; |
||
294 | } |
||
295 | return $total; |
||
0 ignored issues
–
show
The return type of
return $total; (array ) is incompatible with the return type documented by Statistics::getRoundShares of type data .
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 ![]() |
|||
296 | } |
||
297 | if ($data = $this->memcache->get(STATISTICS_ROUND_SHARES)) { |
||
298 | $this->debug->append("Found data in local cache", 2); |
||
299 | return $data; |
||
300 | } |
||
301 | $stmt = $this->mysqli->prepare(" |
||
302 | SELECT |
||
303 | IFNULL(SUM(IF(our_result='Y', IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0)), 0) AS valid, |
||
304 | IFNULL(SUM(IF(our_result='N', IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0)), 0) AS invalid |
||
305 | FROM " . $this->share->getTableName() . " |
||
306 | WHERE UNIX_TIMESTAMP(time) > IFNULL((SELECT MAX(time) FROM " . $this->block->getTableName() . "), 0)"); |
||
307 | if ( $this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) |
||
308 | return $this->memcache->setCache(STATISTICS_ROUND_SHARES, $result->fetch_assoc()); |
||
309 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getRoundShares of type data .
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 ![]() |
|||
310 | } |
||
311 | |||
312 | /** |
||
313 | * Get amount of shares for a all users |
||
314 | * Used in statistics cron to refresh memcache data |
||
315 | * @param account_id int User ID |
||
316 | * @return data array invalid and valid share counts |
||
317 | **/ |
||
318 | public function getAllUserShares() { |
||
319 | $this->debug->append("STA " . __METHOD__, 4); |
||
320 | if (! $data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) { |
||
321 | $data['share_id'] = 0; |
||
322 | $data['data'] = array(); |
||
323 | } |
||
324 | $stmt = $this->mysqli->prepare(" |
||
325 | SELECT |
||
326 | IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS valid, |
||
327 | IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS invalid, |
||
328 | u.id AS id, |
||
329 | u.donate_percent AS donate_percent, |
||
330 | u.is_anonymous AS is_anonymous, |
||
331 | u.username AS username |
||
332 | FROM " . $this->share->getTableName() . " AS s, |
||
333 | " . $this->user->getTableName() . " AS u |
||
334 | WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 ) |
||
335 | AND UNIX_TIMESTAMP(s.time) > IFNULL( |
||
336 | ( |
||
337 | SELECT MAX(b.time) |
||
338 | FROM " . $this->block->getTableName() . " AS b |
||
339 | ) ,0 ) |
||
340 | AND s.id > ? |
||
341 | GROUP BY u.id"); |
||
342 | if ($stmt && $stmt->bind_param('i', $data['share_id']) && $stmt->execute() && $result = $stmt->get_result()) { |
||
343 | $data_new = array(); |
||
0 ignored issues
–
show
$data_new is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
344 | while ($row = $result->fetch_assoc()) { |
||
345 | if (! array_key_exists($row['id'], $data['data'])) { |
||
346 | $data['data'][$row['id']] = $row; |
||
347 | } else { |
||
348 | $data['data'][$row['id']]['valid'] += $row['valid']; |
||
349 | $data['data'][$row['id']]['invalid'] += $row['invalid']; |
||
350 | $data['data'][$row['id']]['donate_percent'] = $row['donate_percent']; |
||
351 | $data['data'][$row['id']]['is_anonymous'] = $row['is_anonymous']; |
||
352 | } |
||
353 | } |
||
354 | $data['share_id'] = $this->share->getLastInsertedShareId(); |
||
355 | return $this->memcache->setCache(STATISTICS_ALL_USER_SHARES, $data); |
||
356 | } |
||
357 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getAllUserShares of type data .
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 ![]() |
|||
358 | } |
||
359 | |||
360 | /** |
||
361 | * Get amount of shares for a specific user |
||
362 | * @param username str username |
||
363 | * @param account_id int account id |
||
364 | * @return data array invalid and valid share counts |
||
365 | **/ |
||
366 | public function getUserShares($username, $account_id=NULL) { |
||
367 | $this->debug->append("STA " . __METHOD__, 4); |
||
368 | // Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL |
||
369 | if ($data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) { |
||
370 | if (array_key_exists($account_id, $data['data'])) |
||
371 | return $data['data'][$account_id]; |
||
372 | // We have no cached value, we return defaults |
||
373 | return array('valid' => 0, 'invalid' => 0, 'donate_percent' => 0, 'is_anonymous' => 0); |
||
0 ignored issues
–
show
The return type of
return array('valid' => ..., 'is_anonymous' => 0); (array<string,integer> ) is incompatible with the return type documented by Statistics::getUserShares of type data .
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 ![]() |
|||
374 | } |
||
375 | if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; |
||
376 | $stmt = $this->mysqli->prepare(" |
||
377 | SELECT |
||
378 | IFNULL(SUM(IF(our_result='Y', IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0)), 0) AS valid, |
||
379 | IFNULL(SUM(IF(our_result='N', IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0)), 0) AS invalid |
||
380 | FROM " . $this->share->getTableName() . " |
||
381 | WHERE username LIKE ? |
||
382 | AND UNIX_TIMESTAMP(time) >IFNULL((SELECT MAX(b.time) FROM " . $this->block->getTableName() . " AS b),0)"); |
||
383 | $username = $username . ".%"; |
||
384 | if ($stmt && $stmt->bind_param("s", $username) && $stmt->execute() && $result = $stmt->get_result()) |
||
385 | return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_assoc()); |
||
386 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getUserShares of type data .
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 ![]() |
|||
387 | } |
||
388 | |||
389 | /** |
||
390 | * Admin panel specific query |
||
391 | * @return data array User settings and shares |
||
392 | **/ |
||
393 | public function getAllUserStats($filter='%',$limit=1,$start=0) { |
||
394 | $this->debug->append("STA " . __METHOD__, 4); |
||
395 | $sql = " |
||
396 | SELECT |
||
397 | a.id AS id, |
||
398 | a.is_admin as is_admin, |
||
399 | a.is_locked as is_locked, |
||
400 | a.no_fees as no_fees, |
||
401 | a.username AS username, |
||
402 | a.donate_percent AS donate_percent, |
||
403 | a.email AS email, |
||
404 | a.last_login as last_login |
||
405 | FROM " . $this->user->getTableName() . " AS a"; |
||
406 | if (is_array($filter)) { |
||
407 | $aFilter = array(); |
||
408 | foreach ($filter as $key => $value) { |
||
409 | if (isset($value) && $value != "" ) { |
||
410 | switch ($key) { |
||
411 | case 'account': |
||
412 | $aFilter[] = "a.username LIKE ?"; |
||
413 | $this->addParam('s', $value); |
||
414 | break; |
||
415 | case 'email': |
||
416 | $aFilter[] = "a.email LIKE ?"; |
||
417 | $this->addParam('s', $value); |
||
418 | break; |
||
419 | case 'is_admin': |
||
420 | $aFilter[] = "a.is_admin = ?"; |
||
421 | $this->addParam('i', $value); |
||
422 | break; |
||
423 | case 'is_locked': |
||
424 | $aFilter[] = "a.is_locked = ?"; |
||
425 | $this->addParam('i', $value); |
||
426 | break; |
||
427 | case 'no_fees': |
||
428 | $aFilter[] = "a.no_fees = ?"; |
||
429 | $this->addParam('i', $value); |
||
430 | break; |
||
431 | } |
||
432 | } |
||
433 | } |
||
434 | } |
||
435 | if (!empty($aFilter)) { |
||
436 | $sql .= " WHERE "; |
||
437 | $sql .= implode(' AND ', $aFilter); |
||
438 | } |
||
439 | $sql .= " |
||
440 | ORDER BY username |
||
441 | LIMIT ?,?"; |
||
442 | $this->addParam('i', $start); |
||
443 | $this->addParam('i', $limit); |
||
444 | $stmt = $this->mysqli->prepare($sql); |
||
445 | if ($this->checkStmt($stmt) && call_user_func_array( array($stmt, 'bind_param'), $this->getParam()) && $stmt->execute() && $result = $stmt->get_result()) { |
||
446 | // Add our cached shares to the users |
||
447 | $aUsers = array(); |
||
448 | while ($row = $result->fetch_assoc()) { |
||
449 | $row['shares'] = $this->getUserShares($row['username'], $row['id']); |
||
450 | $aUsers[] = $row; |
||
451 | } |
||
452 | if (count($aUsers) > 0) { |
||
453 | return $aUsers; |
||
454 | } |
||
455 | } |
||
456 | return $this->sqlError(); |
||
457 | } |
||
458 | |||
459 | /** |
||
460 | * Fetch all user hashrates based on shares and archived shares |
||
461 | * Store it in cache, also keep a copy of the data internally to |
||
462 | * return it for further processing |
||
463 | * @return data array Set of all user stats |
||
464 | **/ |
||
465 | public function fetchAllUserMiningStats($interval=180) { |
||
466 | $this->debug->append("STA " . __METHOD__, 4); |
||
467 | $stmt = $this->mysqli->prepare(" |
||
468 | SELECT |
||
469 | a.id AS id, |
||
470 | a.username AS account, |
||
471 | COUNT(DISTINCT t1.username) AS workers, |
||
472 | IFNULL(SUM(t1.difficulty), 0) AS shares, |
||
473 | ROUND(SUM(t1.difficulty) / ?, " . $this->coin->getShareDifficultyPrecision() . ") AS sharerate, |
||
474 | IFNULL(AVG(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS avgsharediff |
||
475 | FROM ( |
||
476 | SELECT |
||
477 | id, |
||
478 | IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty, |
||
479 | username |
||
480 | FROM " . $this->share->getTableName() . " |
||
481 | WHERE time > DATE_SUB(now(), INTERVAL ? SECOND) AND our_result = 'Y' |
||
482 | UNION |
||
483 | SELECT |
||
484 | share_id, |
||
485 | IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty, |
||
486 | username |
||
487 | FROM " . $this->share->getArchiveTableName() . " |
||
488 | WHERE time > DATE_SUB(now(), INTERVAL ? SECOND) AND our_result = 'Y' |
||
489 | ) AS t1 |
||
490 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
491 | ON SUBSTRING_INDEX( t1.username, '.', 1 ) = a.username |
||
492 | WHERE a.id IS NOT NULL |
||
493 | GROUP BY account |
||
494 | ORDER BY shares DESC |
||
495 | "); |
||
496 | if ($this->checkStmt($stmt) && $stmt->bind_param("iii", $interval, $interval, $interval) && $stmt->execute() && $result = $stmt->get_result() ) { |
||
497 | $aData = array(); |
||
498 | while ($row = $result->fetch_assoc()) { |
||
499 | $aData['data'][$row['id']] = $row; |
||
500 | $aData['data'][$row['id']]['hashrate'] = $this->coin->calcHashrate($row['shares'], $interval); |
||
501 | } |
||
502 | $this->allUserMiningStats = $aData; |
||
503 | return $this->memcache->setStaticCache(STATISTICS_ALL_USER_HASHRATES, $aData, 600); |
||
504 | } else { |
||
505 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::fetchAllUserMiningStats of type data .
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 ![]() |
|||
506 | } |
||
507 | } |
||
508 | |||
509 | /** |
||
510 | * Store our gathered data into our statistic table for users |
||
511 | * @param aData array Data created by fetchAllUserMiningStats |
||
512 | * @return bool true or false |
||
513 | **/ |
||
514 | public function storeAllUserMiningStatsSnapshot($aData) { |
||
515 | $this->debug->append("STA " . __METHOD__, 4); |
||
516 | if (!isset($aData['data'])) return false; |
||
517 | // initilize |
||
518 | $timestamp = time(); // Store all entries with the same timestamp to reduce cardinality |
||
519 | $ok = 0; |
||
520 | $failed = 0; |
||
521 | foreach ($aData['data'] as $key => $aUserData) { |
||
522 | $stmt = $this->mysqli->prepare(" |
||
523 | INSERT INTO " . $this->getUserStatsTableName() . " |
||
524 | ( account_id, hashrate, workers, sharerate, timestamp ) VALUES ( ?, ?, ?, ?, ?)"); |
||
525 | if ($this->checkStmt($stmt) && $stmt->bind_param("ididi", $aUserData['id'], $aUserData['hashrate'], $aUserData['workers'], $aUserData['sharerate'], $timestamp) && $stmt->execute() ) { |
||
526 | $ok++; |
||
527 | } else { |
||
528 | $failed++; |
||
529 | } |
||
530 | } |
||
531 | return array('ok' => $ok, 'failed' => $failed); |
||
532 | } |
||
533 | |||
534 | /** |
||
535 | * Fetch unpaid PPS shares for an account |
||
536 | * @param username string Username |
||
537 | * @param account_id int User ID |
||
538 | * @param last_paid_pps_id int Last paid out share by pps_payout cron |
||
539 | * @return data int Sum of unpaid diff1 shares |
||
540 | **/ |
||
541 | public function getUserUnpaidPPSShares($username, $account_id=NULL, $last_paid_pps_id) { |
||
542 | $this->debug->append("STA " . __METHOD__, 4); |
||
543 | if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; |
||
544 | $stmt = $this->mysqli->prepare(" |
||
545 | SELECT |
||
546 | IFNULL(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS total |
||
547 | FROM " . $this->share->getTableName() . " |
||
548 | WHERE username LIKE ? |
||
549 | AND id > ? |
||
550 | AND our_result = 'Y'"); |
||
551 | $username = $username . ".%"; |
||
552 | if ($this->checkStmt($stmt) && $stmt->bind_param("si", $username, $last_paid_pps_id) && $stmt->execute() && $result = $stmt->get_result() ) |
||
553 | return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->total); |
||
554 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getUserUnpaidPPSShares of type data .
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 ![]() |
|||
555 | } |
||
556 | |||
557 | /** |
||
558 | * Get Shares per x interval by user |
||
559 | * @param username string username |
||
560 | * @param $account_id int account id |
||
561 | * @return data integer Current Sharerate in diff1 shares/s |
||
562 | **/ |
||
563 | public function getUserMiningStats($username, $account_id=NULL, $interval=180) { |
||
564 | $this->debug->append("STA " . __METHOD__, 4); |
||
565 | // Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL |
||
566 | if ($this->getGetCache() && $data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) { |
||
567 | if (array_key_exists($account_id, $data['data'])) { |
||
568 | $retData['hashrate'] = $data['data'][$account_id]['hashrate']; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$retData was never initialized. Although not strictly required by PHP, it is generally a good practice to add $retData = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
569 | $retData['sharerate'] = $data['data'][$account_id]['sharerate']; |
||
570 | $retData['avgsharediff'] = $data['data'][$account_id]['avgsharediff']; |
||
571 | return $retData; |
||
0 ignored issues
–
show
The return type of
return $retData; (array ) is incompatible with the return type documented by Statistics::getUserMiningStats of type data .
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 ![]() |
|||
572 | } |
||
573 | return array('hashrate' => (float)0, 'sharerate' => (float)0, 'avgsharediff' => (float)0); |
||
0 ignored issues
–
show
The return type of
return array('hashrate' ...rediff' => (double) 0); (array<string,double> ) is incompatible with the return type documented by Statistics::getUserMiningStats of type data .
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 ![]() |
|||
574 | } |
||
575 | if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; |
||
576 | $stmt = $this->mysqli->prepare(" |
||
577 | SELECT |
||
578 | IFNULL(SUM(difficulty) / ?, 0) AS sharerate, |
||
579 | IFNULL(SUM(difficulty), 0) AS shares, |
||
580 | IFNULL(AVG(difficulty), 0) AS avgsharediff |
||
581 | FROM ( |
||
582 | SELECT |
||
583 | id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty |
||
584 | FROM |
||
585 | " . $this->share->getTableName() . " |
||
586 | WHERE username LIKE ? |
||
587 | AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
588 | AND our_result = 'Y' |
||
589 | UNION |
||
590 | SELECT |
||
591 | share_id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty |
||
592 | FROM |
||
593 | " . $this->share->getArchiveTableName() . " |
||
594 | WHERE username LIKE ? |
||
595 | AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
596 | AND our_result = 'Y' |
||
597 | ) AS temp"); |
||
598 | $username = $username . ".%"; |
||
599 | if ($this->checkStmt($stmt) && $stmt->bind_param("isisi", $interval, $username, $interval, $username, $interval) && $stmt->execute() && $result = $stmt->get_result() ) { |
||
600 | $aData = $result->fetch_assoc(); |
||
601 | $aData['hashrate'] = $this->coin->calcHashrate($aData['shares'], $interval); |
||
602 | return $this->memcache->setCache(__FUNCTION__ . $account_id, $aData); |
||
603 | } |
||
604 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getUserMiningStats of type data .
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 ![]() |
|||
605 | } |
||
606 | |||
607 | /** |
||
608 | * get our top contributors for either shares or hashrate |
||
609 | * @param type string shares or hashes |
||
610 | * @param limit int Limit result to $limit |
||
611 | * @return data array Users with shares, account or hashrate, account |
||
612 | **/ |
||
613 | public function getTopContributors($type='shares', $limit=15) { |
||
614 | $this->debug->append("STA " . __METHOD__, 4); |
||
615 | switch ($type) { |
||
616 | case 'shares': |
||
617 | View Code Duplication | if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $type . $limit)) return $data; |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
618 | if ($data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) { |
||
619 | // Use global cache to build data, if we have any data there |
||
620 | if (!empty($data['data']) && is_array($data['data'])) { |
||
621 | foreach($data['data'] as $key => $aUser) { |
||
622 | $shares[$key] = $aUser['valid']; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$shares was never initialized. Although not strictly required by PHP, it is generally a good practice to add $shares = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
623 | $username[$key] = $aUser['username']; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$username was never initialized. Although not strictly required by PHP, it is generally a good practice to add $username = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
624 | } |
||
625 | array_multisort($shares, SORT_DESC, $username, SORT_ASC, $data['data']); |
||
0 ignored issues
–
show
The variable
$username does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
626 | $count = 0; |
||
627 | foreach ($data['data'] as $key => $aUser) { |
||
628 | if ($count == $limit) break; |
||
629 | $count++; |
||
630 | $data_new[$key]['shares'] = $aUser['valid']; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$data_new was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data_new = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
631 | $data_new[$key]['account'] = $aUser['username']; |
||
632 | $data_new[$key]['donate_percent'] = $aUser['donate_percent']; |
||
633 | $data_new[$key]['is_anonymous'] = $aUser['is_anonymous']; |
||
634 | } |
||
635 | return $data_new; |
||
0 ignored issues
–
show
The variable
$data_new does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
636 | } |
||
637 | } |
||
638 | // No cached data, fallback to SQL ONLY if we don't use memcache |
||
639 | if ($this->config['memcache']['enabled'] && $this->config['memcache']['force']['contrib_shares']) { |
||
640 | // Do not use SQL queries and a second layer of caching |
||
641 | $this->debug->append('Skipping SQL queries due to config option', 4); |
||
642 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type documented by Statistics::getTopContributors of type data .
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 ![]() |
|||
643 | } |
||
644 | $stmt = $this->mysqli->prepare(" |
||
645 | SELECT |
||
646 | a.username AS account, |
||
647 | a.donate_percent AS donate_percent, |
||
648 | a.is_anonymous AS is_anonymous, |
||
649 | IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) AS shares |
||
650 | FROM " . $this->share->getTableName() . " AS s |
||
651 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
652 | ON SUBSTRING_INDEX( s.username, '.', 1 ) = a.username |
||
653 | WHERE our_result = 'Y' |
||
654 | GROUP BY account |
||
655 | ORDER BY shares DESC |
||
656 | LIMIT ?"); |
||
657 | if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result()) |
||
658 | return $this->memcache->setCache(__FUNCTION__ . $type . $limit, $result->fetch_all(MYSQLI_ASSOC)); |
||
659 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getTopContributors of type data .
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 ![]() |
|||
660 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
661 | |||
662 | case 'hashes': |
||
663 | View Code Duplication | if ($this->getGetCache() && $data = $this->memcache->getStatic(__FUNCTION__ . $type . $limit)) return $data; |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
664 | $stmt = $this->mysqli->prepare(" |
||
665 | SELECT |
||
666 | a.username AS account, |
||
667 | a.donate_percent AS donate_percent, |
||
668 | a.is_anonymous AS is_anonymous, |
||
669 | IFNULL(SUM(t1.difficulty), 0) AS shares |
||
670 | FROM |
||
671 | ( |
||
672 | SELECT id, IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty, username FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND our_result = 'Y' |
||
673 | UNION |
||
674 | SELECT share_id, IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty, username FROM " . $this->share->getArchiveTableName() ." WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND our_result = 'Y' |
||
675 | ) AS t1 |
||
676 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
677 | ON SUBSTRING_INDEX( t1.username, '.', 1 ) = a.username |
||
678 | GROUP BY account |
||
679 | ORDER BY shares DESC LIMIT ?"); |
||
680 | if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result()) { |
||
681 | $aData = array(); |
||
682 | $count = 0; |
||
683 | while ($row = $result->fetch_assoc()) { |
||
684 | $aData[$count] = $row; |
||
685 | $aData[$count]['hashrate'] = $this->coin->calcHashrate($row['shares'], 600); |
||
686 | $count++; |
||
687 | } |
||
688 | return $this->memcache->setStaticCache(__FUNCTION__ . $type . $limit, $aData); |
||
689 | } |
||
690 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getTopContributors of type data .
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 ![]() |
|||
691 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
692 | } |
||
693 | } |
||
694 | |||
695 | /** |
||
696 | * get Hourly hashrate for a user |
||
697 | * @param username string Username |
||
698 | * @param $account_id int account id |
||
699 | * @return data array NOT FINISHED YET |
||
700 | **/ |
||
701 | public function getHourlyMiningStatsByAccount($account_id, $format='array', $days = 1) { |
||
702 | $this->debug->append("STA " . __METHOD__, 4); |
||
703 | if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; |
||
704 | $stmt = $this->mysqli->prepare(" |
||
705 | SELECT |
||
706 | timestamp, |
||
707 | FROM_UNIXTIME(timestamp, '%Y-%m-%d %H:%i') AS time, |
||
708 | AVG(hashrate) AS hashrate, |
||
709 | AVG(workers) AS workers, |
||
710 | AVG(sharerate) AS sharerate |
||
711 | FROM " . $this->getUserStatsTableName() . " |
||
712 | WHERE FROM_UNIXTIME(timestamp) >= DATE_SUB(NOW(), INTERVAL $days DAY) |
||
713 | AND account_id = ? |
||
714 | GROUP BY DAY(FROM_UNIXTIME(timestamp)), HOUR(FROM_UNIXTIME(timestamp))"); |
||
715 | if ($this->checkStmt($stmt) && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result()) { |
||
716 | $aData = $result->fetch_all(MYSQLI_ASSOC); |
||
717 | if ($format == 'json') $aData = json_encode($aData); |
||
718 | return $this->memcache->setCache(__FUNCTION__ . $account_id . $format, $aData); |
||
719 | } |
||
720 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getHourlyMiningStatsByAccount of type data .
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 ![]() |
|||
721 | } |
||
722 | |||
723 | /** |
||
724 | * get user estimated payouts based on share counts |
||
725 | * @param value1 mixed Round shares OR share rate |
||
726 | * @param value2 mixed User shares OR share difficulty |
||
727 | * @param dDonate double User donation setting |
||
728 | * @param bNoFees bool User no-fees option setting |
||
729 | * @return aEstimates array User estimations |
||
730 | **/ |
||
731 | public function getUserEstimates($value1, $value2, $dDonate, $bNoFees, $ppsvalue=0) { |
||
732 | $this->debug->append("STA " . __METHOD__, 4); |
||
733 | if ($this->config['payout_system'] != 'pps') { |
||
734 | if (@$value1['valid'] > 0 && @$value2['valid'] > 0) { |
||
735 | $this->config['reward_type'] == 'fixed' ? $reward = $this->config['reward'] : $reward = $this->block->getAverageAmount(); |
||
736 | $aEstimates['block'] = round(( (float)$value2['valid'] / (float)$value1['valid'] ) * (float)$reward, 8); |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$aEstimates was never initialized. Although not strictly required by PHP, it is generally a good practice to add $aEstimates = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
737 | $bNoFees == 0 ? $aEstimates['fee'] = round(((float)$this->config['fees'] / 100) * (float)$aEstimates['block'], 8) : $aEstimates['fee'] = 0; |
||
738 | $aEstimates['donation'] = round((( (float)$dDonate / 100) * ((float)$aEstimates['block'] - (float)$aEstimates['fee'])), 8); |
||
739 | $aEstimates['payout'] = round((float)$aEstimates['block'] - (float)$aEstimates['donation'] - (float)$aEstimates['fee'], 8); |
||
740 | } else { |
||
741 | $aEstimates['block'] = 0; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$aEstimates was never initialized. Although not strictly required by PHP, it is generally a good practice to add $aEstimates = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
742 | $aEstimates['fee'] = 0; |
||
743 | $aEstimates['donation'] = 0; |
||
744 | $aEstimates['payout'] = 0; |
||
745 | } |
||
746 | } else { |
||
747 | // Hack so we can use this method for PPS estimates too |
||
748 | // value1 = shares/s |
||
749 | // value2 = avg share difficulty |
||
750 | if (@$value1 > 0 && @$value2 > 0) { |
||
751 | $hour = 60 * 60; |
||
752 | $pps = $value1 * $value2 * $ppsvalue; |
||
753 | $aEstimates['hours1'] = $pps * $hour; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$aEstimates was never initialized. Although not strictly required by PHP, it is generally a good practice to add $aEstimates = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
754 | $aEstimates['hours24'] = $pps * 24 * $hour; |
||
755 | $aEstimates['days7'] = $pps * 24 * 7 * $hour; |
||
756 | $aEstimates['days14'] = $pps * 14 * 24 * $hour; |
||
757 | $aEstimates['days30'] = $pps * 30 * 24 * $hour; |
||
758 | } else { |
||
759 | $aEstimates['hours1'] = 0; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$aEstimates was never initialized. Although not strictly required by PHP, it is generally a good practice to add $aEstimates = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
760 | $aEstimates['hours24'] = 0; |
||
761 | $aEstimates['days7'] = 0; |
||
762 | $aEstimates['days14'] = 0; |
||
763 | $aEstimates['days30'] = 0; |
||
764 | } |
||
765 | } |
||
766 | return $aEstimates; |
||
767 | } |
||
768 | |||
769 | /** |
||
770 | * Get pool stats last 24 hours |
||
771 | * @param limit int Last number of hours |
||
772 | * @return array |
||
773 | **/ |
||
774 | public function getPoolStatsHours($hour=24) { |
||
775 | $this->debug->append("STA " . __METHOD__, 4); |
||
776 | if ($data = $this->memcache->get(__FUNCTION__ . $hour)) return $data; |
||
777 | $stmt = $this->mysqli->prepare(" |
||
778 | SELECT |
||
779 | IFNULL(COUNT(id), 0) as count, |
||
780 | IFNULL(AVG(difficulty), 0) as average, |
||
781 | IFNULL(SUM(shares), 0) as shares, |
||
782 | IFNULL(SUM(amount), 0) as rewards |
||
783 | FROM " . $this->block->getTableName() . " |
||
784 | WHERE FROM_UNIXTIME(time) > DATE_SUB(now(), INTERVAL ? HOUR) |
||
785 | AND confirmations >= 1"); |
||
786 | if ($this->checkStmt($stmt) && $stmt->bind_param("i", $hour) && $stmt->execute() && $result = $stmt->get_result()) { |
||
787 | $aData = $result->fetch_assoc(); |
||
788 | $aData['expected'] = $this->coin->calcEstaimtedShares($aData['average']); |
||
789 | return $this->memcache->setCache(__FUNCTION__ . $hour, $aData); |
||
790 | } |
||
791 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getPoolStatsHours of type array .
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 ![]() |
|||
792 | } |
||
793 | |||
794 | /** |
||
795 | * Caclulate estimated shares based on network difficulty and pool difficulty |
||
796 | * @param dDiff double Network difficulty |
||
797 | * @return shares integer Share count |
||
798 | **/ |
||
799 | public function getEstimatedShares($dDiff) { |
||
800 | return $this->coin->calcEstaimtedShares($dDiff); |
||
801 | } |
||
802 | |||
803 | /** |
||
804 | * Get the Expected Time per Block in the whole Network in seconde |
||
805 | * @return seconds double Seconds per Block |
||
806 | */ |
||
807 | public function getExpectedTimePerBlock($type='network',$hashrate = 0){ |
||
808 | if ($data = $this->memcache->get(__FUNCTION__)) return $data; |
||
809 | |||
810 | if ($this->bitcoin->can_connect() === true) { |
||
811 | if ($type == 'network') { |
||
812 | $hashrate = $this->bitcoin->getnetworkhashps(); |
||
0 ignored issues
–
show
The property
bitcoin does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
813 | } else { |
||
814 | // We need hashes/second and expect khash as input |
||
815 | $hashrate = $hashrate * 1000; |
||
816 | } |
||
817 | $dDifficulty = $this->bitcoin->getdifficulty(); |
||
818 | } else { |
||
819 | $hashrate = 1; |
||
820 | $dDifficulty = 1; |
||
821 | } |
||
822 | if ($hashrate <= 0) $hashrate = 1; |
||
823 | return $this->memcache->setCache(__FUNCTION__ . '_' . $type, $this->coin->calcNetworkExpectedTimePerBlock($dDifficulty, $hashrate)); |
||
824 | } |
||
825 | |||
826 | /** |
||
827 | * Get the Expected next Difficulty |
||
828 | * @return difficulty double Next difficulty |
||
829 | **/ |
||
830 | public function getExpectedNextDifficulty(){ |
||
831 | if ($data = $this->memcache->get(__FUNCTION__)) return $data; |
||
832 | |||
833 | if ($this->bitcoin->can_connect() === true) { |
||
834 | $dDifficulty = $this->bitcoin->getdifficulty(); |
||
835 | $dNetworkHashrate = $this->bitcoin->getnetworkhashps(); |
||
836 | } else { |
||
837 | $dDifficulty = 1; |
||
838 | $dNetworkHashrate = 1; |
||
839 | } |
||
840 | |||
841 | return $this->memcache->setCache(__FUNCTION__, $this->coin->calcExpectedNextDifficulty($dDifficulty, $dNetworkHashrate)); |
||
842 | } |
||
843 | |||
844 | /** |
||
845 | * Get Number of blocks until next difficulty change |
||
846 | * @return blocks int blocks until difficulty change |
||
847 | **/ |
||
848 | public function getBlocksUntilDiffChange(){ |
||
849 | if ($data = $this->memcache->get(__FUNCTION__)) return $data; |
||
850 | |||
851 | if ($this->bitcoin->can_connect() === true) { |
||
852 | $iBlockcount = $this->bitcoin->getblockcount(); |
||
853 | } else { |
||
854 | $iBlockcount = 1; |
||
855 | } |
||
856 | |||
857 | return $this->memcache->setCache(__FUNCTION__, $this->config['coindiffchangetarget'] - ($iBlockcount % $this->config['coindiffchangetarget'])); |
||
858 | } |
||
859 | |||
860 | /** |
||
861 | * Get current PPS value |
||
862 | * @return value double PPS Value |
||
863 | **/ |
||
864 | |||
865 | public function getPPSValue() { |
||
866 | // Fetch RPC difficulty |
||
867 | if ($this->bitcoin->can_connect() === true) { |
||
868 | $dDifficulty = $this->bitcoin->getdifficulty(); |
||
869 | } else { |
||
870 | $dDifficulty = 1; |
||
871 | } |
||
872 | |||
873 | if ($this->config['pps']['reward']['type'] == 'blockavg' && $this->block->getBlockCount() > 0) { |
||
874 | $pps_reward = round($this->block->getAvgBlockReward($this->config['pps']['blockavg']['blockcount'])); |
||
875 | } else { |
||
876 | if ($this->config['pps']['reward']['type'] == 'block') { |
||
877 | if ($aLastBlock = $this->block->getLast()) { |
||
878 | $pps_reward = $aLastBlock['amount']; |
||
879 | } else { |
||
880 | $pps_reward = $this->config['pps']['reward']['default']; |
||
881 | } |
||
882 | } else { |
||
883 | $pps_reward = $this->config['pps']['reward']['default']; |
||
884 | } |
||
885 | } |
||
886 | return round($this->coin->calcPPSValue($pps_reward, $dDifficulty), 12); |
||
887 | } |
||
888 | |||
889 | /** |
||
890 | * Get all currently active users in the past 2 minutes |
||
891 | * @param interval int Time in seconds to fetch shares from |
||
892 | * @return data mixed int count if any users are active, false otherwise |
||
893 | **/ |
||
894 | View Code Duplication | public function getCountAllActiveUsers($interval=120) { |
|
0 ignored issues
–
show
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. ![]() |
|||
895 | $this->debug->append("STA " . __METHOD__, 4); |
||
896 | if ($data = $this->memcache->get(__FUNCTION__)) return $data; |
||
897 | $stmt = $this->mysqli->prepare(" |
||
898 | SELECT COUNT(DISTINCT(SUBSTRING_INDEX( `username` , '.', 1 ))) AS total |
||
899 | FROM " . $this->share->getTableName() . " |
||
900 | WHERE our_result = 'Y' |
||
901 | AND time > DATE_SUB(now(), INTERVAL ? SECOND)"); |
||
902 | if ($this->checkStmt($stmt) && $stmt->bind_param('i', $interval) && $stmt->execute() && $result = $stmt->get_result()) |
||
903 | return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->total); |
||
904 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Statistics::getCountAllActiveUsers of type data .
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 ![]() |
|||
905 | } |
||
906 | |||
907 | /** |
||
908 | * Purge older entries from our statistics_users table |
||
909 | **/ |
||
910 | public function purgeUserStats($days = 1) { |
||
911 | // Fallbacks if unset |
||
912 | $stmt = $this->mysqli->prepare("DELETE FROM " . $this->getUserStatsTableName() . " WHERE FROM_UNIXTIME(timestamp) <= DATE_SUB(NOW(), INTERVAL ? DAY)"); |
||
913 | if ($this->checkStmt($stmt) && $stmt->bind_param('i', $days) && $stmt->execute()) |
||
914 | return $stmt->affected_rows; |
||
915 | return $this->sqlError(); |
||
916 | } |
||
917 | } |
||
918 | |||
919 | $statistics = new Statistics(); |
||
920 | $statistics->setDebug($debug); |
||
921 | $statistics->setMysql($mysqli); |
||
922 | $statistics->setShare($share); |
||
923 | $statistics->setUser($user); |
||
924 | $statistics->setBlock($block); |
||
925 | $statistics->setMemcache($memcache); |
||
926 | $statistics->setConfig($config); |
||
927 | $statistics->setBitcoin($bitcoin); |
||
928 | $statistics->setErrorCodes($aErrorCodes); |
||
929 | $statistics->setCoin($coin); |
||
930 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: