Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F9582481
D1442.id3692.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
17 KB
Referenced Files
None
Subscribers
None
D1442.id3692.diff
View Options
Index: .env.example
===================================================================
--- /dev/null
+++ .env.example
@@ -0,0 +1,4 @@
+MEDIAWIKI_ENTRY_POINT="/srv/mediawiki/index.php"
+DB_HOST="localhost"
+DB_USER="root"
+DB_PASS=""
Index: .gitignore
===================================================================
--- /dev/null
+++ .gitignore
@@ -0,0 +1,6 @@
+# Composer
+/vendor/
+composer.lock
+
+# DotEnv
+.env
Index: LocalSettings.php
===================================================================
--- /dev/null
+++ LocalSettings.php
@@ -0,0 +1,22 @@
+<?php
+
+$service->run();
+$serviceConfiguration = $service->getConfiguration();
+
+$localDatabases = $serviceConfiguration->getLocalDatabases();
+
+$wgConf->wikis = $localDatabases;
+$wgConf->localVHosts = [ 'localhost' ];
+$wgConf->settings = $serviceConfiguration->getSettings();
+$wgConf->suffixes = $localDatabases;
+$wgConf->siteParamsCallback = 'Nasqueron\SAAS\MediaWiki\Hooks::onSiteParameters';
+
+$wgDBname = $serviceConfiguration->getSelectedDatabase();
+$wgDBserver = $_ENV['DB_HOST'];
+$wgDBuser = $_ENV['DB_USER'];
+$wgDBpassword = $_ENV['DB_PASS'];
+
+$wgConf->extractAllGlobals( $wgDBname );
+
+wfLoadExtensions($serviceConfiguration->getResources('Extension'));
+wfLoadSkins($serviceConfiguration->getResources('Skin'));
Index: composer.json
===================================================================
--- /dev/null
+++ composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "nasqueron/saas-mediawiki",
+ "description": "SaaS configuration entry point for MediaWiki",
+ "keywords": [
+ "nasqueron",
+ "SAAS",
+ "mediawiki",
+ "farm"
+ ],
+ "type": "project",
+ "license": "BSD-2-Clause",
+ "authors": [
+ {
+ "name": "Sébastien Santoro",
+ "email": "dereckson@espace-win.org"
+ }
+ ],
+ "require": {
+ "vlucas/phpdotenv": "dev-master"
+ },
+ "autoload": {
+ "psr-4": {
+ "Nasqueron\\SAAS\\": "lib-to-move-to-saas-service/",
+ "Nasqueron\\SAAS\\MediaWiki\\": "src/",
+ "Nasqueron\\SAAS\\MediaWiki\\Configuration\\": "config/",
+ "Nasqueron\\SAAS\\MediaWiki\\Tests\\": "tests/"
+ }
+ }
+}
Index: config/CommonSettings.php
===================================================================
--- /dev/null
+++ config/CommonSettings.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Nasqueron\SAAS\MediaWiki\Configuration;
+
+use Nasqueron\SAAS\ConfigurationException;
+
+class CommonSettings {
+
+ /**
+ * @throws ConfigurationException
+ */
+ public static function mapSettings (array &$settings) : void {
+ $settings += self::getMappedSettings($settings);
+ }
+
+ /**
+ * @throws ConfigurationException
+ */
+ public static function getMappedSettings (array $settings) : array {
+ $mappedSettings = [];
+ $mappedSettings += self::getRightsSettings($settings['saasLicense']);
+ return $mappedSettings;
+ }
+
+ ///
+ /// Individual set of settings
+ ///
+
+ /**
+ * @throws ConfigurationException
+ */
+ private static function getRightsSettings (array $licenses) : array {
+ $settings = [];
+ foreach ($licenses as $key => $license) {
+ switch ($license) {
+ case 'CC-BY 4.0':
+ $settings['wgRightsUrl'][$key] = 'http://creativecommons.org/licenses/by/4.0/';
+ $settings['wgRightsText'][$key] = 'Creative Commons Attribution 4.0 International License';
+ $settings['wgRightsIcon'][$key] = 'https://i.creativecommons.org/l/by/4.0/88x31.png';
+ break;
+
+ default:
+ throw new ConfigurationException("License unknown: $license");
+ }
+ }
+ return $settings;
+ }
+}
Index: config/Instances.php
===================================================================
--- /dev/null
+++ config/Instances.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Nasqueron\SAAS\MediaWiki\Configuration;
+
+use Nasqueron\SAAS\MediaWiki\InstancesRepository;
+
+class Instances extends InstancesRepository {
+
+ static public function getList () : array {
+ return [
+ // Format: => database name
+
+ "agora.nasqueron.org" => "nasqueron_wiki",
+ "arsmagica.espace-win.org" => "arsmagica",
+ "utopia.espace-win.org" => "utopia",
+ "www.wolfplex.be" => "wolfplexdb",
+ ];
+ }
+
+ static public function getAliases () : array {
+ return [
+ // Format: Database => [ hosts ]
+
+ "wolfplexdb" => [
+ "www.wolfplex.org",
+ "wiki.wolfplex.org",
+ "wiki.wolfplex.be",
+ ]
+ ];
+ }
+
+}
Index: config/MappableSettings.php
===================================================================
--- /dev/null
+++ config/MappableSettings.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Nasqueron\SAAS\MediaWiki\Configuration;
+
+///
+/// Temporary hack to get clean configuration.
+///
+/// Plan is to deploy the MediaWiki SaaS on a dedicated node.
+///
+/// Meanwhile, as we share the main Nasqueron MySQL database,
+/// with an history of databases going back to 2001, we need
+/// to map nicely named site key to actual databases names.
+
+abstract class MappableSettings {
+
+ abstract static public function getDatabaseMap() : array;
+ abstract static public function getMappedSettings() : array;
+
+ static public function getSettings () : array {
+ $settings = [];
+ foreach (static::getMappedSettings() as $setting => $values) {
+ $settings[$setting] = self::mapDatabases($values);
+ }
+ return $settings;
+ }
+
+ static private function mapDatabases ($items) {
+ $setting = [];
+ foreach ($items as $key => $value) {
+ $mappedKey = self::mapDatabase($key);
+ $setting[$mappedKey] = $value;
+ }
+ return $setting;
+ }
+
+ static private function mapDatabase ($key) {
+ foreach (static::getDatabaseMap() as $canonical => $actual) {
+ if ($key === $canonical) {
+ return $actual;
+ }
+ }
+
+ return $key;
+ }
+
+}
Index: config/Settings.php
===================================================================
--- /dev/null
+++ config/Settings.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace Nasqueron\SAAS\MediaWiki\Configuration;
+
+class Settings extends MappableSettings {
+
+ static public function getDatabaseMap () : array {
+ return [
+ 'agora' => 'nasqueron_wiki',
+ 'wolfplex' => 'wolfplexdb',
+ ];
+ }
+
+ static public function getMappedSettings () : array {
+ return [
+ 'wgDBprefix' => [
+ 'default' => '',
+
+ // Legacy installations
+ 'arsmagica' => 'arsm_',
+ 'utopia' => 'wiki_',
+ 'wolfplex' => 'mw_', // shared database
+ ],
+
+ 'wgSitename' => [
+ 'agora' => 'Nasqueron Agora',
+ 'arsmagica' => 'Ars Magica',
+ 'utopia' => 'Utopia',
+ 'wolfplex' => 'Wolfplex',
+ ],
+
+ 'wgLanguageCode' => [
+ 'default' => 'en',
+ 'arsmagica' => 'fr',
+ 'utopia' => 'fr',
+ ],
+
+ 'wgArticlePath' => [
+ 'default' => '/wiki/$1',
+ 'arsmagica' => '/$1',
+ ],
+
+ 'wgUploadDirectory' => [
+ 'agora' => '',
+ 'arsmagica' => '',
+ 'utopia' => '',
+ 'wolfplex' => '',
+ ],
+
+ 'wgLogo' => [
+ // Do we serve /w/images for each wiki?
+ 'default' => '/w/images/b/bc/Wiki.png',
+ ],
+
+ 'wgEnableUploads' => [
+ 'default' => false,
+ ],
+
+ 'wgNamespacesWithSubpages' => [
+ 'wolfplex' => [
+ NS_MAIN => true,
+ ],
+ 'nasqueron' => [
+ NS_MAIN => true,
+ ],
+ ],
+
+ 'saasLicense' => [
+ 'default' => 'CC-BY 4.0',
+ ],
+
+ 'wgEnableCreativeCommonsRdf' => [
+ 'default' => true,
+ ],
+
+ 'wgEnableDublinCoreRdf' => [
+ 'default' => true,
+ ],
+
+ 'saasUseExtensionCite' => [
+ 'default' => true,
+ ],
+
+ 'saasUseSkinMonoBook' => [
+ 'default' => true,
+ ],
+
+ 'saasUseSkinVector' => [
+ 'default' => true,
+ ],
+
+ 'saasUseSkinTimeless' => [
+ 'default' => true,
+ ],
+ ];
+ }
+
+}
Index: index.php
===================================================================
--- /dev/null
+++ index.php
@@ -0,0 +1,11 @@
+<?php
+
+use Nasqueron\SAAS\MediaWiki\Service;
+
+// Composer PSR-4 autoload. Allow to use an .env file or the environment.
+require __DIR__ . '/vendor/autoload.php';
+(new Dotenv\Dotenv(__DIR__))->safeLoad();
+
+$service = Service::preload();
+
+require $service->getEntryPoint();
Index: src/Configuration.php
===================================================================
--- /dev/null
+++ src/Configuration.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Nasqueron\SAAS\MediaWiki;
+
+use Nasqueron\SAAS\MediaWiki\Configuration\CommonSettings;
+use Nasqueron\SAAS\MediaWiki\Configuration\Instances;
+use Nasqueron\SAAS\MediaWiki\Configuration\Settings;
+
+class Configuration {
+
+ /**
+ * @var string
+ */
+ private $host;
+
+ public function __construct (string $host) {
+ $this->host = $host;
+ }
+
+ public function getLocalDatabases () : array {
+ return array_values(Instances::getList());
+ }
+
+ public function getSettings () : array {
+ // wg… keys
+ $settings = Settings::getSettings();
+
+ // saas… → wg… keys
+ CommonSettings::mapSettings($settings);
+
+ return $settings;
+ }
+
+ public function getResources (string $type) : array {
+ // saasUse<type><resource name>
+ // e.g. saasUseExtensionCite or saasUseSkinTimeless
+
+ $resources = [];
+
+ $prefix = "saasUse" . $type;
+ $len = strlen($prefix);
+ foreach ($GLOBALS as $key => $value) {
+ if (substr($key, 0, $len) === $prefix) {
+ $resources[] = substr($key, $len);
+ }
+ }
+
+ return $resources;
+ }
+
+ /**
+ * @throws \Nasqueron\SAAS\InstanceNotFoundException
+ */
+ public function getSelectedDatabase () {
+ return Instances::getDatabaseFromHost($this->host);
+ }
+
+ ///
+ /// Helper methods
+ ///
+
+ public static function isSelectedWiki (string $wiki, string $suffix) : bool {
+ return substr($wiki, -strlen($suffix)) == $suffix;
+ }
+}
Index: src/Hooks.php
===================================================================
--- /dev/null
+++ src/Hooks.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Nasqueron\SAAS\MediaWiki;
+
+class Hooks {
+
+ public static function onSiteParameters ($conf, $wiki) {
+ $site = null;
+ $lang = null;
+
+ foreach ($conf->suffixes as $suffix) {
+ if (Configuration::isSelectedWiki($wiki, $suffix)) {
+ $site = $suffix;
+ $lang = substr( $wiki, 0, -strlen( $suffix ) );
+ break;
+ }
+ }
+
+ return [
+ 'suffix' => $site,
+ 'lang' => $lang,
+ 'params' => [
+ 'lang' => $lang,
+ 'site' => $site,
+ 'wiki' => $wiki,
+ ],
+ 'tags' => [],
+ ];
+ }
+
+}
Index: src/InstancesRepository.php
===================================================================
--- /dev/null
+++ src/InstancesRepository.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Nasqueron\SAAS\MediaWiki;
+
+use Nasqueron\SAAS\InstanceNotFoundException;
+
+abstract class InstancesRepository {
+
+ ///
+ /// Repository data methods
+ ///
+
+ abstract static public function getList () : array;
+ abstract static public function getAliases () : array;
+
+ ///
+ /// Helper methods
+ ///
+
+ /**
+ * @throws InstanceNotFoundException
+ */
+ public static function getDatabaseFromHost (string $host) : string {
+ // Case 1 - the host is canonical
+ $canonicalList = static::getList();
+ if (isset($canonicalList[$host])) {
+ return $canonicalList[$host];
+ }
+
+ // Case 2 - the host is an alias
+ foreach (static::getAliases() as $database => $vhost) {
+ if ($host === $vhost) {
+ return $database;
+ }
+ }
+
+ throw new InstanceNotFoundException($host);
+ }
+
+}
Index: src/Service.php
===================================================================
--- /dev/null
+++ src/Service.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace Nasqueron\SAAS\MediaWiki;
+
+use Nasqueron\SAAS\InstanceNotFoundException;
+use Nasqueron\SAAS\SaaSException;
+use Nasqueron\SAAS\Service as BaseService;
+use Nasqueron\SAAS\MediaWiki\Configuration\Instances;
+
+class Service extends BaseService {
+
+ /**
+ * @var string
+ */
+ private $host;
+
+ /**
+ * @var Configuration
+ */
+ private $configuration = null;
+
+ /**
+ * @var Service
+ */
+ private static $service = null;
+
+ public function __construct (string $host = '') {
+ $this->host = $host ?: self::getServerHost();
+ }
+
+ /**
+ * @return Service
+ */
+ public static function preload()
+ {
+ if (self::$service === null) {
+ self::$service = new self;
+ try {
+ self::$service
+ ->handleNotExistingSite()
+ ->handleAliveRequest();
+ } catch (SaaSException $exception) {
+ self::$service->serveNotAvailableResponse();
+ }
+ }
+
+ return self::$service;
+
+ }
+
+ public function getHost () : string {
+ return $this->host;
+ }
+
+ public function run () : void {
+ $this->decorateHeaders();
+ }
+
+ public function isExisting () : bool {
+ try {
+ Instances::getDatabaseFromHost($this->host);
+ } catch (InstanceNotFoundException $exception) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private function decorateHeaders () : void {
+ header("SaaS-Host: " . $this->host);
+ header("SaaS-App: MediaWiki");
+ }
+
+ public function serveNotExistingResponse() : void {
+ header("HTTP/1.0 404 Not Found");
+
+ require __DIR__ . '/../views/404.php';
+ die;
+ }
+
+
+ public function serveNotAvailableResponse() : void {
+ header("HTTP/1.0 503 Service Unavailable");
+
+ require __DIR__ . '/../views/503.php';
+ die;
+ }
+
+ public function getEntryPoint() : string {
+ return $_ENV['MEDIAWIKI_ENTRY_POINT'];
+ }
+
+ public function getConfiguration() : Configuration {
+ if ($this->configuration === null) {
+ $this->configuration = new Configuration($this->host);
+ }
+
+ return $this->configuration;
+ }
+
+}
Index: views/404.php
===================================================================
--- /dev/null
+++ views/404.php
@@ -0,0 +1,25 @@
+<!doctype html>
+<html class="no-js" lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="x-ua-compatible" content="ie=edge">
+ <title>SaaS :: Instance not found</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+</head>
+<body>
+
+<h1>Service not found</h1>
+<p>The <?= $this->getHost() ?> instance of your service is not available.</p>
+<p>This generally means the domain name has been configured to point to
+ this server, but is not declared in the configuration.</p>
+<h2>Is this a new wiki?</h2>
+<p>This entry point serves several wikis. If you're creating a new wiki, this message means
+ you've successfully configured the DNS and the front-end web server.</p>
+
+<p>The next step is to declare your wiki to the <strong>saas-mediawiki</strong> repository.</p>
+<p>Create the wiki database if still not done and
+ declare the host / database pair to the <tt>config/Instances.php</tt> file.</p>
+<p>This repository is also where you can customize the wiki settings,
+in the <tt>config/Settings.php</tt> file.<br />You probably want to customize site name there.</p>
+<p>You've done all those steps? Reload php-fpm to reset caching or troubleshoot those files.</p>
+</html>
Index: views/503.php
===================================================================
--- /dev/null
+++ views/503.php
@@ -0,0 +1,14 @@
+<!doctype html>
+<html class="no-js" lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="x-ua-compatible" content="ie=edge">
+ <title>SaaS :: Instance not available</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+</head>
+<body>
+
+<p>The service is not available. Please retry in a few moment.</p>
+
+</body>
+</html>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jun 9, 19:40 (17 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2717394
Default Alt Text
D1442.id3692.diff (17 KB)
Attached To
Mode
D1442: Provide configuration for wikis
Attached
Detach File
Event Timeline
Log In to Comment