Commit 10cda1cc authored by Samuel Hilson's avatar Samuel Hilson
Browse files

Add back folders with case that matches namespace for psr-4 autoload compliance

parent fea34b4c
Pipeline #145298008 passed with stage
in 1 minute and 7 seconds
<?php
/**
* Reverb
* Notifications API
*
* @package Reverb
* @author Alexia E. Smith
* @license GPL-2.0-or-later
*/
declare(strict_types=1);
namespace Reverb\Api;
use ApiBase;
use Hydrawiki\Reverb\Client\V1\Resources\NotificationDismissals as NotificationDismissalsResource;
use MediaWiki\MediaWikiServices;
use Reverb\Identifier\Identifier;
use Reverb\Notification\Notification;
use Reverb\Notification\NotificationBroadcast;
use Reverb\Notification\NotificationBundle;
use Reverb\UserIdHelper;
class ApiNotifications extends ApiBase {
/**
* Main API entry point.
*
* @return void
*/
public function execute() {
$this->params = $this->extractRequestParams();
if (!$this->getUser()->isLoggedIn()) {
$this->dieWithError(['apierror-permissiondenied-generic']);
}
switch ($this->params['do']) {
case 'getNotificationsForUser':
$response = $this->getNotificationsForUser();
break;
case 'dismissNotification':
$response = $this->dismissNotification();
break;
case 'dismissAllNotifications':
$response = $this->dismissAllNotifications();
break;
default:
$this->dieWithError(['invaliddo', $this->params['do']]);
break;
}
foreach ($response as $key => $value) {
$this->getResult()->addValue(null, $key, $value);
}
}
/**
* Get notifications for the current user.
*
* @return array
*/
public function getNotificationsForUser(): array {
$return = [
'notifications' => []
];
$filters = [];
if ($this->params['read'] === 1) {
$filters['read'] = 1;
}
if ($this->params['unread'] === 1) {
$filters['unread'] = 1;
}
if (!empty($this->params['type'])) {
$types = explode(',', $this->params['type']);
foreach ($types as $key => $type) {
if (!NotificationBroadcast::isTypeConfigured($type)) {
unset($types[$key]);
}
}
if (!empty($types)) {
$filters['type'] = implode(',', $types);
}
}
$bundle = NotificationBundle::getBundleForUser(
$this->getUser(),
$filters,
$this->params['itemsPerPage'],
$this->params['page']
);
if ($bundle !== null) {
foreach ($bundle as $key => $notification) {
$return['notifications'][] = $notification->toArray();
}
$return['meta'] = [
'unread' => $bundle->getUnreadCount(),
'read' => $bundle->getReadCount(),
'total_this_page' => $bundle->getTotalThisPage(),
'total_all' => $bundle->getTotalAll(),
'page' => $bundle->getPageNumber(),
'items_per_page' => $bundle->getItemsPerPage()
];
}
return $return;
}
/**
* Dismiss a notification based on ID.
*
* @return array
*/
public function dismissNotification(): array {
if (!$this->getRequest()->wasPosted()) {
$this->dieWithError(['apierror-mustbeposted', __FUNCTION__]);
}
$success = false;
$id = $this->params['notificationId'];
$timestamp = $this->params['dismissedAt'];
if ($timestamp === null) {
$timestamp = time();
}
if (!empty($id)) {
$success = Notification::dismissNotification($this->getUser(), (string)$id, $timestamp);
}
return [
'success' => $success
];
}
/**
* Dismiss a notification based on ID.
*
* @return array
*/
public function dismissAllNotifications(): array {
if (!$this->getRequest()->wasPosted()) {
$this->dieWithError(['apierror-mustbeposted', __FUNCTION__]);
}
$success = false;
$serviceUserId = UserIdHelper::getUserIdForService($this->getUser());
$userIdentifier = Identifier::newUser($serviceUserId);
$dismiss = new NotificationDismissalsResource(
[
'target-id' => (string)$userIdentifier
]
);
try {
$client = MediaWikiServices::getInstance()->getService('ReverbApiClient');
$response = $client->notification_dismissals()->create($dismiss);
$success = true;
} catch (ApiRequestUnsuccessful $e) {
wfLogWarning('Invalid API response from the service: ' . $e->getMessage());
} catch (Exception $e) {
wfLogWarning('General exception encountered when communicating with the service: ' . $e->getMessage());
}
return [
'success' => $success
];
}
/**
* Array of allowed parameters on the API request.
*
* @return array
*/
public function getAllowedParams() {
return [
'do' => [
ApiBase::PARAM_TYPE => 'string',
ApiBase::PARAM_REQUIRED => true
],
'page' => [
ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_DFLT => 0
],
'itemsPerPage' => [
ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_DFLT => 50
],
'type' => [
ApiBase::PARAM_TYPE => 'string',
ApiBase::PARAM_REQUIRED => false,
ApiBase::PARAM_DFLT => null
],
'read' => [
ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_REQUIRED => false,
ApiBase::PARAM_DFLT => null
],
'unread' => [
ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_REQUIRED => false,
ApiBase::PARAM_DFLT => null
],
'notificationId' => [
ApiBase::PARAM_TYPE => 'string',
ApiBase::PARAM_REQUIRED => false,
ApiBase::PARAM_DFLT => null
],
'dismissedAt' => [
ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_REQUIRED => false,
ApiBase::PARAM_DFLT => null
]
];
}
/**
* Get example URL parameters and help message key.
*
* @return string
*/
protected function getExamplesMessages() {
return [
'action=notifications&do=getNotificationsForUser&page=0&itemsPerPage=50'
=> 'apihelp-notifications-getNotificationsForUser-example',
'action=notifications&do=dismissNotification&notificationId=1&dismissedAt=1562006555'
=> 'apihelp-notifications-dismissNotification-example',
'action=notifications&do=dismissAllNotifications'
=> 'apihelp-notifications-dismissAllNotifications-example'
];
}
/**
* Destination URL of help information for this API.
*
* @return string
*/
public function getHelpUrls() {
return '';
}
}
This diff is collapsed.
<?php
/**
* Reverb
* Identifier
*
* @package Reverb
* @author Alexia E. Smith
* @license GPL-2.0-or-later
*/
declare(strict_types=1);
namespace Reverb\Identifier;
use DynamicSettings\Environment;
use MediaWiki\MediaWikiServices;
abstract class Identifier {
/**
* Namespace
*
* @var string
*/
protected $namespace = '';
/**
* What am I?(Type such as site, user.)
*
* @var string
*/
protected $what = '';
/**
* Unique ID
*
* @var string
*/
protected $who = '';
/**
* What/Type to class mapping.
*
* @var array
*/
private static $whatClassMap = [
'site' => 'Reverb\Identifier\SiteIdentifier',
'user' => 'Reverb\Identifier\UserIdentifier'
];
/**
* Get a new instance based on the identifier given.
*
* @param string|array $identifier String or array based identifier with namespace, what, and who.
*
* @return Identifier One of the Identifier children.
*
* @throws InvalidIdentifierException
*/
public static function factory($identifier): Identifier {
if (!is_array($identifier)) {
$idPieces = self::splitIdentifier($identifier);
} else {
$idPieces = $identifier;
}
if ($idPieces === null || !isset(self::$whatClassMap[$idPieces['what']])) {
throw new InvalidIdentifierException();
}
return new self::$whatClassMap[$idPieces['what']]((string)$idPieces['namespace'], (string)$idPieces['who']);
}
/**
* Return a factory response for an user identifier.
*
* @param mixed $who Unique identifier of the item.
*
* @return UserIdentifier
*/
public static function newUser($who): UserIdentifier {
$who = strval($who);
return self::factory(['namespace' => self::getConfiguredNamespace(), 'what' => 'user', 'who' => $who]);
}
/**
* Return a factory response for a site identifier.
*
* @param mixed $who Unique identifier of the item.
*
* @return SiteIdentifier
*/
public static function newSite($who): SiteIdentifier {
$who = strval($who);
return self::factory(['namespace' => self::getConfiguredNamespace(), 'what' => 'site', 'who' => $who]);
}
/**
* Return a factory response for a local site identifier.
*
* @return SiteIdentifier
*/
public static function newLocalSite(): SiteIdentifier {
$siteKey = Environment::getSiteKey();
if (empty($siteKey)) {
throw new MWException('Site key could not be detected.');
}
return self::factory(['namespace' => self::getConfiguredNamespace(), 'what' => 'site', 'who' => $siteKey]);
}
/**
* Split an identifier with all three parts into an array.
*
* @param string $identifier Raw parameter with unknown validity.
*
* @return array|null Array with ['namespace' => 'hydra', 'what' => 'hydra', 'id' => 'hydra'] or null if invalid.
*/
private static function splitIdentifier(string $identifier): ?array {
$regex = '#^([a-z]{1,64}):([a-z]{1,64}):([\w]{1,64})$#';
$matches = [];
if (preg_match($regex, $identifier, $matches) > 0) {
return [
'namespace' => $matches[1],
'what' => $matches[2],
'who' => $matches[3]
];
}
return null;
}
/**
* Main Constructor
*
* @param string $namespace Namespace
* @param string $who Unique ID
*
* @return void
*/
private function __construct(string $namespace, string $who) {
$this->namespace = $namespace;
$this->who = $who;
}
/**
* Return a concatenated version of the identifier.
*
* @return string
*/
public function __toString(): string {
return $this->whereIsHome() . ":" . $this->whatAmI() . ':' . $this->whoAmI();
}
/**
* Get the namespace for this identifier.
*
* @return string
*/
public function whereIsHome(): string {
return $this->namespace;
}
/**
* Return what kind of identifier this is such as 'user' or 'site'.
*
* @return string What kind of identifier am I?
*/
public function whatAmI(): string {
return $this->what;
}
/**
* Get the unique ID for this identifier.
*
* @return string
*/
public function whoAmI(): string {
return $this->who;
}
/**
* Did this notification originate from this place?
*
* @return boolean
*/
public function isLocal(): bool {
return $this->namespace === self::getConfiguredNamespace();
}
/**
* Get the namespace from $wgReverbNamespace.
*
* @return string
*/
public static function getConfiguredNamespace(): string {
$mainConfig = MediaWikiServices::getInstance()->getMainConfig();
return $mainConfig->get('ReverbNamespace');
}
}
<?php
/**
* Reverb
* InvalidIdentifierException
*
* @package Reverb
* @author Alexia E. Smith
* @license GPL-2.0-or-later
*/
declare(strict_types=1);
namespace Reverb\Identifier;
use Exception;
class InvalidIdentifierException extends Exception {
}
<?php
/**
* Reverb
* SiteIdentifier
*
* @package Reverb
* @author Alexia E. Smith
* @license GPL-2.0-or-later
*/
declare(strict_types=1);
namespace Reverb\Identifier;
class SiteIdentifier extends Identifier {
/**
* What am I?(Type such as site, user.)
*
* @var string
*/
protected $what = 'site';
/**
* Did this notification originate from this place?
*
* @return boolean
*/
public function isLocal(): bool {
return $this->whereIsHome() === $this->getConfiguredNamespace() && $this->whoAmI() === wfWikiID();
}
}
<?php
/**
* Reverb
* UserIdentifier
*
* @package Reverb
* @author Alexia E. Smith
* @license GPL-2.0-or-later
*/
declare(strict_types=1);
namespace Reverb\Identifier;
class UserIdentifier extends Identifier {
/**
* What am I?(Type such as site, user.)
*
* @var string
*/
protected $what = 'user';
}
<?php
/**
* Reverb
* Notification
*
* @package Reverb
* @author Alexia E. Smith
* @license GPL-2.0-or-later
*/
declare(strict_types=1);
namespace Reverb\Notification;
use DynamicSettings\Wiki;
use Exception;
use Hydrawiki\Reverb\Client\V1\Exceptions\ApiRequestUnsuccessful as ApiRequestUnsuccessful;
use Hydrawiki\Reverb\Client\V1\Resources\Notification as NotificationResource;
use Hydrawiki\Reverb\Client\V1\Resources\NotificationTarget as NotificationTargetResource;
use MediaWiki\MediaWikiServices;
use Message;
use MWException;
use Reverb\Identifier\Identifier;
use Reverb\Identifier\InvalidIdentifierException;
use Reverb\Identifier\SiteIdentifier;
use Reverb\Identifier\UserIdentifier;
use Reverb\Traits\NotificationListTrait;
use Reverb\Traits\UserContextTrait;
use Reverb\UserIdHelper;
use Title;
use User;
class Notification {
use UserContextTrait;
use NotificationListTrait;
/**
* Data Resource
*
* @var Hydrawiki\Reverb\Client\V1\Resources\Notification
*/
private $resource = null;
/**
* Cached Origin SiteIdentifier
*
* @var SiteIdentifier|null
*/
private $originIdCache = null;
/**
* Cached Agent UserIdentifier
*
* @var SiteIdentifier|null
*/
private $agentIdCache = null;
/**
* Dismissed Timestamp
*
* @var integer
*/
private $dismissedAt = 0;
/**
* Cache of loaded wikis.
*
* @var array
*/
private static $wikiCache = [];
/**
* Main Constructor
*
* @param NotificationResource $resource Already known notification resource.
*
* @return void
*/
public function __construct(NotificationResource $resource) {
$this->resource = $resource;
}
/**
* Get the unique ID for this notification used by the service.
*
* @return integer ID