-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCustomDependSelects.module
More file actions
141 lines (125 loc) · 5.08 KB
/
CustomDependSelects.module
File metadata and controls
141 lines (125 loc) · 5.08 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
<?php
namespace ProcessWire;
class CustomDependSelects extends WireData implements Module {
/**
* @inheritDoc
*/
public function className($options = null) {
return 'CustomDependSelects';
}
public static function getModuleinfo() {
return [
'permanent' => false, // true if module is permanent and thus not uninstallable (3rd party modules should specify 'false')
'title' => 'CustomDependSelects',
'summary' => 'Add features to dependent selects. PW v3.0.203 recommended.',
'comments' => 'Use custom selectors in page field selector: check_access=role1|role2 ... to control who can see results, field=item.id to select on id of current repeater item',
'author' => 'Mark Evens',
'version' => "0.0.3",
'autoload' => true,
'singular' => true,
'icon' => 'level-down',
'requires' => ['ProcessWire>=3.0.200'],
];
}
/**
* Construct
* Set default values for configuration settings
*/
public function __construct() {
}
/**
* Initialize the module
*
* ProcessWire calls this method when the module is loaded. At this stage, all
* module configuration values have been populated.
*
* For “autoload” modules (such as this one), this will be called before ProcessWire’s API is ready.
* This is a good place to attach hooks (as is the “ready” method).
*
*/
public function init() {
}
/**
* Called when ProcessWire’s API is ready (optional)
*
* This optional method is similar to that of init() except that it is called
* after the current $page has been determined and the API is fully ready to use.
* Use this method instead of (or in addition to) the init() method if your
* initialization requires that the `$page` API variable is available.
*
* @throws WireException
*
*/
public function ready() {
/**
* This hook permits the use of [item.id] as a selector value in a page selector (i.e. selector string specified in page field input config)
* It is principally intended for use in the blendFrom field to add the test blendTo=0|[item.id] so that only blendTo items which have not been allocated to OTHER blendFroms are shown
* However, it's use has not been restricted to that field - this might be slightly inefficient, but more flexible
*/
$this->wire()->addHookBefore('InputfieldPage::getSelectablePages', function($event) {
if($this->wire()->session->get('dbMigrate_installPages')) return;
$inputfield = $event->object;
$page = $inputfield->hasPage;
$selector = $inputfield->getSetting('findPagesSelector');
$selector = str_replace('[item.id]', $page->id, $selector);
$selector = $this->checkAccess($selector, 'check_access');
//bd($selector, 'new selector from getSelectablePages before hook');
$inputfield->findPagesSelector($selector);
});
/**
* ProcessPageSearch deletes the check_access=0 if user is not superuser. 'id!=' is used to carry the term and needs to be replaced
* (see notes in checkAccess() below)
*/
$this->wire()->addHookAfter('ProcessPageSearch::findReady', function(HookEvent $event) {
$selector = $event->return;
//bd($selector, 'processed selector in ProcessPageSearch hook');
$selector = $this->checkAccess($selector, 'id!');
//bd($selector, 'revised selector in ProcessPageSearch hook');
$event->return = $selector;
});
/**
* We also need to fix the selector when the page field is saved, otherwise PW will throw errors
*/
$this->wire()->addHookBefore('Fieldtype::savePageField', function($event) {
//bd($event->arguments, 'args for savePageFieldHook');
$page = $event->arguments[0];
$pageField = $event->arguments[1];
$selector = $pageField->get('findPagesSelector');
//bd($selector, 'selector');
$selector = str_replace('[item.id]', $page->id, $selector);
$event->arguments[1]->set('findPagesSelector', $this->checkAccess($selector, 'check_access'));
});
}
private function checkAccess($selector, $term) {
if(strpos($selector, "$term=") !== false) {
$re = "/$term=([\w|\|]*)\b/m";
preg_match_all($re, $selector, $matches, PREG_SET_ORDER, 0);
//bd($selector, 'match selector');
//bd($matches, 'matches');
$selTerm = $matches[0][0];
$selVal = $matches[0][1];
if($selVal != 0) { // s/b custom check_access selector of form check_access=role|role1...]
$user = $this->wire()->users->getCurrentUser();
if($user->isSuperuser()) {
if($term == 'check_access') $selector = str_replace($selTerm, 'check_access=0', $selector);
} else {
$roles = explode('|', $selVal);
$pass = false;
foreach($roles as $role) {
if($user->hasRole($role)) {
$pass = true;
break;
}
}
if($pass) {
$selector = str_replace($selTerm, 'check_access=0', $selector);
if($term == 'check_access') $selector = 'id!=' . $selVal . ', ' . $selector;
// Make id!= the first selector term so that it is the one caught by subsequent matching - in case there is another such term
// If the term is not added and there is a (regular) id!= term then it should not matter because it will have integer values, not matching roles
}
}
}
}
return $selector;
}
}