-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAddValidationTypes.php
More file actions
149 lines (130 loc) · 5.44 KB
/
AddValidationTypes.php
File metadata and controls
149 lines (130 loc) · 5.44 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?php
namespace UWMadison\AddValidationTypes;
use ExternalModules\AbstractExternalModule;
class AddValidationTypes extends AbstractExternalModule
{
private $inputRegex = [
"displayName" => "/^[a-zA-Z0-9 ()-:\/.]+$/",
"internalName" => "/^[a-z0-9_ ]+$/",
"phpRegex" => "", // Validated with preg_match
"jsRegex" => "" // Validated in js
];
public function redcap_control_center()
{
if ($this->isPage('ControlCenter/validation_type_setup.php')) {
$this->loadSettings();
echo "<style>#val_table { display:none; }</style>";
echo "<script src={$this->getUrl("main.js")}></script>";
}
}
public function redcap_module_ajax($action, $payload)
{
$result = ["errors" => ["No valid action"]];
if ($action == "add") {
$result = $this->addType($payload["display"], $payload["internal"], $payload["phpRegex"], $payload["jsRegex"], $payload["dataType"]);
} elseif ($action == "remove") {
$result = $this->removeType($payload["name"]);
}
return $result;
}
private function loadSettings()
{
$this->initializeJavascriptModuleObject();
$settings = json_encode([
"regex" => $this->inputRegex,
"emTypes" => $this->emValidationTypes(),
"validationTypes" => $this->allValidationTypes(),
"dataTypes" => $this->allDataTypes(),
"repo" => $this->getUrl("repo.php")
]);
echo "<script>{$this->getJavascriptModuleObjectName()}.settings = {$settings}</script>";
}
private function emValidationTypes()
{
return array_filter(array_map('trim', explode(",", $this->getSystemSetting('typesAdded'))));
}
private function allValidationTypes()
{
// Grab most data from the validation table and format
$result = [];
$sql = $this->query("SELECT * FROM redcap_validation_types", []);
while ($row = $sql->fetch_assoc()) {
// Skip pulling the regex, we won't use it
$result[$row["validation_name"]] = [
"internal" => $this->escape($row["validation_name"]),
"display" => $this->escape($row["validation_label"]),
"dataType" => $this->escape($row["data_type"]),
"visible" => $row["visible"] == 1
];
}
return $result;
}
private function allDataTypes()
{
// Fetch db metadata and parse the enum for data_type col
$sql = $this->query("SHOW COLUMNS FROM redcap_validation_types LIKE 'data_type'", []);
$enum = $sql->fetch_assoc()["Type"];
preg_match("/enum\((.*)\)$/", $enum, $matches);
return array_map(function ($value) {
return trim($value, "'");
}, explode(',', $matches[1]));
}
private function addType($display, $internal, $phpRegex, $jsRegex, $dataType)
{
$errors = [];
// Display Name (alpha, numeric, space, limited special chars ()-:/.)
if (!preg_match($this->inputRegex["displayName"], $display)) {
$errors[] = "Incorrectly formatted display name";
}
// Internal Name (lower alpha, undersocre, numeric)
if (!preg_match($this->inputRegex["internalName"], $internal)) {
$errors[] = "Incorrectly formatted internal name";
}
// PHP Regex validation
if (preg_match($phpRegex, '') === false) {
$errors[] = "Invalid PHP (PCRE) Regex submitted";
}
// Make sure that display name isn't in use
$allTypes = $this->allValidationTypes();
$displayNames = array_map(function ($key) use ($allTypes) {
return str_replace(" ", "", strtolower($allTypes[$key]["display"]));
}, array_keys($allTypes));
$trimDisplay = str_replace(" ", "", strtolower($display));
if (in_array($trimDisplay, $displayNames)) {
$errors[] = "Display name too similar to existing name";
}
// Make sure that internal name isn't in use
if (in_array($internal, array_keys($allTypes))) {
$errors[] = "Internal name is already in use";
}
// Make sure the data type is real
if (!in_array($dataType, $this->allDataTypes())) {
$errors[] = "Invalid data type";
}
// Perform the DB Update and update the EM's setting
if (count($errors) == 0) {
$this->query("
INSERT INTO redcap_validation_types (validation_name, validation_label, regex_js, regex_php, data_type, legacy_value, visible)
VALUES (?, ?, ?, ?, ?, NULL, 0)", [$internal, $display, $jsRegex, $phpRegex, $dataType]);
$types = $this->emValidationTypes();
$types[] = $internal;
$this->setSystemSetting("typesAdded", implode(",", $types));
}
return ["errors" => $errors];
}
private function removeType($name)
{
// We can remove only those types that we added
$types = $this->emValidationTypes();
if (!in_array($name, $types)) {
return ["errors" => ["Bad validation type or type was not added by EM"]];
}
// Perform delete
$this->query("
DELETE from redcap_validation_types
WHERE validation_name = ?", [$name]);
$types = array_diff($types, [$name]);
$this->setSystemSetting('typesAdded', implode(",", $types));
return ["errors" => []];
}
}