Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preliminary Implementation of Wiki Farm Support for Canasta #250

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
APACHE_LOG_DIR=/var/log/apache2

# System setup
RUN set x; \

Check failure on line 17 in Dockerfile

View workflow job for this annotation

GitHub Actions / test

DL3008 warning: Pin versions in apt get install. Instead of `apt-get install <package>` use `apt-get install <package>=<version>`

Check failure on line 17 in Dockerfile

View workflow job for this annotation

GitHub Actions / test

DL3015 info: Avoid additional packages by specifying `--no-install-recommends`
apt-get clean \
&& apt-get update \
&& apt-get install -y aptitude \
Expand Down Expand Up @@ -61,6 +61,7 @@
php7.4-curl \
php7.4-zip \
php7.4-fpm \
php7.4-yaml \
libapache2-mod-fcgid \
&& aptitude clean \
&& rm -rf /var/lib/apt/lists/*
Expand Down Expand Up @@ -736,8 +737,9 @@
COPY _sources/configs/robots.txt $WWW_ROOT/
COPY _sources/configs/.htaccess $WWW_ROOT/
COPY _sources/images/favicon.ico $WWW_ROOT/
COPY _sources/canasta/LocalSettings.php _sources/canasta/CanastaUtils.php _sources/canasta/CanastaDefaultSettings.php $MW_HOME/
COPY _sources/canasta/LocalSettings.php _sources/canasta/CanastaUtils.php _sources/canasta/CanastaDefaultSettings.php _sources/canasta/FarmConfigLoader.php $MW_HOME/
COPY _sources/canasta/getMediawikiSettings.php /
COPY _sources/canasta/canasta_img.php $MW_HOME/
COPY _sources/configs/mpm_event.conf /etc/apache2/mods-available/mpm_event.conf

RUN set -x; \
Expand All @@ -752,10 +754,13 @@
&& sed -i 's/MW_CONFIG_FILE/CANASTA_CONFIG_FILE/g' "$MW_HOME/includes/CanastaNoLocalSettings.php" \
# Modify config
&& sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf \
&& sed -i '/<Directory \/var\/www\/>/i RewriteCond %{THE_REQUEST} \\s(.*?)\\s\nRewriteRule ^ - [E=ORIGINAL_URL:%{REQUEST_SCHEME}://%{HTTP_HOST}%1]' /etc/apache2/apache2.conf \
&& echo "Alias /w/images/ /var/www/mediawiki/w/canasta_img.php/" >> /etc/apache2/apache2.conf \
&& echo "Alias /w/images /var/www/mediawiki/w/canasta_img.php" >> /etc/apache2/apache2.conf \
&& a2enmod expires \
&& a2disconf other-vhosts-access-log \
# Enable environment variables for FPM workers
&& sed -i '/clear_env/s/^;//' /etc/php/7.4/fpm/pool.d/www.conf
&& sed -i '/clear_env/s/^;//' /etc/php/7.4/fpm/pool.d/www.conf

COPY _sources/images/Powered-by-Canasta.png /var/www/mediawiki/w/resources/assets/

Expand Down
33 changes: 26 additions & 7 deletions _sources/canasta/CanastaDefaultSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
exit;
}

require_once "$IP/CanastaUtils.php";
require_once "{$IP}/CanastaUtils.php";

$canastaLocalSettingsFilePath = getenv( 'MW_VOLUME' ) . '/config/LocalSettings.php';
chl178 marked this conversation as resolved.
Show resolved Hide resolved
$canastaCommonSettingsFilePath = getenv( 'MW_VOLUME' ) . '/config/CommonSettings.php';
jeffw16 marked this conversation as resolved.
Show resolved Hide resolved

if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
// Called from WebInstaller or similar entry point

if ( !file_exists( $canastaLocalSettingsFilePath ) ) {
if ( !file_exists( $canastaLocalSettingsFilePath ) && !file_exists( $canastaCommonSettingsFilePath ) ) {
// Remove all variables, WebInstaller should decide that "$IP/LocalSettings.php" does not exist.
$vars = array_keys( get_defined_vars() );
foreach ( $vars as $v => $k ) {
Expand All @@ -24,7 +26,7 @@
// WebStart entry point

// Check that user's LocalSettings.php exists
if ( !is_readable( $canastaLocalSettingsFilePath ) ) {
if ( !is_readable( $canastaLocalSettingsFilePath ) && !is_readable( $canastaCommonSettingsFilePath ) ) {
// Emulate that "$IP/LocalSettings.php" does not exist

// Set CANASTA_CONFIG_FILE for NoLocalSettings template work correctly in includes/CanastaNoLocalSettings.php
Expand Down Expand Up @@ -70,10 +72,27 @@
$wgCdnServersNoPurge[] = '172.16.0.0/12'; // 172.16.0.0 – 172.31.255.255
$wgCdnServersNoPurge[] = '192.168.0.0/16'; // 192.168.0.0 – 192.168.255.255

# Include user defined CommonSettings.php file
if ( file_exists( $canastaCommonSettingsFilePath ) ) {
require_once "$canastaCommonSettingsFilePath";
}

# Include user defined LocalSettings.php file
require_once "$canastaLocalSettingsFilePath";
if ( file_exists( $canastaLocalSettingsFilePath ) ) {
require_once "$canastaLocalSettingsFilePath";
}

$filenames = glob( getenv( 'MW_VOLUME' ) . '/config/settings/*.php' );

if ( $filenames !== false && is_array( $filenames ) ) {
sort( $filenames );

foreach ( $filenames as $filename ) {
require_once "$filename";
}
}

# Include all php files in config/settings directory
foreach (glob(getenv( 'MW_VOLUME' ) . '/config/settings/*.php') as $filename) {
require_once $filename;
# Include the FarmConfig
if ( file_exists( getenv( 'MW_VOLUME' ) . '/config/wikis.yaml' ) ) {
require_once "$IP/FarmConfigLoader.php";
}
2 changes: 1 addition & 1 deletion _sources/canasta/CanastaUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function cfLoadSkin( $skinName ) {
/**
* Not exactly a utility function, but - show a warning to users if $wgSMTP is not set.
*/
$wgHooks['SiteNoticeAfter'][] = function ( &$siteNotice, Skin $skin ) {
$wgHooks['SiteNoticeAfter'][] = static function ( &$siteNotice, Skin $skin ) {
global $wgSMTP, $wgEnableEmail, $wgEnableUserEmail;

if ( !$wgEnableEmail || $wgSMTP ) {
Expand Down
153 changes: 153 additions & 0 deletions _sources/canasta/FarmConfigLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<?php

# Protect against web entry
if ( !defined( 'MEDIAWIKI' ) ) {
exit;
chl178 marked this conversation as resolved.
Show resolved Hide resolved
}

// Get the original URL from the environment variables
$original_url = getenv( 'ORIGINAL_URL' );
$serverName = "";
$path = "";

// Check if the original URL is defined, else throw an exception
if ( $original_url === false && !defined( 'MW_WIKI_NAME' ) ) {
return;
}

// Parse the original URL
$urlComponents = parse_url( $original_url );

// Check if URL parsing was successful, else throw an exception
if ( $urlComponents === false ) {
throw new Exception( 'Error: Failed to parse the original URL' );
}

// Extract the server name (host) from the URL
if ( isset( $urlComponents['host'] ) ) {
$serverName = $urlComponents['host'];
}

// Extract the path from the URL, if any
if ( isset( $urlComponents['path'] ) ) {
// Split the path into parts
$pathParts = explode( '/', trim( $urlComponents['path'], '/' ) );

// Check if path splitting was successful, else throw an exception
if ( $pathParts === false ) {
throw new Exception( 'Error: Failed to split the path into parts' );
}

// If there is a path, store the first directory in the variable $path
if ( count( $pathParts ) > 0 ) {
$firstDirectory = $pathParts[0];
}

// If the first directory is not "wiki" or "w", store it in the variable $path
if ( $firstDirectory != "wiki" && $firstDirectory != "w" ) {
$path = $firstDirectory;
}
}

// Parse the YAML configuration file containing the wiki information
$wikiConfigurations = null;

try {
// Get the file path of the YAML configuration file
$file = getenv( 'MW_VOLUME' ) . '/config/wikis.yaml';

// Check if the configuration file exists, else throw an exception
if ( !file_exists( $file ) ) {
throw new Exception( 'The configuration file does not exist' );
}

// Parse the configuration file
$wikiConfigurations = yaml_parse_file( $file );

// Check if file parsing was successful, else throw an exception
if ( $wikiConfigurations === false ) {
throw new Exception( 'Error parsing the configuration file' );
}
} catch ( Exception $e ) {
die( 'Caught exception: ' . $e->getMessage() );
}

$wikiIdToConfigMap = [];
$urlToWikiIdMap = [];

// Populate the arrays with data from the configuration file
if ( isset( $wikiConfigurations ) && isset( $wikiConfigurations['wikis'] ) && is_array( $wikiConfigurations['wikis'] ) ) {
foreach ( $wikiConfigurations['wikis'] as $wiki ) {
// Check if 'url' and 'id' are set before using them
if ( isset( $wiki['url'] ) && isset( $wiki['id'] ) ) {
$urlToWikiIdMap[$wiki['url']] = $wiki['id'];
$wikiIdToConfigMap[$wiki['id']] = $wiki;
} else {
throw new Exception( 'Error: The wiki configuration is missing either the url or id attribute.' );
}
}
} else {
throw new Exception( 'Error: Invalid wiki configurations.' );
}

// Prepare the key using the server name and the path
if ( empty( $path ) ) {
$key = $serverName;
} else {
$key = $serverName . '/' . $path;
}

// Retrieve the wikiID if available
$wikiID = defined( 'MW_WIKI_NAME' ) ? MW_WIKI_NAME : null;

// Check if the key is null or if it exists in the urlToWikiIdMap, else throw an exception
if ( $key === null ) {
throw new Exception( "Error: Key is null." );
} elseif ( $wikiID === null && array_key_exists( $key, $urlToWikiIdMap ) ) {
$wikiID = $urlToWikiIdMap[$key];
} elseif ( $wikiID === null ) {
throw new Exception( "Error: $key does not exist in urlToWikiIdMap." );
}

// Get the configuration for the selected wiki
$selectedWikiConfig = $wikiIdToConfigMap[$wikiID] ?? null;

// Check if a matching configuration was found. If so, configure the wiki database, else terminate execution
if ( !empty( $selectedWikiConfig ) ) {
// Set database name to the wiki ID
$wgDBname = $wikiID;

// Set site name and meta namespace from the configuration, or use the wiki ID if 'name' is not set
$wgSitename = isset( $selectedWikiConfig['name'] ) ? $selectedWikiConfig['name'] : $wikiID;
$wgMetaNamespace = isset( $selectedWikiConfig['name'] ) ? $selectedWikiConfig['name'] : $wikiID;
} else {
die( 'Unknown wiki.' );
}

// Configure the wiki server and URL paths
$wgServer = "https://$serverName";
$wgScriptPath = !empty( $path )
? "/$path/w"
: "/w";

$wgArticlePath = !empty( $path )
? "/$path/wiki/$1"
: "/wiki/$1";
$wgCacheDirectory = "$IP/cache/$wikiID";
$wgUploadDirectory = "$IP/images/$wikiID";

// Load additional configuration files specific to the wiki ID
$files = glob( getenv( 'MW_VOLUME' ) . "/config/{$wikiID}/*.php" );

$wgEnableUploads = true;

// Check if the glob function was successful, else continue with the execution
if ( $files !== false && is_array( $files ) ) {
// Sort the files
sort( $files );

// Include each file
foreach ( $files as $filename ) {
require_once "$filename";
}
}
Loading
Loading