Лицензия для SkywikiMagic
Перейти к навигации
Перейти к поиску
SkywikiMagic/README.md0000644000000000000000000000014214723367061013434 0ustar rootroot# WikiOasisMagic
Forked from [miraheze/MirahezeMagic](https://github.com/miraheze/MirahezeMagic)
SkywikiMagic/extension.json0000644000000000000000000000451214727376305015076 0ustar rootroot{
"name": "SkywikiMagic",
"author": [
"Agent Isai",
"John Lewis",
"Labster",
"MacFan4000",
"Reception123",
"Revi",
"Paladox",
"Southparkfan",
"Universal Omega",
"Waki285"
],
"descriptionmsg": "skywikimagic-description",
"namemsg": "skywikimagic-extensionname",
"license-name": "GPL-3.0-or-later",
"type": "other",
"requires": {
"MediaWiki": ">= 1.42.0",
"platform": {
"php": ">= 8.0"
}
},
"MessagesDirs": {
"WikiOasisMagic": [
"i18n/wikioasis"
]
},
"AutoloadNamespaces": {
"WikiOasis\\WikiOasisMagic\\": "includes/"
},
"SpecialPages": {
"CreateNewWiki": {
"class": "WikiOasis\\WikiOasisMagic\\SpecialCreateNewWiki",
"services": [
"CreateWikiDatabaseUtils",
"WikiManagerFactory"
]
},
"ChangeDomain": {
"class": "WikiOasis\\WikiOasisMagic\\SpecialChangeDomain",
"services": [
"CreateWikiDatabaseUtils",
"RemoteWikiFactory"
]
}
},
"AvailableRights": [
"createnewwiki"
],
"Hooks": {
"AbuseFilterShouldFilterAction": {
"handler": "Main"
},
"ContributionsToolLinks": {
"handler": "Main"
},
"CreateWikiStatePrivate": {
"handler": "Main"
},
"CreateWikiTables": {
"handler": "Main"
},
"GetLocalURL::Internal": {
"handler": "Main"
},
"GlobalUserPageWikis": {
"handler": "Main"
},
"ImportDumpJobGetFile": {
"handler": "Main"
},
"MessageCacheFetchOverrides": {
"handler": "Main"
},
"MimeMagicInit": {
"handler": "Main"
},
"SiteNoticeAfter": {
"handler": "Main"
},
"SkinAddFooterLinks": {
"handler": "Main"
},
"TitleReadWhitelist": {
"handler": "Main"
}
},
"HookHandlers": {
"Main": {
"class": "WikiOasis\\WikiOasisMagic\\HookHandlers\\Main",
"factory": "WikiOasis\\WikiOasisMagic\\HookHandlers\\Main::factory",
"services": [
"MainConfig",
"CommentStore",
"DBLoadBalancerFactory",
"HttpRequestFactory"
]
}
},
"config": {
"WikiOasisMagicMemcachedServers": {
"description": "Array. Memcached servers to use for clearing memcached keys when a wiki is deleted or renamed.",
"value": []
}
},
"ConfigRegistry": {
"WikiOasisMagic": "MediaWiki\\Config\\GlobalVarConfig::newInstance"
},
"manifest_version": 2
}
SkywikiMagic/i18n/0000755000000000000000000000000014723367061012737 5ustar rootrootSkywikiMagic/i18n/wikioasis/0000755000000000000000000000000014727377257014755 5ustar rootrootSkywikiMagic/i18n/wikioasis/en.json0000644000000000000000000001401314727377257016251 0ustar rootroot{
"@metadata": {
"authors": [
"Agent Isai",
"John Lewis",
"AlvaroMolina",
"MacFan4000",
"Universal Omega",
"Waki285"
]
},
"skywikimagic-extensionname": "SkywikiMagic",
"skywikimagic-description": "SkyWiki dedicated extension",
"extensions-antispam": "Spam prevention",
"extensions-api": "API",
"extensions-editors": "Editors",
"extensions-mediahandlers": "Media handlers",
"extensions-parserhooks": "Parser hooks",
"extensions-skins": "Skins",
"extensions-specialpages": "Special pages",
"extensions-variable": "Variables",
"grant-usedatadumpapi": "Create, view, and delete dumps",
"group-autopatrolled-member": "{{GENDER:$1|autopatrolled}}",
"group-autopatrolled": "Autopatrolled users",
"group-confirmed-member": "{{GENDER:$1|confirmed user}}",
"group-confirmed": "Confirmed users",
"group-electionadmin": "Election administrators",
"group-electionadmin-member": "{{GENDER:$1|election administrator}}",
"group-flood-member": "{{GENDER:$1|flooder}}",
"group-flood": "Flooders",
"group-founder": "Founders",
"group-founder-member": "{{GENDER:$1|founder}}",
"group-global-admin-member": "{{GENDER:$1|global administrator}}",
"group-global-admin": "Global Administrators",
"group-global-flood-member": "{{GENDER:$1|global flooder}}",
"group-global-flood": "Global flooders",
"group-global-ipblock-exempt-member": "{{GENDER:$1|global IP block exempt}}",
"group-global-ipblock-exempt": "Global IP block exemption",
"group-global-patroller-member": "{{GENDER:$1|global patroller}}",
"group-global-patroller": "Global patrollers",
"group-global-renamer-member": "{{GENDER:$1|global renamer}}",
"group-global-renamer": "Global renamers",
"group-global-rollbacker-member": "{{GENDER:$1|global rollbacker}}",
"group-global-rollbacker": "Global rollbackers",
"group-ipblock-exempt-member": "{{GENDER:$1|IP block exempt}}",
"group-ipblock-exempt": "IP block exemption",
"group-member": "Members",
"group-member-member": "{{GENDER:$1|member}}",
"group-patroller-member": "{{GENDER:$1|patroller}}",
"group-patroller": "Patrollers",
"group-rollbacker-member": "{{GENDER:$1|rollbacker}}",
"group-rollbacker": "Rollbackers",
"group-steward-member": "{{GENDER:$1|steward}}",
"group-steward": "Stewards",
"group-sysadmin-member": "{{GENDER:$1|system administrator}}",
"group-sysadmin": "System administrators",
"group-translator-member": "{{GENDER:$1|translator}}",
"group-translator": "Translators",
"group-trustandsafety-member": "{{GENDER:$1|Trust and Safety member}}",
"group-trustandsafety": "Trust and Safety",
"group-wiki-creator-member": "{{GENDER:$1|wiki creator}}",
"group-wiki-creator": "Wiki creators",
"grouppage-autopatrolled": "wom:Special:MyLanguage/User groups#{{int:Group-autopatrolled}}",
"grouppage-confirmed": "wom:Special:MyLanguage/User groups#{{int:Group-autoconfirmed}}",
"grouppage-electionadmin": "wom:Special:MyLanguage/Meta:Election administrators",
"grouppage-flood": "wom:Special:MyLanguage/User groups#{{int:Group-flood}}",
"grouppage-founder": "wom:Special:MyLanguage/User groups#{{int:Group-founder}}",
"grouppage-global-admin": "wom:Special:MyLanguage/Global Administrators",
"grouppage-global-flood": "wom:Special:MyLanguage/Global flooders",
"grouppage-global-ipblock-exempt": "wom:Special:MyLanguage/Global IP block exemption",
"grouppage-global-patroller": "wom:Special:MyLanguage/Global Patrollers",
"grouppage-global-renamer": "wom:Special:MyLanguage/Global renamers",
"grouppage-global-rollbacker": "wom:Special:MyLanguage/Global rollbackers",
"grouppage-ipblock-exempt": "wom:Special:MyLanguage/User groups#{{int:Group-ipblock-exempt}}",
"grouppage-member": "wom:Special:MyLanguage/User groups#{{int:Group-member}}",
"grouppage-patroller": "wom:Special:MyLanguage/User groups#{{int:Group-patroller}}",
"grouppage-rollbacker": "wom:Special:MyLanguage/User groups#{{int:Group-rollbacker}}",
"grouppage-steward": "wom:Special:MyLanguage/Stewards",
"grouppage-sysadmin": "wom:Special:MyLanguage/System administrators",
"grouppage-trustandsafety": "wom:Special:MyLanguage/Trust and Safety",
"grouppage-wiki-creator": "wom:Special:MyLanguage/Meta:Wiki creators",
"settings-anti-spam": "Anti Spam",
"settings-beta": "Beta",
"settings-categories": "Categories",
"settings-discussion": "Discussion",
"settings-editing": "Editing",
"settings-links": "Links",
"settings-localisation": "Localisation",
"settings-maps": "Maps",
"settings-media": "Media",
"settings-notifications": "Notifications",
"settings-parserfunctions": "Parser Functions",
"settings-permissions": "Permissions",
"settings-preferences": "Preferences",
"settings-recentchanges": "Recent changes",
"settings-restricted": "Restricted",
"settings-seo": "SEO",
"settings-socialtools": "Social tools",
"settings-styling": "Styling",
"settings-wikibase": "Wikibase",
"specialpages-group-wikimanage": "Wiki management",
"miraheze-label-managewiki-article-path": "Article path",
"miraheze-label-managewiki-article-path-root": "Don't use /wiki/ for articles (use the root path)",
"miraheze-label-managewiki-article-path-wiki": "Use /wiki/ for articles",
"miraheze-label-managewiki-mainpage-is-domain-root": "Make the main page of this wiki use the domain root?",
"miraheze-label-managewiki-mediawiki-version": "MediaWiki version",
"miraheze-label-managewiki-primary-domain": "Primary domain",
"createnewwiki": "Start your own community",
"createnewwiki-description": "Every wiki, whether big or small, needs an address and a name. Please note that the subdomain can only contain alphanumeric characters.",
"action-createnewwiki": "create a new wiki through CreateNewWiki",
"right-createnewwiki": "Create a new wiki through CreateNewWiki",
"createnewwiki-label-subdomain": "Subdomain:",
"createnewwiki-placeholder-subdomain": "Give your community a subdomain",
"createnewwiki-placeholder-sitename": "Name your wiki",
"changedomain": "Change domain",
"changedomain-info": "Insert the database name of the wiki you wish to change the domain for.",
"changedomain-label-domain": "Domain"
}
SkywikiMagic/includes/0000755000000000000000000000000014727411650013764 5ustar rootrootSkywikiMagic/includes/SpecialCreateNewWiki.php0000644000000000000000000001105314727376352020510 0ustar rootroot<?php
namespace WikiOasis\WikiOasisMagic;
use ErrorPageError;
use MediaWiki\Html\Html;
use MediaWiki\Message\Message;
use MediaWiki\SpecialPage\FormSpecialPage;
use Miraheze\CreateWiki\ConfigNames;
use Miraheze\CreateWiki\Services\CreateWikiDatabaseUtils;
use Miraheze\CreateWiki\Services\WikiManagerFactory;
use OOUI;
class SpecialCreateNewWiki extends FormSpecialPage {
private CreateWikiDatabaseUtils $databaseUtils;
private WikiManagerFactory $wikiManagerFactory;
public function __construct(
CreateWikiDatabaseUtils $databaseUtils,
WikiManagerFactory $wikiManagerFactory
) {
parent::__construct( 'CreateNewWiki', 'createnewwiki' );
$this->databaseUtils = $databaseUtils;
$this->wikiManagerFactory = $wikiManagerFactory;
}
/**
* @param ?string $par
*/
public function execute( $par ): void {
if ( !$this->databaseUtils->isCurrentWikiCentral() ) {
throw new ErrorPageError( 'errorpagetitle', 'createwiki-wikinotcentralwiki' );
}
if ( !$this->getUser()->isEmailConfirmed() ) {
throw new ErrorPageError( 'requestwiki', 'requestwiki-error-emailnotconfirmed' );
}
parent::execute( $par );
}
/**
* @inheritDoc
*/
protected function getFormFields(): array {
$formDescriptor = [
'dbname' => [
#'label-message' => 'createnewwiki-label-subdomain',
'label' => "." . $this->getConfig()->get( 'CreateWikiSubdomain' ),
'cssclass' => 'subdomain',
'placeholder-message' => 'createnewwiki-placeholder-subdomain',
'type' => 'text',
'required' => true,
'validation-callback' => [ $this, 'isValidDatabase' ],
],
'sitename' => [
'label-message' => 'createwiki-label-sitename',
'placeholder-message' => 'createnewwiki-placeholder-sitename',
'type' => 'text',
'size' => 20,
],
'language' => [
'type' => 'language',
'label-message' => 'createwiki-label-language',
'default' => 'en',
],
];
if ( $this->getConfig()->get( ConfigNames::UsePrivateWikis ) ) {
$formDescriptor['private'] = [
'type' => 'check',
'label-message' => 'createwiki-label-private',
];
}
if ( $this->getConfig()->get( ConfigNames::Categories ) ) {
$formDescriptor['category'] = [
'type' => 'select',
'label-message' => 'createwiki-label-category',
'options' => $this->getConfig()->get( ConfigNames::Categories ),
'default' => 'uncategorised',
];
}
$formDescriptor['reason'] = [
'type' => 'textarea',
'rows' => 10,
'label-message' => 'createwiki-label-reason',
'help-message' => 'createwiki-help-reason',
'required' => true,
'useeditfont' => true,
];
return $formDescriptor;
}
/**
* @inheritDoc
*/
public function onSubmit( array $formData ): bool {
if ( $this->getConfig()->get( ConfigNames::UsePrivateWikis ) ) {
$private = $formData['private'];
} else {
$private = 0;
}
if ( $this->getConfig()->get( ConfigNames::Categories ) ) {
$category = $formData['category'];
} else {
$category = 'uncategorised';
}
$wikiManager = $this->wikiManagerFactory->newInstance( $formData['dbname'] . 'wiki' );
$wikiManager->create(
sitename: $formData['sitename'],
language: $formData['language'],
private: $private,
category: $category,
requester: $this->getContext()->getUser()->getName(),
actor: $this->getContext()->getUser()->getName(),
reason: $formData['reason'],
extra: []
);
$this->getOutput()->redirect( "http://" . $formData['dbname'] . "." . $this->getConfig()->get( 'CreateWikiSubdomain' ) );
return true;
}
public function isValidDatabase( ?string $dbname ): bool|string|Message {
if ( !$dbname || ctype_space( $dbname ) ) {
return $this->msg( 'htmlform-required' );
}
$wikiManager = $this->wikiManagerFactory->newInstance( $dbname . 'wiki' );
$check = $wikiManager->checkDatabaseName( $dbname . 'wiki', forRename: false );
if ( $check ) {
// Will return a string — the error it received
return $check;
}
return true;
}
/**
* @inheritDoc
*/
protected function getDisplayFormat(): string {
return 'ooui';
}
/**
* @inheritDoc
*/
protected function getGroupName(): string {
return 'wikimanage';
}
/**
* @inheritDoc
*/
protected function preHtml(): string {
return $this->msg( 'createnewwiki-description' ) . "
<style>
.subdomain .oo-ui-fieldLayout-body {
display: flex;
flex-direction: row-reverse;
justify-content: flex-end;
}
.subdomain .oo-ui-fieldLayout-field {
flex: 1;
max-width: 50em;
margin-right: 1rem;
}
.oo-ui-fieldLayout-body .oo-ui-iconElement-icon {
margin-right: .25rem;
}
</style>
";
}
}
SkywikiMagic/includes/HookHandlers/0000755000000000000000000000000014727360362016350 5ustar rootrootSkywikiMagic/includes/HookHandlers/Main.php0000644000000000000000000004016214727234344017750 0ustar rootroot<?php
namespace WikiOasis\WikiOasisMagic\HookHandlers;
use MediaWiki\Cache\Hook\MessageCacheFetchOverridesHook;
use MediaWiki\CommentStore\CommentStore;
use MediaWiki\Config\Config;
use MediaWiki\Config\GlobalVarConfig;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Context\RequestContext;
use MediaWiki\Extension\AbuseFilter\AbuseFilterServices;
use MediaWiki\Extension\AbuseFilter\Hooks\AbuseFilterShouldFilterActionHook;
use MediaWiki\Extension\AbuseFilter\Variables\VariableHolder;
use MediaWiki\Extension\CentralAuth\User\CentralAuthUser;
use MediaWiki\Hook\ContributionsToolLinksHook;
use MediaWiki\Hook\GetLocalURL__InternalHook;
use MediaWiki\Hook\MimeMagicInitHook;
use MediaWiki\Hook\SiteNoticeAfterHook;
use MediaWiki\Hook\SkinAddFooterLinksHook;
use MediaWiki\Html\Html;
use MediaWiki\Http\HttpRequestFactory;
use MediaWiki\Linker\Linker;
use MediaWiki\MainConfigNames;
use MediaWiki\MediaWikiServices;
use MediaWiki\Permissions\Hook\TitleReadWhitelistHook;
use MediaWiki\Shell\Shell;
use MediaWiki\SpecialPage\SpecialPage;
use MediaWiki\Title\Title;
use MediaWiki\User\User;
use MediaWiki\WikiMap\WikiMap;
use Memcached;
use MessageCache;
use Miraheze\CreateWiki\Hooks\CreateWikiStatePrivateHook;
use Miraheze\CreateWiki\Hooks\CreateWikiTablesHook;
use Miraheze\ManageWiki\Helpers\ManageWikiExtensions;
use Miraheze\ManageWiki\Helpers\ManageWikiSettings;
use Miraheze\ImportDump\Hooks\ImportDumpJobGetFileHook;
use Redis;
use Skin;
use Throwable;
use Wikimedia\IPUtils;
use Wikimedia\Rdbms\DBConnRef;
use Wikimedia\Rdbms\ILBFactory;
class Main implements
AbuseFilterShouldFilterActionHook,
ContributionsToolLinksHook,
CreateWikiStatePrivateHook,
CreateWikiTablesHook,
GetLocalURL__InternalHook,
ImportDumpJobGetFileHook,
MessageCacheFetchOverridesHook,
MimeMagicInitHook,
SiteNoticeAfterHook,
SkinAddFooterLinksHook,
TitleReadWhitelistHook
{
/** @var ServiceOptions */
private $options;
/** @var CommentStore */
private $commentStore;
/** @var ILBFactory */
private $dbLoadBalancerFactory;
/** @var HttpRequestFactory */
private $httpRequestFactory;
/**
* @param ServiceOptions $options
* @param CommentStore $commentStore
* @param ILBFactory $dbLoadBalancerFactory
* @param HttpRequestFactory $httpRequestFactory
*/
public function __construct(
ServiceOptions $options,
CommentStore $commentStore,
ILBFactory $dbLoadBalancerFactory,
HttpRequestFactory $httpRequestFactory
) {
$this->options = $options;
$this->commentStore = $commentStore;
$this->dbLoadBalancerFactory = $dbLoadBalancerFactory;
$this->httpRequestFactory = $httpRequestFactory;
}
/**
* @param Config $mainConfig
* @param CommentStore $commentStore
* @param ILBFactory $dbLoadBalancerFactory
* @param HttpRequestFactory $httpRequestFactory
*
* @return self
*/
public static function factory(
Config $mainConfig,
CommentStore $commentStore,
ILBFactory $dbLoadBalancerFactory,
HttpRequestFactory $httpRequestFactory
): self {
return new self(
new ServiceOptions(
[
'ArticlePath',
'CreateWikiCacheDirectory',
'CreateWikiGlobalWiki',
'EchoSharedTrackingDB',
'JobTypeConf',
'LanguageCode',
'LocalDatabases',
'ManageWikiSettings',
'WikiOasisMagicMemcachedServers',
'Script',
],
$mainConfig
),
$commentStore,
$dbLoadBalancerFactory,
$httpRequestFactory
);
}
/**
* Avoid filtering automatic account creation
*
* @param VariableHolder $vars
* @param Title $title
* @param User $user
* @param array &$skipReasons
* @return bool|void
*/
public function onAbuseFilterShouldFilterAction(
VariableHolder $vars,
Title $title,
User $user,
array &$skipReasons
) {
if ( defined( 'MW_PHPUNIT_TEST' ) ) {
return;
}
$varManager = AbuseFilterServices::getVariablesManager();
$action = $varManager->getVar( $vars, 'action', 1 )->toString();
if ( $action === 'autocreateaccount' ) {
$skipReasons[] = 'Blocking automatic account creation is not allowed';
return false;
}
}
public function onCreateWikiStatePrivate( string $dbname ): void {
/*$localRepo = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo();
$sitemaps = $localRepo->getBackend()->getTopFileList( [
'dir' => $localRepo->getZonePath( 'public' ) . '/sitemaps',
'adviseStat' => false,
] );
foreach ( $sitemaps as $sitemap ) {
$status = $localRepo->getBackend()->quickDelete( [
'src' => $localRepo->getZonePath( 'public' ) . '/sitemaps/' . $sitemap,
] );
if ( !$status->isOK() ) {
$statusFormatter = MediaWikiServices::getInstance()->getFormatterFactory()
->getStatusFormatter( RequestContext::getMain() );
$statusMessage = $statusFormatter->getWikiText( $status );
wfDebugLog( 'WikiOasisMagic', "Sitemap \"{$sitemap}\" failed to delete: {$statusMessage}" );
}
}
$localRepo->getBackend()->clean( [ 'dir' => $localRepo->getZonePath( 'public' ) . '/sitemaps' ] );*/
}
public function onCreateWikiTables( array &$cTables ): void {
$cTables['localnames'] = 'ln_wiki';
$cTables['localuser'] = 'lu_wiki';
}
public function onImportDumpJobGetFile( &$filePath, $importDumpRequestManager ): void {
wfDebugLog( 'WikiOasisMagic', "Importing dump from {$filePath}" );
$originalFilePath = $importDumpRequestManager->getSplitFilePath();
if ( $originalFilePath === null ) {
return;
}
wfDebugLog( 'WikiOasisMagic', "Importing dump from {$originalFilePath} to {$filePath}" );
// copy $originalFilePath to $filePath file
if (!copy('/var/www/mediawiki/images/metawiki/'.$originalFilePath, $filePath)) {
throw new RuntimeException("Failed to copy $originalFilePath to $filePath");
}
wfDebugLog( 'WikiOasisMagic', "Importing dump from {$originalFilePath} to {$filePath} done" );
}
/**
* From WikimediaMessages
* When core requests certain messages, change the key to a Miraheze version.
*
* @see https://www.mediawiki.org/wiki/Manual:Hooks/MessageCacheFetchOverrides
* @param string[] &$keys
*/
public function onMessageCacheFetchOverrides( array &$keys ): void {
static $keysToOverride = [
/*'centralauth-groupname',
'centralauth-login-error-locked',
'createwiki-close-email-body',
'createwiki-close-email-sender',
'createwiki-close-email-subject',
'createwiki-defaultmainpage',
'createwiki-defaultmainpage-summary',
'createwiki-email-body',
'createwiki-email-subject',
'createwiki-error-subdomaintaken',
'createwiki-help-bio',
'createwiki-help-category',
'createwiki-help-reason',
'createwiki-help-subdomain',
'createwiki-label-reason',
'dberr-again',
'dberr-problems',
'globalblocking-ipblocked-range',
'globalblocking-ipblocked-xff',
'globalblocking-ipblocked',*/
'grouppage-autoconfirmed',
'grouppage-automoderated',
'grouppage-autoreview',
'grouppage-blockedfromchat',
'grouppage-bot',
'grouppage-bureaucrat',
'grouppage-chatmod',
'grouppage-checkuser',
'grouppage-commentadmin',
'grouppage-csmoderator',
'grouppage-editor',
'grouppage-flow-bot',
'grouppage-interface-admin',
'grouppage-moderator',
'grouppage-no-ipinfo',
'grouppage-reviewer',
'grouppage-suppress',
'grouppage-sysop',
'grouppage-upwizcampeditors',
'grouppage-user',
/*'importdump-help-reason',
'importdump-help-target',
'importdump-help-upload-file',
'importdump-import-failed-comment',
'importtext',
'interwiki_intro',
'newsignuppage-loginform-tos',
'newsignuppage-must-accept-tos',
'oathauth-step1',
'prefs-help-realname',
'privacypage',
'requestwiki-error-invalidcomment',
'requestwiki-info-guidance',
'requestwiki-info-guidance-post',
'requestwiki-label-agreement',
'requestwiki-success',
'restriction-delete',
'restriction-protect',
'skinname-snapwikiskin',
'snapwikiskin',
'uploadtext',
'webauthn-module-description',
'wikibase-sitelinks-miraheze',*/
];
$languageCode = $this->options->get( MainConfigNames::LanguageCode );
$transformationCallback = static function ( string $key, MessageCache $cache ) use ( $languageCode ): string {
$transformedKey = "wikioasis-$key";
// MessageCache uses ucfirst if ord( key ) is < 128, which is true of all
// of the above. Revisit if non-ASCII keys are used.
$ucKey = ucfirst( $key );
if (
/*
* Override order:
* 1. If the MediaWiki:$ucKey page exists, use the key unprefixed
* (in all languages) with normal fallback order. Specific
* language pages (MediaWiki:$ucKey/xy) are not checked when
* deciding which key to use, but are still used if applicable
* after the key is decided.
*
* 2. Otherwise, use the prefixed key with normal fallback order
* (including MediaWiki pages if they exist).
*/
$cache->getMsgFromNamespace( $ucKey, $languageCode ) === false
) {
return $transformedKey;
}
return $key;
};
foreach ( $keysToOverride as $key ) {
$keys[$key] = $transformationCallback;
}
}
public function onTitleReadWhitelist( $title, $user, &$whitelisted ) {
if ( $title->equals( Title::newMainPage() ) ) {
$whitelisted = true;
return;
}
$specialsArray = [
'CentralAutoLogin',
'CentralLogin',
'ConfirmEmail',
'CreateAccount',
'Notifications',
'OAuth',
'ResetPassword'
];
if ( $user->isAllowed( 'interwiki' ) ) {
$specialsArray[] = 'Interwiki';
}
if ( $title->isSpecialPage() ) {
$rootName = strtok( $title->getText(), '/' );
$rootTitle = Title::makeTitle( $title->getNamespace(), $rootName );
foreach ( $specialsArray as $page ) {
if ( $rootTitle->equals( SpecialPage::getTitleFor( $page ) ) ) {
$whitelisted = true;
return;
}
}
}
}
public function onGlobalUserPageWikis( array &$list ): bool {
$cwCacheDir = $this->options->get( 'CreateWikiCacheDirectory' );
if ( file_exists( "{$cwCacheDir}/databases.php" ) ) {
$databasesArray = include "{$cwCacheDir}/databases.php";
$dbList = array_keys( $databasesArray['databases'] ?? [] );
// Filter out those databases that don't have GlobalUserPage enabled
$list = array_filter( $dbList, static function ( $dbname ) {
$extensions = new ManageWikiExtensions( $dbname );
return in_array( 'globaluserpage', $extensions->list() );
} );
return false;
}
return true;
}
public function onMimeMagicInit( $mimeMagic ) {
$mimeMagic->addExtraTypes( 'text/plain txt off' );
}
public function onSkinAddFooterLinks( Skin $skin, string $key, array &$footerItems ) {
/*if ( $key === 'places' ) {
$footerItems['termsofservice'] = $this->addFooterLink( $skin, 'termsofservice', 'termsofservicepage' );
$footerItems['donate'] = $this->addFooterLink( $skin, 'miraheze-donate', 'miraheze-donatepage' );
}*/
}
public function onSiteNoticeAfter( &$siteNotice, $skin ) {
/*$cwConfig = new GlobalVarConfig( 'cw' );
if ( $cwConfig->get( 'Closed' ) ) {
if ( $cwConfig->get( 'Private' ) ) {
$siteNotice .= '<div class="wikitable" style="text-align: center; width: 90%; margin-left: auto; margin-right:auto; padding: 15px; border: 4px solid black; background-color: #EEE;"> <span class="plainlinks"> <img src="https://static.miraheze.org/metawiki/0/02/Wiki_lock.png" align="left" style="width:80px;height:90px;">' . $skin->msg( 'miraheze-sitenotice-closed-private' )->parse() . '</span></div>';
} elseif ( $cwConfig->get( 'Locked' ) ) {
$siteNotice .= '<div class="wikitable" style="text-align: center; width: 90%; margin-left: auto; margin-right:auto; padding: 15px; border: 4px solid black; background-color: #EEE;"> <span class="plainlinks"> <img src="https://static.miraheze.org/metawiki/5/5f/Out_of_date_clock_icon.png" align="left" style="width:80px;height:90px;">' . $skin->msg( 'miraheze-sitenotice-closed-locked' )->parse() . '</span></div>';
} else {
$siteNotice .= '<div class="wikitable" style="text-align: center; width: 90%; margin-left: auto; margin-right:auto; padding: 15px; border: 4px solid black; background-color: #EEE;"> <span class="plainlinks"> <img src="https://static.miraheze.org/metawiki/0/02/Wiki_lock.png" align="left" style="width:80px;height:90px;">' . $skin->msg( 'miraheze-sitenotice-closed' )->parse() . '</span></div>';
}
} elseif ( $cwConfig->get( 'Inactive' ) && $cwConfig->get( 'Inactive' ) !== 'exempt' ) {
if ( $cwConfig->get( 'Private' ) ) {
$siteNotice .= '<div class="wikitable" style="text-align: center; width: 90%; margin-left: auto; margin-right:auto; padding: 15px; border: 4px solid black; background-color: #EEE;"> <span class="plainlinks"> <img src="https://static.miraheze.org/metawiki/5/5f/Out_of_date_clock_icon.png" align="left" style="width:80px;height:90px;">' . $skin->msg( 'miraheze-sitenotice-inactive-private' )->parse() . '</span></div>';
} else {
$siteNotice .= '<div class="wikitable" style="text-align: center; width: 90%; margin-left: auto; margin-right:auto; padding: 15px; border: 4px solid black; background-color: #EEE;"> <span class="plainlinks"> <img src="https://static.miraheze.org/metawiki/5/5f/Out_of_date_clock_icon.png" align="left" style="width:80px;height:90px;">' . $skin->msg( 'miraheze-sitenotice-inactive' )->parse() . '</span></div>';
}
}*/
}
public function onContributionsToolLinks( $id, Title $title, array &$tools, SpecialPage $specialPage ) {
$username = $title->getText();
if ( !IPUtils::isIPAddress( $username ) ) {
$globalUserGroups = CentralAuthUser::getInstanceByName( $username )->getGlobalGroups();
if (
!in_array( 'steward', $globalUserGroups ) &&
!in_array( 'global-sysop', $globalUserGroups ) &&
!$specialPage->getUser()->isAllowed( 'centralauth-lock' )
) {
return;
}
$tools['centralauth'] = Linker::makeExternalLink(
'https://meta.wikioasis.org/wiki/Special:CentralAuth/' . $username,
strtolower( $specialPage->msg( 'centralauth' )->text() )
);
}
}
/**
* phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName
*
* @param Title $title
* @param string &$url
* @param string $query
*/
public function onGetLocalURL__Internal( $title, &$url, $query ) {
// phpcs:enable
if ( defined( 'MW_PHPUNIT_TEST' ) ) {
return;
}
// If the URL contains wgScript, rewrite it to use wgArticlePath
if ( str_contains( $url, $this->options->get( MainConfigNames::Script ) ) ) {
$dbkey = wfUrlencode( $title->getPrefixedDBkey() );
$url = str_replace( '$1', $dbkey, $this->options->get( MainConfigNames::ArticlePath ) );
if ( $query !== '' ) {
$url = wfAppendQuery( $url, $query );
}
}
}
private function addFooterLink( $skin, $desc, $page ) {
if ( $skin->msg( $desc )->inContentLanguage()->isDisabled() ) {
$title = null;
} else {
$title = Title::newFromText( $skin->msg( $page )->inContentLanguage()->text() );
}
if ( !$title ) {
return '';
}
return Html::element( 'a',
[ 'href' => $title->fixSpecialName()->getLinkURL() ],
$skin->msg( $desc )->text()
);
}
/** Removes redis keys for jobrunner */
private function removeRedisKey( string $key ) {
$jobTypeConf = $this->options->get( MainConfigNames::JobTypeConf );
if ( !isset( $jobTypeConf['default']['redisServer'] ) || !$jobTypeConf['default']['redisServer'] ) {
return;
}
$hostAndPort = IPUtils::splitHostAndPort( $jobTypeConf['default']['redisServer'] );
if ( $hostAndPort ) {
try {
$redis = new Redis();
$redis->connect( $hostAndPort[0], $hostAndPort[1] );
$redis->auth( $jobTypeConf['default']['redisConfig']['password'] );
$redis->del( $redis->keys( $key ) );
} catch ( Throwable $ex ) {
// empty
}
}
}
/** Remove memcached keys */
private function removeMemcachedKey( string $key ) {
$memcachedServers = $this->options->get( 'WikiOasisMemcachedServers' );
try {
foreach ( $memcachedServers as $memcachedServer ) {
$memcached = new Memcached();
$memcached->addServer( $memcachedServer[0], (string)$memcachedServer[1] );
// Fetch all keys
$keys = $memcached->getAllKeys();
if ( !is_array( $keys ) ) {
return;
}
foreach ( $keys as $item ) {
// Decide which keys to delete
if ( preg_match( "/{$key}/", $item ) ) {
$memcached->delete( $item );
} else {
continue;
}
}
}
} catch ( Throwable $ex ) {
// empty
}
}
}
SkywikiMagic/includes/SpecialChangeDomain.php0000644000000000000000000001212114727411650020310 0ustar rootroot<?php
namespace WikiOasis\WikiOasisMagic;
use ErrorPageError;
use MediaWiki\Html\Html;
use MediaWiki\Message\Message;
use MediaWiki\HTMLForm\HTMLForm;
use MediaWiki\SpecialPage\SpecialPage;
use Miraheze\CreateWiki\ConfigNames;
use Miraheze\CreateWiki\Services\CreateWikiDatabaseUtils;
use Miraheze\CreateWiki\Services\RemoteWikiFactory;
use ManualLogEntry;
class SpecialChangeDomain extends SpecialPage {
private CreateWikiDatabaseUtils $databaseUtils;
private RemoteWikiFactory $remoteWikiFactory;
public function __construct(
CreateWikiDatabaseUtils $databaseUtils,
RemoteWikiFactory $remoteWikiFactory
) {
parent::__construct( 'ChangeDomain', 'managewiki-restricted' );
$this->databaseUtils = $databaseUtils;
$this->remoteWikiFactory = $remoteWikiFactory;
}
/**
* @param ?string $par
*/
public function execute( $par ): void {
if ( !$this->databaseUtils->isCurrentWikiCentral() ) {
throw new ErrorPageError( 'errorpagetitle', 'createwiki-wikinotcentralwiki' );
}
$par = explode( '/', $par ?? '', 3 );
$this->getOutput()->setPageTitle( 'Change domain' );
if ( $par[0] == '' ) {
$this->showInputBox();
} else {
$this->showWikiForm( $par[0] );
}
}
public function showInputBox() {
$formDescriptor = [
'info' => [
'default' => $this->msg( 'changedomain-info' )->text(),
'type' => 'info',
],
'dbname' => [
'label-message' => 'managewiki-label-dbname',
'type' => 'text',
'size' => 20,
'required' => true
]
];
if ( !$this->getContext()->getUser()->isAllowed( 'managewiki-restricted' ) ) {
$this->getOutput()->addHTML(
Html::errorBox( $this->msg( 'managewiki-error-nopermission' )->escaped() )
);
}
$htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext(), 'searchForm' );
$htmlForm->setWrapperLegendMsg( 'managewiki-core-header' );
$htmlForm->setMethod( 'post' )
->setSubmitCallback( [ $this, 'onSubmitRedirectToWikiForm' ] )
->prepareForm()
->show();
return true;
}
public function onSubmitRedirectToWikiForm( array $params ) {
if ( $params['dbname'] !== '' ) {
header( 'Location: ' . SpecialPage::getTitleFor( 'ChangeDomain' )->getFullURL() . '/' . $params['dbname'] );
} else {
return 'Invalid url.';
}
return true;
}
public function showWikiForm( $wiki ) {
$out = $this->getOutput();
$out->addModules( [ 'ext.managewiki.oouiform' ] );
$out->addModuleStyles( [
'ext.managewiki.oouiform.styles',
'mediawiki.widgets.TagMultiselectWidget.styles',
] );
$out->addModuleStyles( [ 'oojs-ui-widgets.styles' ] );
$out->addModules( [ 'mediawiki.special.userrights' ] );
$remoteWiki = $this->remoteWikiFactory->newInstance( $wiki );
if ( $remoteWiki->isLocked() ) {
$out->addHTML( Html::errorBox( $this->msg( 'managewiki-mwlocked' )->escaped() ) );
}
$options = [];
$formDescriptor = [
'wiki' => [
'type' => 'hidden',
'name' => 'wiki',
'default' => $wiki,
],
'subdomain' => [
'default' => $remoteWiki->getServerName(),
'label-message' => 'changedomain-label-domain',
'type' => 'text',
'size' => 20
]
];
$htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext(), 'changesubdomain' );
$htmlForm->setSubmitTextMsg( 'managewiki-save' );
$htmlForm->setSubmitCallback( [ $this, 'submitForm' ] );
if ( !$this->getContext()->getUser()->isAllowed( 'managewiki-restricted' ) ) {
$out->addHTML(
Html::errorBox( $this->msg( 'managewiki-error-nopermission' )->escaped() )
);
}
$htmlForm->show();
}
public function submitForm( array $params ) {
$out = $this->getOutput();
$remoteWiki = $this->remoteWikiFactory->newInstance( $params['wiki'] );
if ( $remoteWiki->isLocked() ) {
$out->addHTML( Html::errorBox( $this->msg( 'managewiki-mwlocked' )->escaped() ) );
return;
}
if ( !$this->getContext()->getUser()->isAllowed( 'managewiki-restricted' ) ) {
$out->addHTML(
Html::errorBox( $this->msg( 'managewiki-error-nopermission' )->escaped() )
);
return;
}
$remoteWiki->setServerName( $params['subdomain'] );
$remoteWiki->commit();
$logEntry = new ManualLogEntry( 'managewiki', 'settings' );
$logEntry->setPerformer( $this->getUser() );
$logEntry->setTarget( SpecialPage::getTitleValueFor( 'ChangeDomain', (string)$params['wiki'] ) );
$logEntry->setParameters( [ '4::wiki' => $params['wiki'], '5::changes' => 'servername' ] );
$logID = $logEntry->insert();
$logEntry->publish( $logID );
$out->addHTML(
Html::successBox(
Html::element(
'p',
[],
wfMessage( 'managewiki-success' )->plain()
),
'mw-notify-success'
)
);
return true;
}
/**
* @inheritDoc
*/
protected function getGroupName(): string {
return 'wikimanage';
}
}