Skip to content

Commit 8214316

Browse files
authored
delete messages using ajax (#384)
1 parent b0253ac commit 8214316

File tree

7 files changed

+137
-12
lines changed

7 files changed

+137
-12
lines changed

resources/autoload.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
require_once __DIR__ . "/lib/exceptions/EnsureException.php";
3333
require_once __DIR__ . "/lib/exceptions/EncodingUnknownException.php";
3434
require_once __DIR__ . "/lib/exceptions/EncodingConversionException.php";
35+
require_once __DIR__ . "/lib/exceptions/UnityHTTPDMessageNotFoundException.php";
3536

3637
require_once __DIR__ . "/config.php";
3738
require __DIR__ . "/init.php";

resources/lib/UnityHTTPD.php

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use UnityWebPortal\lib\exceptions\NoDieException;
66
use UnityWebPortal\lib\exceptions\ArrayKeyException;
7+
use UnityWebPortal\lib\exceptions\UnityHTTPDMessageNotFoundException;
78
use RuntimeException;
89

910
enum UnityHTTPDMessageLevel: string
@@ -226,13 +227,22 @@ public static function errorHandler(int $severity, string $message, string $file
226227

227228
public static function getPostData(string $key): mixed
228229
{
229-
try {
230-
return $_POST[$key];
231-
} catch (ArrayKeyException $e) {
232-
self::badRequest('failed to get $_POST data', $e, [
233-
'$_POST' => $_POST,
234-
]);
230+
if (!isset($_SERVER)) {
231+
throw new RuntimeException('$_SERVER is unset');
232+
}
233+
if (!array_key_exists("REQUEST_METHOD", $_SERVER)) {
234+
throw new RuntimeException('$_SERVER has no array key "REQUEST_METHOD"');
235+
}
236+
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
237+
self::badRequest('$_SERVER["REQUEST_METHOD"] != "POST"');
235238
}
239+
if (!isset($_POST)) {
240+
self::badRequest('$_POST is unset');
241+
}
242+
if (!array_key_exists($key, $_POST)) {
243+
self::badRequest("\$_POST has no array key '$key'");
244+
}
245+
return $_POST[$key];
236246
}
237247

238248
public static function getUploadedFileContents(
@@ -325,6 +335,43 @@ public static function getMessages()
325335

326336
public static function clearMessages()
327337
{
338+
self::ensureSessionMessagesSanity();
328339
$_SESSION["messages"] = [];
329340
}
341+
342+
private static function getMessageIndex(
343+
UnityHTTPDMessageLevel $level,
344+
string $title,
345+
string $body,
346+
) {
347+
$messages = self::getMessages();
348+
$error_msg = sprintf(
349+
"message(level='%s' title='%s' body='%s'), not found. found messages: %s",
350+
$level->value,
351+
$title,
352+
$body,
353+
jsonEncode($messages),
354+
);
355+
foreach ($messages as $i => $message) {
356+
if ($title == $message[0] && $body == $message[1] && $level == $message[2]) {
357+
return $i;
358+
}
359+
}
360+
throw new UnityHTTPDMessageNotFoundException($error_msg);
361+
}
362+
363+
/* returns the 1st message that matches or throws UnityHTTPDMessageNotFoundException */
364+
public static function getMessage(UnityHTTPDMessageLevel $level, string $title, string $body)
365+
{
366+
$index = self::getMessageIndex($level, $title, $body);
367+
return $_SESSION["messages"][$index];
368+
}
369+
370+
/* deletes the 1st message that matches or throws UnityHTTPDMessageNotFoundException */
371+
public static function deleteMessage(UnityHTTPDMessageLevel $level, string $title, string $body)
372+
{
373+
$index = self::getMessageIndex($level, $title, $body);
374+
unset($_SESSION["messages"][$index]);
375+
$_SESSION["messages"] = array_values($_SESSION["messages"]);
376+
}
330377
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
namespace UnityWebPortal\lib\exceptions;
4+
5+
class UnityHTTPDMessageNotFoundException extends \Exception {}

resources/templates/header.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,32 @@
147147
<div class='message %s'>
148148
<h3>%s</h3>
149149
<p>%s</p>
150-
<button onclick=\"this.parentElement.style.display='none';\">×</button>
150+
<button
151+
onclick=\"
152+
this.parentElement.style.display='none';
153+
$.ajax({
154+
url: '/panel/ajax/delete_message.php',
155+
method: 'POST',
156+
data: {
157+
'level': '%s',
158+
'title': '%s',
159+
'body': '%s',
160+
}
161+
});
162+
\"
163+
>
164+
×
165+
</button>
151166
</div>
152167
",
153168
htmlspecialchars($level->value),
154169
htmlspecialchars($title),
155-
htmlspecialchars($body)
170+
htmlspecialchars($body),
171+
htmlspecialchars($level->value),
172+
htmlspecialchars($title),
173+
htmlspecialchars($body),
156174
);
157175
}
158-
UnityHTTPD::clearMessages();
159176
if (
160177
isset($_SESSION["is_admin"])
161178
&& $_SESSION["is_admin"]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
use PHPUnit\Framework\TestCase;
4+
use UnityWebPortal\lib\UnityHTTPD;
5+
use UnityWebPortal\lib\UnityHTTPDMessageLevel;
6+
7+
class DeleteMessageTest extends TestCase
8+
{
9+
public function testDeleteMessage(): void
10+
{
11+
switchUser(...getBlankUser());
12+
$initial = UnityHTTPD::getMessages();
13+
$this->assertEmpty($initial);
14+
UnityHTTPD::messageDebug("foo1", "bar1");
15+
UnityHTTPD::messageDebug("foo2", "bar2");
16+
UnityHTTPD::messageDebug("foo3", "bar3");
17+
UnityHTTPD::messageError("foo", "bar");
18+
UnityHTTPD::messageInfo("foo", "bar");
19+
UnityHTTPD::messageSuccess("foo", "bar");
20+
UnityHTTPD::messageWarning("foo", "bar");
21+
try {
22+
$before = array_map("jsonEncode", UnityHTTPD::getMessages());
23+
http_post(
24+
__DIR__ . "/../../webroot/panel/ajax/delete_message.php",
25+
[
26+
"level" => "debug",
27+
"title" => "foo2",
28+
"body" => "bar2",
29+
],
30+
enforce_PRG: false,
31+
);
32+
$after = array_map("jsonEncode", UnityHTTPD::getMessages());
33+
$difference = array_diff($before, $after);
34+
$message_expected_removed = ["foo2", "bar2", UnityHTTPDMessageLevel::DEBUG];
35+
$this->assertEqualsCanonicalizing([jsonEncode($message_expected_removed)], $difference);
36+
} finally {
37+
UnityHTTPD::clearMessages();
38+
}
39+
}
40+
}

test/phpunit-bootstrap.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
require_once __DIR__ . "/../resources/lib/exceptions/EnsureException.php";
2424
require_once __DIR__ . "/../resources/lib/exceptions/EncodingUnknownException.php";
2525
require_once __DIR__ . "/../resources/lib/exceptions/EncodingConversionException.php";
26+
require_once __DIR__ . "/../resources/lib/exceptions/UnityHTTPDMessageNotFoundException.php";
2627

2728
use UnityWebPortal\lib\UnityGroup;
2829
use UnityWebPortal\lib\UnityHTTPD;
@@ -96,7 +97,7 @@ function switchUser(
9697
ensure(!is_null($USER));
9798
}
9899

99-
function http_post(string $phpfile, array $post_data): void
100+
function http_post(string $phpfile, array $post_data, bool $enforce_PRG = true): void
100101
{
101102
global $LDAP,
102103
$SQL,
@@ -126,8 +127,10 @@ function http_post(string $phpfile, array $post_data): void
126127
unset($_POST);
127128
$_SERVER = $_PREVIOUS_SERVER;
128129
}
129-
// https://en.wikipedia.org/wiki/Post/Redirect/Get
130-
ensure($post_did_redirect_or_die, "post did not redirect or die!");
130+
if ($enforce_PRG) {
131+
// https://en.wikipedia.org/wiki/Post/Redirect/Get
132+
ensure($post_did_redirect_or_die, "post did not redirect or die!");
133+
}
131134
}
132135

133136
function http_get(string $phpfile, array $get_data = []): void
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
require_once __DIR__ . "/../../../resources/autoload.php";
4+
5+
use UnityWebPortal\lib\UnityHTTPD;
6+
use UnityWebPortal\lib\UnityHTTPDMessageLevel;
7+
8+
$level_str = UnityHTTPD::getPostData("level");
9+
$level = UnityHTTPDMessageLevel::from($level_str);
10+
$title = UnityHTTPD::getPostData("title");
11+
$body = UnityHTTPD::getPostData("body");
12+
UnityHTTPD::deleteMessage($level, $title, $body);

0 commit comments

Comments
 (0)