MediaWiki REL1_35
Pingback.php
Go to the documentation of this file.
1<?php
25use Psr\Log\LoggerInterface;
26
32class Pingback {
33
39 private const SCHEMA_REV = 15781718;
40
42 protected $logger;
43
45 protected $config;
46
48 protected $key;
49
51 protected $id;
52
57 public function __construct( Config $config = null, LoggerInterface $logger = null ) {
58 $this->config = $config ?: RequestContext::getMain()->getConfig();
59 $this->logger = $logger ?: LoggerFactory::getInstance( __CLASS__ );
60 $this->key = 'Pingback-' . MW_VERSION;
61 }
62
67 private function shouldSend() {
68 return $this->config->get( 'Pingback' ) && !$this->checkIfSent();
69 }
70
75 private function checkIfSent() {
77 $timestamp = $dbr->selectField(
78 'updatelog',
79 'ul_value',
80 [ 'ul_key' => $this->key ],
81 __METHOD__
82 );
83 if ( $timestamp === false ) {
84 return false;
85 }
86 // send heartbeat ping if last ping was over a month ago
87 if ( time() - (int)$timestamp > 60 * 60 * 24 * 30 ) {
88 return false;
89 }
90 return true;
91 }
92
98 private function markSent() {
99 $dbw = wfGetDB( DB_MASTER );
100 $timestamp = time();
101 return $dbw->upsert(
102 'updatelog',
103 [ 'ul_key' => $this->key, 'ul_value' => $timestamp ],
104 'ul_key',
105 [ 'ul_value' => $timestamp ],
106 __METHOD__
107 );
108 }
109
118 private function acquireLock() {
119 $cache = ObjectCache::getLocalClusterInstance();
120 if ( !$cache->add( $this->key, 1, 60 * 60 ) ) {
121 return false; // throttled
122 }
123
124 $dbw = wfGetDB( DB_MASTER );
125 if ( !$dbw->lock( $this->key, __METHOD__, 0 ) ) {
126 return false; // already in progress
127 }
128
129 return true;
130 }
131
144 public function getSystemInfo() {
145 $event = [
146 'database' => $this->config->get( 'DBtype' ),
147 'MediaWiki' => MW_VERSION,
148 'PHP' => PHP_VERSION,
149 'OS' => PHP_OS . ' ' . php_uname( 'r' ),
150 'arch' => PHP_INT_SIZE === 8 ? 64 : 32,
151 'machine' => php_uname( 'm' ),
152 ];
153
154 if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
155 $event['serverSoftware'] = $_SERVER['SERVER_SOFTWARE'];
156 }
157
158 $limit = ini_get( 'memory_limit' );
159 if ( $limit && $limit != -1 ) {
160 $event['memoryLimit'] = $limit;
161 }
162
163 return $event;
164 }
165
171 private function getData() {
172 return [
173 'schema' => 'MediaWikiPingback',
174 'revision' => self::SCHEMA_REV,
175 'wiki' => $this->getOrCreatePingbackId(),
176 'event' => $this->getSystemInfo(),
177 ];
178 }
179
188 private function getOrCreatePingbackId() {
189 if ( !$this->id ) {
190 $id = wfGetDB( DB_REPLICA )->selectField(
191 'updatelog', 'ul_value', [ 'ul_key' => 'PingBack' ], __METHOD__ );
192
193 if ( $id == false ) {
195 $dbw = wfGetDB( DB_MASTER );
196 $dbw->insert(
197 'updatelog',
198 [ 'ul_key' => 'PingBack', 'ul_value' => $id ],
199 __METHOD__,
200 [ 'IGNORE' ]
201 );
202
203 if ( !$dbw->affectedRows() ) {
204 $id = $dbw->selectField(
205 'updatelog', 'ul_value', [ 'ul_key' => 'PingBack' ], __METHOD__ );
206 }
207 }
208
209 $this->id = $id;
210 }
211
212 return $this->id;
213 }
214
230 private function postPingback( array $data ) {
231 $json = FormatJson::encode( $data );
232 $queryString = rawurlencode( str_replace( ' ', '\u0020', $json ) ) . ';';
233 $url = 'https://www.mediawiki.org/beacon/event?' . $queryString;
234 return MediaWikiServices::getInstance()->getHttpRequestFactory()->post( $url, [], __METHOD__ ) !== null;
235 }
236
252 public function sendPingback() {
253 if ( !$this->acquireLock() ) {
254 $this->logger->debug( __METHOD__ . ": couldn't acquire lock" );
255 return false;
256 }
257
258 $data = $this->getData();
259 if ( !$this->postPingback( $data ) ) {
260 $this->logger->warning( __METHOD__ . ": failed to send pingback; check 'http' log" );
261 return false;
262 }
263
264 $this->markSent();
265 $this->logger->debug( __METHOD__ . ": pingback sent OK ({$this->key})" );
266 return true;
267 }
268
273 public static function schedulePingback() {
274 DeferredUpdates::addCallableUpdate( function () {
275 $instance = new Pingback;
276 if ( $instance->shouldSend() ) {
277 $instance->sendPingback();
278 }
279 } );
280 }
281}
const MW_VERSION
The running version of MediaWiki.
Definition Defines.php:40
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
static generateHex( $chars)
Generate a run of cryptographically random data and return it in hexadecimal string format.
PSR-3 logger instance factory.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Send information about this MediaWiki instance to MediaWiki.org.
Definition Pingback.php:32
acquireLock()
Acquire lock for sending a pingback.
Definition Pingback.php:118
getOrCreatePingbackId()
Get a unique, stable identifier for this wiki.
Definition Pingback.php:188
sendPingback()
Send information about this MediaWiki instance to MediaWiki.org.
Definition Pingback.php:252
LoggerInterface $logger
Definition Pingback.php:42
shouldSend()
Should a pingback be sent?
Definition Pingback.php:67
getData()
Get the EventLogging packet to be sent to the server.
Definition Pingback.php:171
postPingback(array $data)
Serialize pingback data and send it to MediaWiki.org via a POST to its event beacon endpoint.
Definition Pingback.php:230
string $id
Randomly-generated identifier for this wiki.
Definition Pingback.php:51
Config $config
Definition Pingback.php:45
string $key
updatelog key (also used as cache/db lock key)
Definition Pingback.php:48
markSent()
Record the fact that we have sent a pingback for this MediaWiki version, to ensure we don't submit da...
Definition Pingback.php:98
__construct(Config $config=null, LoggerInterface $logger=null)
Definition Pingback.php:57
static schedulePingback()
Schedule a deferred callable that will check if a pingback should be sent and (if so) proceed to send...
Definition Pingback.php:273
checkIfSent()
Has a pingback been sent in the last month for this MediaWiki version?
Definition Pingback.php:75
getSystemInfo()
Collect basic data about this MediaWiki installation and return it as an associative array conforming...
Definition Pingback.php:144
Interface for configuration instances.
Definition Config.php:30
$cache
Definition mcc.php:33
const DB_REPLICA
Definition defines.php:25
const DB_MASTER
Definition defines.php:29