Skip to content
This repository has been archived by the owner on Sep 23, 2023. It is now read-only.

Commit

Permalink
Create wikis in a background process
Browse files Browse the repository at this point in the history
* The form now points to start.php, which converts
  allowed POST data to environment variables and
  sends them to new.php
* The output is written to log files in log/*.html
  which are then polled by the JS for new content
  every second
* Logs are only deleted when the wiki is deleted,
  allowing for debugging and inspection by other
  users.

Fixes #399
  • Loading branch information
edg2s committed Dec 15, 2021
1 parent b133f56 commit 7f94c4f
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 157 deletions.
2 changes: 2 additions & 0 deletions deletewiki.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ set -ex

rm -rf $PATCHDEMO/wikis/$WIKI

rm $PATCHDEMO/logs/$WIKI.html

# delete database
mysql -u patchdemo --password=patchdemo -e "DROP DATABASE IF EXISTS patchdemo_$WIKI";
39 changes: 33 additions & 6 deletions includes.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,17 @@ function shell( $cmd, array $env = [] ): ?string {
return $error ? null : $process->getOutput();
}

/**
* Can't be called from CLI, use delete_wiki_cli_safe
*
* @param string $wiki Wiki name
* @return int Error code
*/
function delete_wiki( string $wiki ): int {
return delete_wiki_cli_safe( $wiki, getServer() . getServerPath() );
}

function delete_wiki_cli_safe( string $wiki, string $serverUri ): int {
global $mysqli;

$wikiData = get_wiki_data( $wiki );
Expand All @@ -325,16 +335,12 @@ function delete_wiki( string $wiki ): int {
);

foreach ( $wikiData['announcedTasks'] as $task ) {
// TODO: Deduplicate server/serverPath with variables in new.php
$server = detectProtocol() . '://' . $_SERVER['HTTP_HOST'];
$serverPath = preg_replace( '`/[^/]*$`', '', $_SERVER['REQUEST_URI'] );

$creator = $wikiData['creator'];
post_phab_comment(
'T' . $task,
"Test wiki on [[ $server$serverPath | Patch demo ]] " . ( $creator ? ' by ' . $creator : '' ) . " using patch(es) linked to this task was **deleted**:\n" .
"Test wiki on [[ $serverUri | Patch demo ]] " . ( $creator ? ' by ' . $creator : '' ) . " using patch(es) linked to this task was **deleted**:\n" .
"\n" .
"~~[[ $server$serverPath/wikis/$wiki/w/ ]]~~"
"~~[[ $serverUri/wikis/$wiki/w/ ]]~~"
);
}

Expand Down Expand Up @@ -475,7 +481,14 @@ function get_repo_presets(): array {
return $presets;
}

function isCli(): bool {
return PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg';
}

function detectProtocol(): string {
if ( isCli() ) {
throw new Error( 'Can\'t access server variables from CLI.' );
}
// Copied from MediaWiki's WebRequest::detectProtocol
if (
( !empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) ||
Expand All @@ -490,6 +503,20 @@ function detectProtocol(): string {
}
}

function getServer(): string {
if ( isCli() ) {
throw new Error( 'Can\'t access server variables from CLI.' );
}
return detectProtocol() . '://' . $_SERVER['HTTP_HOST'];
}

function getServerPath(): string {
if ( isCli() ) {
throw new Error( 'Can\'t access server variables from CLI.' );
}
return preg_replace( '`/[^/]*$`', '', $_SERVER['REQUEST_URI'] );
}

function get_csrf_token(): string {
global $useOAuth;
if ( !$useOAuth ) {
Expand Down
7 changes: 5 additions & 2 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
echo new OOUI\FormLayout( [
'infusable' => true,
'method' => 'POST',
'action' => 'new.php',
'action' => 'start.php',
'id' => 'new-form',
'items' => [
new OOUI\FieldsetLayout( [
Expand Down Expand Up @@ -311,7 +311,10 @@
'<td data-label="Linked tasks" class="linkedTasks">' . $linkedTasks . '</td>' .
'<td data-label="Time" class="date">' . date( 'Y-m-d H:i:s', $wikiData[ 'created' ] ) . '</td>' .
( $useOAuth ? '<td data-label="Creator">' . ( $creator ? user_link( $creator ) : '?' ) . '</td>' : '' ) .
( $canAdmin ? '<td data-label="Time to create">' . ( $wikiData['timeToCreate'] ? $wikiData['timeToCreate'] . 's' : '' ) . '</td>' : '' ) .
( $canAdmin ?
'<td data-label="Time to create"><a href="start.php?wiki=' . $wiki . '">' . ( $wikiData['timeToCreate'] ? $wikiData['timeToCreate'] . 's' : '' ) . '</a></td>' :
''
) .
( $canDelete ?
'<td data-label="Actions"><a href="delete.php?wiki=' . $wiki . '">Delete</a></td>' :
'<!-- EMPTY ACTIONS -->'
Expand Down
28 changes: 0 additions & 28 deletions js/new.js

This file was deleted.

57 changes: 57 additions & 0 deletions js/start.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* global OO, pd */
( function () {
window.pd = window.pd || {};

pd.installProgressField = OO.ui.infuse(
document.getElementsByClassName( 'installProgressField' )[ 0 ]
);

pd.installProgressField.fieldWidget.pushPending();

pd.openWiki = OO.ui.infuse(
document.getElementsByClassName( 'openWiki' )[ 0 ]
);

pd.notify = function ( message, body ) {
if ( 'Notification' in window && +localStorage.getItem( 'patchdemo-notifications' ) ) {
// eslint-disable-next-line no-new
new Notification(
message,
{
icon: './images/favicon-32x32.png',
body: body
}
);
}
};

$( function () {
var log = '';
var offset = 0;
// eslint-disable-next-line no-jquery/no-global-selector
var $log = $( '.newWikiLog' );
function poll() {
$.get( 'log.php', {
wiki: pd.wiki,
offset: offset
} ).then( function ( result ) {
if ( result ) {
// result can be unbalanced HTML, so store it in
// a string and rewrite the whole thing each time
log += result;
$log.html( log );
offset += result.length;
}
if ( !pd.finished ) {
setTimeout( poll, 1000 );
}
} );
}

poll();

// Add wiki to URL so that page can be shared/reloaded
history.replaceState( null, '', 'start.php?wiki=' + pd.wiki );
} );

}() );
33 changes: 33 additions & 0 deletions log.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

$offset = $_GET['offset'];
$wiki = $_GET['wiki'];

if ( !preg_match( '/^[0-9a-f]{10,32}$/', $wiki ) ) {
die( 'Invalid wiki name.' );
}

$file = 'logs/' . $wiki . '.html';

if ( file_exists( $file ) ) {
echo file_get_contents(
$file,
false,
null,
$offset
);
} else {
// TODO: De-duplicate with new.php
$err = 'Log not found.';
echo $err;
$errJson = json_encode( $err );
echo <<<EOT
<script>
pd.installProgressField.fieldWidget.setDisabled( true );
pd.installProgressField.fieldWidget.popPending();
pd.installProgressField.setErrors( [ new OO.ui.HtmlSnippet( $errJson ) ] );
pd.notify( 'Your PatchDemo wiki failed to build', $errJson );
pd.finished = true;
</script>
EOT;
}
Loading

0 comments on commit 7f94c4f

Please sign in to comment.