SearchUpdateProcessor::commitIndex()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\FullTextSearch\Search\Processors;
4
5
use SilverStripe\FullTextSearch\Search\Services\IndexableService;
6
use SilverStripe\ORM\DataObject;
7
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
8
use SilverStripe\FullTextSearch\Search\FullTextSearch;
9
10
abstract class SearchUpdateProcessor
11
{
12
    /**
13
     * List of dirty records to process in format
14
     *
15
     * array(
16
     *   '$BaseClass' => array(
17
     *     '$State Key' => array(
18
     *       'state' => array(
19
     *         'key1' => 'value',
20
     *         'key2' => 'value'
21
     *       ),
22
     *       'ids' => array(
23
     *         '*id*' => array(
24
     *           '*Index Name 1*',
25
     *           '*Index Name 2*'
26
     *         )
27
     *       )
28
     *     )
29
     *   )
30
     * )
31
     *
32
     * @var array
33
     */
34
    protected $dirty;
35
36
    public function __construct()
37
    {
38
        $this->dirty = array();
39
    }
40
41
    public function addDirtyIDs($class, $statefulids, $index)
42
    {
43
        $base = DataObject::getSchema()->baseDataClass($class);
44
        $forclass = isset($this->dirty[$base]) ? $this->dirty[$base] : array();
45
46
        foreach ($statefulids as $statefulid) {
47
            $id = $statefulid['id'];
48
            $state = $statefulid['state'];
49
            $statekey = serialize($state);
50
51
            if (!isset($forclass[$statekey])) {
52
                $forclass[$statekey] = array('state' => $state, 'ids' => array($id => array($index)));
53
            } elseif (!isset($forclass[$statekey]['ids'][$id])) {
54
                $forclass[$statekey]['ids'][$id] = array($index);
55
            } elseif (array_search($index, $forclass[$statekey]['ids'][$id]) === false) {
56
                $forclass[$statekey]['ids'][$id][] = $index;
57
                // dirty count stays the same
58
            }
59
        }
60
61
        $this->dirty[$base] = $forclass;
62
    }
63
64
    /**
65
     * Generates the list of indexes to process for the dirty items
66
     *
67
     * @return array
68
     */
69
    protected function prepareIndexes()
70
    {
71
        $originalState = SearchVariant::current_state();
72
        $dirtyIndexes = array();
73
        $dirty = $this->getSource();
74
        $indexes = FullTextSearch::get_indexes();
75
        $indexableService = IndexableService::singleton();
76
        foreach ($dirty as $base => $statefulids) {
77
            if (!$statefulids) {
78
                continue;
79
            }
80
81
            foreach ($statefulids as $statefulid) {
82
                $state = $statefulid['state'];
83
                $ids = $statefulid['ids'];
84
85
                SearchVariant::activate_state($state);
86
87
                // Ensure that indexes for all new / updated objects are included
88
                $objs = DataObject::get($base)->byIDs(array_keys($ids));
89
                foreach ($objs as $obj) {
90
                    foreach ($ids[$obj->ID] as $index) {
91
                        if (!$indexes[$index]->variantStateExcluded($state)) {
92
                            // Remove any existing records from index if ShowInSearch is changed to false
93
                            if (!$indexableService->isIndexable($obj)) {
94
                                $indexes[$index]->delete($base, $obj->ID, $state);
95
                            } else {
96
                                $indexes[$index]->add($obj);
97
                            }
98
                            $dirtyIndexes[$index] = $indexes[$index];
99
                        }
100
                    }
101
                    unset($ids[$obj->ID]);
102
                }
103
104
                // Generate list of records that do not exist and should be removed
105
                foreach ($ids as $id => $fromindexes) {
106
                    foreach ($fromindexes as $index) {
107
                        if (!$indexes[$index]->variantStateExcluded($state)) {
108
                            $indexes[$index]->delete($base, $id, $state);
109
                            $dirtyIndexes[$index] = $indexes[$index];
110
                        }
111
                    }
112
                }
113
            }
114
        }
115
116
        SearchVariant::activate_state($originalState);
117
        return $dirtyIndexes;
118
    }
119
120
    /**
121
     * Commits the specified index to the Solr service
122
     *
123
     * @param SolrIndex $index Index object
0 ignored issues
show
Bug introduced by
The type SilverStripe\FullTextSea...ch\Processors\SolrIndex was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
124
     * @return bool Flag indicating success
125
     */
126
    protected function commitIndex($index)
127
    {
128
        return $index->commit() !== false;
129
    }
130
131
    /**
132
     * Gets the record data source to process
133
     *
134
     * @return array
135
     */
136
    protected function getSource()
137
    {
138
        return $this->dirty;
139
    }
140
141
    /**
142
     * Process all indexes, returning true if successful
143
     *
144
     * @return bool Flag indicating success
145
     */
146
    public function process()
147
    {
148
        // Generate and commit all instances
149
        $indexes = $this->prepareIndexes();
150
        foreach ($indexes as $index) {
151
            if (!$this->commitIndex($index)) {
152
                return false;
153
            }
154
        }
155
        return true;
156
    }
157
158
    abstract public function triggerProcessing();
159
}
160