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

Commit 0c4d135

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 b133f56 commit 0c4d135

File tree

9 files changed

+271
-158
lines changed

9 files changed

+271
-158
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
@@ -308,7 +308,17 @@ function shell( $cmd, array $env = [] ): ?string {
308308
return $error ? null : $process->getOutput();
309309
}
310310

311+
/**
312+
* Can't be called from CLI, use delete_wiki_cli_safe
313+
*
314+
* @param string $wiki Wiki name
315+
* @return int Error code
316+
*/
311317
function delete_wiki( string $wiki ): int {
318+
return delete_wiki_cli_safe( $wiki, get_server() . get_server_path() );
319+
}
320+
321+
function delete_wiki_cli_safe( string $wiki, string $serverUri ): int {
312322
global $mysqli;
313323

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

327337
foreach ( $wikiData['announcedTasks'] as $task ) {
328-
// TODO: Deduplicate server/serverPath with variables in new.php
329-
$server = detectProtocol() . '://' . $_SERVER['HTTP_HOST'];
330-
$serverPath = preg_replace( '`/[^/]*$`', '', $_SERVER['REQUEST_URI'] );
331-
332338
$creator = $wikiData['creator'];
333339
post_phab_comment(
334340
'T' . $task,
335-
"Test wiki on [[ $server$serverPath | Patch demo ]] " . ( $creator ? ' by ' . $creator : '' ) . " using patch(es) linked to this task was **deleted**:\n" .
341+
"Test wiki on [[ $serverUri | Patch demo ]] " . ( $creator ? ' by ' . $creator : '' ) . " using patch(es) linked to this task was **deleted**:\n" .
336342
"\n" .
337-
"~~[[ $server$serverPath/wikis/$wiki/w/ ]]~~"
343+
"~~[[ $serverUri/wikis/$wiki/w/ ]]~~"
338344
);
339345
}
340346

@@ -475,7 +481,14 @@ function get_repo_presets(): array {
475481
return $presets;
476482
}
477483

478-
function detectProtocol(): string {
484+
function is_cli(): bool {
485+
return PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg';
486+
}
487+
488+
function detect_protocol(): string {
489+
if ( is_cli() ) {
490+
throw new Error( 'Can\'t access server variables from CLI.' );
491+
}
479492
// Copied from MediaWiki's WebRequest::detectProtocol
480493
if (
481494
( !empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) ||
@@ -490,6 +503,20 @@ function detectProtocol(): string {
490503
}
491504
}
492505

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

index.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
echo new OOUI\FormLayout( [
5757
'infusable' => true,
5858
'method' => 'POST',
59-
'action' => 'new.php',
59+
'action' => 'start.php',
6060
'id' => 'new-form',
6161
'items' => [
6262
new OOUI\FieldsetLayout( [
@@ -311,7 +311,10 @@
311311
'<td data-label="Linked tasks" class="linkedTasks">' . $linkedTasks . '</td>' .
312312
'<td data-label="Time" class="date">' . date( 'Y-m-d H:i:s', $wikiData[ 'created' ] ) . '</td>' .
313313
( $useOAuth ? '<td data-label="Creator">' . ( $creator ? user_link( $creator ) : '?' ) . '</td>' : '' ) .
314-
( $canAdmin ? '<td data-label="Time to create">' . ( $wikiData['timeToCreate'] ? $wikiData['timeToCreate'] . 's' : '' ) . '</td>' : '' ) .
314+
( $canAdmin ?
315+
'<td data-label="Time to create"><a href="start.php?wiki=' . $wiki . '">' . ( $wikiData['timeToCreate'] ? $wikiData['timeToCreate'] . 's' : '' ) . '</a></td>' :
316+
''
317+
) .
315318
( $canDelete ?
316319
'<td data-label="Actions"><a href="delete.php?wiki=' . $wiki . '">Delete</a></td>' :
317320
'<!-- EMPTY ACTIONS -->'

js/new.js

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

js/start.js

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

log.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
// TODO: De-duplicate with new.php
21+
$err = 'Log not found.';
22+
echo $err;
23+
$errJson = json_encode( $err );
24+
echo <<<EOT
25+
<script>
26+
pd.installProgressField.fieldWidget.setDisabled( true );
27+
pd.installProgressField.fieldWidget.popPending();
28+
pd.installProgressField.setErrors( [ new OO.ui.HtmlSnippet( $errJson ) ] );
29+
pd.notify( 'Your PatchDemo wiki failed to build', $errJson );
30+
pd.finished = true;
31+
</script>
32+
EOT;
33+
}

0 commit comments

Comments
 (0)