/
Hook.php
110 lines (95 loc) · 3.75 KB
/
Hook.php
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
<?php
// ensure this extension isn't being accessed directly
if (!defined( 'MEDIAWIKI')) {
echo("This is an extension to the MediaWiki package and cannot be run standalone.\n");
die(-1);
}
/* ---------- settings ---------- */
// allow SysOp users to view all content regardless of whether they're mentioned in the group parameter?
$sysop_override = true;
// error message if no group parameter is specified in the <RoleContent>
$error_msg = 'Group parameter not specified.';
/* ---------- /settings ---------- */
// set MediaWiki settings and hooks
$wgExtensionCredits['parserhook'][] = array(
"path" => __FILE__,
"name" => "Role-Based Content",
"version" => "1.0.1",
"author" => "Patrick Mehlbaum",
"url" => "https://patrickm.xyz",
"description" => "This extension allows you to restrict page content based on a user's role."
);
$wgHooks["ParserFirstCallInit"][] = "onParserFirstCallInit";
$wgHooks["OutputPageBeforeHTML"][] = "onOutputPageBeforeHTML";
// disable caching so that users only see what they're supposed to and not what the last person saw
$wgParserCacheType = CACHE_NONE;
$wgCachePages = false;
function onParserFirstCallInit($parser) {
// set the parser to watch for <RoleContent> blocks, and call renderRoleContent() as a callback
$parser->setHook("RoleContent", "renderRoleContent");
}
function onOutputPageBeforeHTML(OutputPage $out, &$text) {
// add our custom JS script
// https://doc.wikimedia.org/mediawiki-core/master/php/classOutputPage.html#a17767a6aa7eb32cc60b29cf081b9adb2
$out->addScriptFile('./extensions/RoleBasedContent/rbc.js');
}
function renderRoleContent($block, array $args, Parser $parser, PPFrame $frame) {
/* Just a quick run-down of what this all does!
* (in case you need to edit something!)
*
* @param string $block what is inside of the <RoleContent> block
* @param array $args the XML-style parameters passed with the block (assoc. array)
*/
// get the <RoleContent> group parameter, escape html, and check validity
$group = strtolower(htmlspecialchars($args["group"] ?? null, ENT_QUOTES));
if (is_null($group) || empty($group)) {
return '<strong><span style="color: red">' . $error_msg . '</span></strong>';
}
/* API parameters sourced from
* https://www.mediawiki.org/wiki/API:Userinfo#Example
*
* execute an API query to find the current user's groups
*/
$api_params = array(
"action" => "query",
"meta" => "userinfo",
"uiprop" => "groups",
"format" => "json"
);
$api_response = handleAPIRequest($api_params);
// check if viewer is logged in, return nothing if they're not
if (empty($api_response["query"]["userinfo"]["id"])) {
return true;
}
// array with a list of user's groups
$groups = $api_response["query"]["userinfo"]["groups"];
// should we show the content?
$show = false;
// check if user is SysOp
if (in_array("sysop", $groups) && $sysop_override) { $show = true; }
// check if user is in specified group
else if (in_array($group, $groups)) { $show = true; }
// check if the group specified contains an array of allowed groups
else if (strpos($group, ",") !== false) {
// get the allowed groups as an array
$allowed_groups = explode($group, ",");
// go through each allowed group
foreach ($allowed_group as $allowed_group) {
if (in_array(trim($allowed_group), $groups)) { $show = true; }
}
}
// if $show is true, show them the content along with the <br> removal tag
return ($show) ? '<!--RBC:REMOVE-->' . $block : true;
}
function handleAPIRequest(array $param) : array {
global $wgRequest;
/* PHP internal API request sourced from
* https://www.mediawiki.org/wiki/API:Calling_internally#From_application_code
* returns an array
*/
$api = new ApiMain(
new DerivativeRequest($wgRequest, $param)
);
$api->execute();
return $api->getResult()->getResultData();
}