/
SearchVariantSubsites.php
139 lines (122 loc) · 5.14 KB
/
SearchVariantSubsites.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
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
<?php
class SearchVariantSubsites extends SearchVariant
{
public function appliesToEnvironment()
{
return class_exists('Subsite');
}
public function appliesTo($class, $includeSubclasses)
{
// Include all DataExtensions that contain a SubsiteID.
// TODO: refactor subsites to inherit a common interface, so we can run introspection once only.
return SearchIntrospection::has_extension($class, 'SiteTreeSubsites', $includeSubclasses) ||
SearchIntrospection::has_extension($class, 'GroupSubsites', $includeSubclasses) ||
SearchIntrospection::has_extension($class, 'FileSubsites', $includeSubclasses) ||
SearchIntrospection::has_extension($class, 'SiteConfigSubsites', $includeSubclasses);
}
public function currentState()
{
return (string)Subsite::currentSubsiteID();
}
public function reindexStates()
{
static $ids = null;
if ($ids === null) {
$ids = array('0');
foreach (DataObject::get('Subsite') as $subsite) {
$ids[] = (string)$subsite->ID;
}
}
return $ids;
}
public function activateState($state)
{
// We always just set the $_GET variable rather than store in Session - this always works, has highest priority
// in Subsite::currentSubsiteID() and doesn't persist unlike Subsite::changeSubsite
$_GET['SubsiteID'] = $state;
Permission::flush_permission_cache();
}
public function alterDefinition($class, $index)
{
$self = get_class($this);
// Add field to root
$this->addFilterField($index, '_subsite', array(
'name' => '_subsite',
'field' => '_subsite',
'fullfield' => '_subsite',
'base' => ClassInfo::baseDataClass($class),
'origin' => $class,
'type' => 'Int',
'lookup_chain' => array(array('call' => 'variant', 'variant' => $self, 'method' => 'currentState'))
));
}
/**
* This field has been altered to allow a user to obtain search results for a particular subsite
* When attempting to do this in project code, SearchVariantSubsites kicks and overwrites any filter you've applied
* This fix prevents the module from doing this if a filter is applied on the index or the query, or if a field is
* being excluded specifically before being executed.
*
* A pull request has been raised for this issue. Once accepted this forked module can be deleted and the parent
* project should be used instead.
*/
public function alterQuery($query, $index)
{
if ($this->isFieldFiltered('_subsite', $query)) {
return;
}
$subsite = Subsite::currentSubsiteID();
$query->filter('_subsite', array($subsite, SearchQuery::$missing));
}
/**
* We need _really_ complicated logic to find just the changed subsites (because we use versions there's no explicit
* deletes, just new versions with different members) so just always use all of them
*/
public function extractManipulationWriteState(&$writes)
{
$self = get_class($this);
$query = new SQLQuery('"ID"', '"Subsite"');
$subsites = array_merge(array('0'), $query->execute()->column());
foreach ($writes as $key => $write) {
$applies = $this->appliesTo($write['class'], true);
if (!$applies) {
continue;
}
if (isset($write['fields']['SiteTree:SubsiteID'])) {
$subsitesForWrite = array($write['fields']['SiteTree:SubsiteID']);
}
// files in subsite 0 should be in all subsites as they are global
elseif (isset($write['fields']['File:SubsiteID']) && intval($write['fields']['File:SubsiteID']) !== 0) {
$subsitesForWrite = array($write['fields']['File:SubsiteID']);
}
else {
$subsitesForWrite = $subsites;
}
$next = array();
foreach ($write['statefulids'] as $i => $statefulid) {
foreach ($subsitesForWrite as $subsiteID) {
$next[] = array(
'id' => $statefulid['id'],
'state' => array_merge(
$statefulid['state'],
array($self => (string)$subsiteID)
)
);
}
}
$writes[$key]['statefulids'] = $next;
}
}
/**
* Determine if a field with a certain name is filtered by the search query or on the index
* This is the equivalent of saying "show me the results that do ONLY contain this value"
* @param $field string name of the field being filtered
* @param $query SearchQuery currently being executed
* @param $index SearchIndex which specifies a filter field
* @return bool true if $field is being filtered, false if it is not being filtered
*/
protected function isFieldFiltered($field, $query)
{
$queryHasFilter = !empty($query->require[$field]);
return $queryHasFilter;
}
}