-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrl.php
More file actions
113 lines (91 loc) · 3.12 KB
/
rl.php
File metadata and controls
113 lines (91 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<?php
/**
* @file
* Handles RL experiment tracking via AJAX with minimal bootstrap.
*
* Following the statistics.php architecture for optimal performance.
* Updated for Drupal 10/11 compatibility.
*/
use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpFoundation\Request;
$action = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$experiment_id = filter_input(INPUT_POST, 'experiment_id', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$arm_id = filter_input(INPUT_POST, 'arm_id', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
// Ping action is read-only and doesn't require experiment_id.
if ($action === 'ping') {
http_response_code(200);
exit('pong');
}
if (!$action || !$experiment_id || !in_array($action, ['turn', 'turns', 'reward'])) {
http_response_code(400);
exit('Invalid request parameters');
}
// Validate experiment ID format (alphanumeric, hyphens, underscores).
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $experiment_id)) {
http_response_code(400);
exit('Invalid experiment_id format');
}
try {
$levels_up = '../../../';
chdir($levels_up);
$drupal_root = getcwd();
$autoload_path = $drupal_root . '/../vendor/autoload.php';
if (!file_exists($autoload_path)) {
$script_filename = $_SERVER['SCRIPT_FILENAME'] ?? '';
if (!preg_match('/^[a-zA-Z0-9\/_.-]+$/', $script_filename)) {
http_response_code(500);
exit('Invalid script filename');
}
$drupal_root = dirname(dirname(dirname(dirname($script_filename))));
$autoload_path = $drupal_root . '/../vendor/autoload.php';
if (!file_exists($autoload_path)) {
http_response_code(500);
exit('Drupal autoload.php not found');
}
}
$autoloader = require_once $autoload_path;
$request = Request::createFromGlobals();
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');
$kernel->boot();
$container = $kernel->getContainer();
$registry = $container->get('rl.experiment_registry');
if (!$registry->isRegistered($experiment_id)) {
exit();
}
$storage = $container->get('rl.experiment_data_storage');
switch ($action) {
case 'turn':
if ($arm_id && preg_match('/^[a-zA-Z0-9_-]+$/', $arm_id)) {
$storage->recordTurn($experiment_id, $arm_id);
}
break;
case 'turns':
$arm_ids = filter_input(INPUT_POST, 'arm_ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if ($arm_ids) {
$arm_ids_array = explode(',', $arm_ids);
$arm_ids_array = array_map('trim', $arm_ids_array);
$valid_arm_ids = [];
foreach ($arm_ids_array as $aid) {
if (preg_match('/^[a-zA-Z0-9_-]+$/', $aid)) {
$valid_arm_ids[] = $aid;
}
}
if (!empty($valid_arm_ids)) {
$storage->recordTurns($experiment_id, $valid_arm_ids);
}
}
break;
case 'reward':
if ($arm_id && preg_match('/^[a-zA-Z0-9_-]+$/', $arm_id)) {
$storage->recordReward($experiment_id, $arm_id);
}
break;
}
http_response_code(200);
}
catch (\Exception $e) {
// Log error and return 500.
error_log('RL endpoint error: ' . $e->getMessage());
http_response_code(500);
exit('Server error');
}