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

Commit df58b13

Browse files
committed
Create wikis in a background process
* 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, #336
1 parent f8bf392 commit df58b13

File tree

9 files changed

+298
-193
lines changed

9 files changed

+298
-193
lines changed

deletewiki.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ set -ex
33

44
rm -rf $PATCHDEMO/wikis/$WIKI
55

6+
rm $PATCHDEMO/logs/$WIKI.html
7+
68
# delete database
79
mysql -u patchdemo --password=patchdemo -e "DROP DATABASE IF EXISTS patchdemo_$WIKI";

includes.php

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,17 @@ function shell( $cmd, array $env = [] ): ?string {
316316
return $error ? null : $process->getOutput();
317317
}
318318

319+
/**
320+
* Can't be called from CLI, use delete_wiki_cli_safe
321+
*
322+
* @param string $wiki Wiki name
323+
* @return int Error code
324+
*/
319325
function delete_wiki( string $wiki ): int {
326+
return delete_wiki_cli_safe( $wiki, get_server() . get_server_path() );
327+
}
328+
329+
function delete_wiki_cli_safe( string $wiki, string $serverUri ): int {
320330
global $mysqli;
321331

322332
$wikiData = get_wiki_data( $wiki );
@@ -333,16 +343,12 @@ function delete_wiki( string $wiki ): int {
333343
);
334344

335345
foreach ( $wikiData['announcedTasks'] as $task ) {
336-
// TODO: Deduplicate server/serverPath with variables in new.php
337-
$server = detectProtocol() . '://' . $_SERVER['HTTP_HOST'];
338-
$serverPath = preg_replace( '`/[^/]*$`', '', $_SERVER['REQUEST_URI'] );
339-
340346
$creator = $wikiData['creator'];
341347
post_phab_comment(
342348
'T' . $task,
343-
"Test wiki on [[ $server$serverPath | Patch demo ]] " . ( $creator ? ' by ' . $creator : '' ) . " using patch(es) linked to this task was **deleted**:\n" .
349+
"Test wiki on [[ $serverUri | Patch demo ]] " . ( $creator ? ' by ' . $creator : '' ) . " using patch(es) linked to this task was **deleted**:\n" .
344350
"\n" .
345-
"~~[[ $server$serverPath/wikis/$wiki/w/ ]]~~"
351+
"~~[[ $serverUri/wikis/$wiki/w/ ]]~~"
346352
);
347353
}
348354

@@ -478,7 +484,14 @@ function get_repo_presets(): array {
478484
return $presets;
479485
}
480486

481-
function detectProtocol(): string {
487+
function is_cli(): bool {
488+
return PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg';
489+
}
490+
491+
function detect_protocol(): string {
492+
if ( is_cli() ) {
493+
throw new Error( 'Can\'t access server variables from CLI.' );
494+
}
482495
// Copied from MediaWiki's WebRequest::detectProtocol
483496
if (
484497
( !empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) ||
@@ -493,6 +506,20 @@ function detectProtocol(): string {
493506
}
494507
}
495508

509+
function get_server(): string {
510+
if ( is_cli() ) {
511+
throw new Error( 'Can\'t access server variables from CLI.' );
512+
}
513+
return detect_protocol() . '://' . $_SERVER['HTTP_HOST'];
514+
}
515+
516+
function get_server_path(): string {
517+
if ( is_cli() ) {
518+
throw new Error( 'Can\'t access server variables from CLI.' );
519+
}
520+
return preg_replace( '`/[^/]*$`', '', $_SERVER['REQUEST_URI'] );
521+
}
522+
496523
function get_csrf_token(): string {
497524
global $useOAuth;
498525
if ( !$useOAuth ) {

index.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
echo new OOUI\FormLayout( [
5858
'infusable' => true,
5959
'method' => 'POST',
60-
'action' => 'new.php',
60+
'action' => 'start.php',
6161
'id' => 'new-form',
6262
'items' => [
6363
new OOUI\FieldsetLayout( [
@@ -348,7 +348,10 @@
348348
'<td data-label="Linked tasks" class="linkedTasks">' . $linkedTasks . '</td>' .
349349
'<td data-label="Time" class="date">' . date( 'Y-m-d H:i:s', $wikiData[ 'created' ] ) . '</td>' .
350350
( $useOAuth ? '<td data-label="Creator">' . ( $creator ? user_link( $creator ) : '?' ) . '</td>' : '' ) .
351-
( $canAdmin ? '<td data-label="Time to create">' . ( $wikiData['timeToCreate'] ? $wikiData['timeToCreate'] . 's' : '' ) . '</td>' : '' ) .
351+
( $canAdmin ?
352+
'<td data-label="Time to create"><a href="start.php?wiki=' . $wiki . '">' . ( $wikiData['timeToCreate'] ? $wikiData['timeToCreate'] . 's' : '' ) . '</a></td>' :
353+
''
354+
) .
352355
( count( $actions ) ?
353356
'<td data-label="Actions">' . implode( '&nbsp;&middot;&nbsp;', $actions ) . '</td>' :
354357
'<!-- EMPTY ACTIONS -->'

js/new.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

js/start.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/* global OO, pd */
2+
( function () {
3+
window.pd = window.pd || {};
4+
5+
var installProgressField = OO.ui.infuse(
6+
document.getElementsByClassName( 'installProgressField' )[ 0 ]
7+
);
8+
9+
installProgressField.fieldWidget.pushPending();
10+
11+
var openWiki = OO.ui.infuse(
12+
document.getElementsByClassName( 'openWiki' )[ 0 ]
13+
);
14+
15+
function endProgress() {
16+
installProgressField.fieldWidget.popPending();
17+
pd.finished = true;
18+
}
19+
20+
pd.abandon = function ( html ) {
21+
installProgressField.fieldWidget.setDisabled( true );
22+
installProgressField.setErrors( [ new OO.ui.HtmlSnippet( html ) ] );
23+
pd.notify( 'Your PatchDemo wiki failed to build', html );
24+
endProgress();
25+
};
26+
27+
pd.setProgress = function ( pc, label ) {
28+
installProgressField.fieldWidget.setProgress( pc );
29+
installProgressField.setLabel( label );
30+
if ( pc === 100 ) {
31+
openWiki.setDisabled( false );
32+
pd.notify( 'Your PatchDemo wiki is ready!' );
33+
endProgress();
34+
}
35+
};
36+
37+
pd.notify = function ( message, body ) {
38+
if ( 'Notification' in window && +localStorage.getItem( 'patchdemo-notifications' ) ) {
39+
// eslint-disable-next-line no-new
40+
new Notification(
41+
message,
42+
{
43+
icon: './images/favicon-32x32.png',
44+
body: body
45+
}
46+
);
47+
}
48+
};
49+
50+
$( function () {
51+
// eslint-disable-next-line no-jquery/no-global-selector
52+
var $log = $( '.newWikiLog' );
53+
var log = '';
54+
var offset = 0;
55+
function poll() {
56+
$.get( 'log.php', {
57+
wiki: pd.wiki,
58+
offset: offset
59+
} ).then( function ( result ) {
60+
if ( result ) {
61+
// result can be unbalanced HTML, so store it in
62+
// a string and rewrite the whole thing each time
63+
log += result;
64+
$log.html( log );
65+
offset += result.length;
66+
}
67+
if ( !pd.finished ) {
68+
setTimeout( poll, 1000 );
69+
}
70+
} );
71+
}
72+
73+
poll();
74+
75+
// Add wiki to URL so that page can be shared/reloaded
76+
history.replaceState( null, '', 'start.php?wiki=' + pd.wiki );
77+
} );
78+
79+
}() );

log.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
$offset = $_GET['offset'];
4+
$wiki = $_GET['wiki'];
5+
6+
if ( !preg_match( '/^[0-9a-f]{10,32}$/', $wiki ) ) {
7+
die( 'Invalid wiki name.' );
8+
}
9+
10+
$file = 'logs/' . $wiki . '.html';
11+
12+
if ( file_exists( $file ) ) {
13+
echo file_get_contents(
14+
$file,
15+
false,
16+
null,
17+
$offset
18+
);
19+
} else {
20+
echo "<script>pd.abandon( 'Log not found.' );</script>";
21+
}

0 commit comments

Comments
 (0)