Passed
Push — hans/valid-classes ( 1110df...3598c3 )
by Simon
11:18
created

SolrConfigureTask::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
4
namespace Firesphere\SolrSearch\Tasks;
5
6
use Exception;
7
use Firesphere\SolrSearch\Helpers\SolrLogger;
8
use Firesphere\SolrSearch\Indexes\BaseIndex;
9
use Firesphere\SolrSearch\Interfaces\ConfigStore;
10
use Firesphere\SolrSearch\Services\SolrCoreService;
11
use Firesphere\SolrSearch\Stores\FileConfigStore;
12
use Firesphere\SolrSearch\Stores\PostConfigStore;
13
use Firesphere\SolrSearch\Traits\LoggerTrait;
14
use GuzzleHttp\Exception\GuzzleException;
15
use ReflectionException;
16
use RuntimeException;
17
use SilverStripe\Control\HTTPRequest;
18
use SilverStripe\Core\Injector\Injector;
19
use SilverStripe\Dev\BuildTask;
20
use SilverStripe\ORM\ValidationException;
21
22
/**
23
 * Class SolrConfigureTask
24
 *
25
 * @package Firesphere\SolrSearch\Tasks
26
 */
27
class SolrConfigureTask extends BuildTask
28
{
29
    use LoggerTrait;
30
31
    /**
32
     * @var array Available stores
33
     */
34
    protected static $storeModes = [
35
        'file' => FileConfigStore::class,
36
        'post' => PostConfigStore::class,
37
//        'webdav' => WebdavConfigStore::class,
38
    ];
39
    /**
40
     * @var string URLSegment
41
     */
42
    private static $segment = 'SolrConfigureTask';
43
    /**
44
     * @var string Title
45
     */
46
    protected $title = 'Configure Solr cores';
47
    /**
48
     * @var string Description
49
     */
50
    protected $description = 'Create or reload a Solr Core by adding or reloading a configuration.';
51
52
    /**
53
     * SolrConfigureTask constructor.
54
     */
55 33
    public function __construct()
56
    {
57 33
        parent::__construct();
58 33
    }
59
60
    /**
61
     * Implement this method in the task subclass to
62
     * execute via the TaskRunner
63
     *
64
     * @param HTTPRequest $request
65
     * @return bool|Exception
66
     * @throws ReflectionException
67
     * @throws ValidationException
68
     * @throws GuzzleException
69
     */
70 32
    public function run($request)
71
    {
72 32
        $this->extend('onBeforeSolrConfigureTask', $request);
73
74 32
        $indexes = (new SolrCoreService())->getValidIndexes();
75
76 32
        foreach ($indexes as $index) {
77
            try {
78 32
                $this->configureIndex($index);
79
            } catch (Exception $error) {
80
                $this->getLogger()->error(sprintf('Core loading failed for %s', $index));
81
                $this->getLogger()->error($error); // in browser mode, it might not always show
82
                // Continue to the next index
83
                continue;
84
            }
85 32
            $this->extend('onAfterConfigureIndex', $index);
86
        }
87
88 32
        $this->extend('onAfterSolrConfigureTask');
89
        // Grab the latest logs
90 32
        $solrLogger = new SolrLogger();
91 32
        $solrLogger->saveSolrLog('Config');
92
93 32
        return true;
94
    }
95
96
    /**
97
     * Update the index on the given store
98
     *
99
     * @param string $index
100
     * @throws ValidationException
101
     * @throws GuzzleException
102
     */
103 32
    protected function configureIndex($index): void
104
    {
105
        /** @var BaseIndex $instance */
106 32
        $instance = Injector::inst()->get($index, false);
107
108 32
        $index = $instance->getIndexName();
109
110
        // Then tell Solr to use those config files
111
        /** @var SolrCoreService $service */
112 32
        $service = Injector::inst()->get(SolrCoreService::class);
113
114
        // Assuming a core that doesn't exist doesn't have uptime, as per Solr docs
115
        // And it has a start time.
116
        // You'd have to be pretty darn fast to hit 0 uptime and 0 starttime for an existing core!
117 32
        $status = $service->coreStatus($index);
118 32
        $configStore = $this->createConfigForIndex($instance);
119
        // Default to create
120 32
        $method = 'coreCreate';
121
        // Switch to reload if the core is loaded
122 32
        if ($status && ($status->getUptime() && $status->getStartTime() !== null)) {
123 32
            $method = 'coreReload';
124
        }
125
        try {
126 32
            $service->$method($index, $configStore);
127 32
            $this->getLogger()->info(sprintf('Core %s successfully loaded', $index));
128
        } catch (Exception $error) {
129
            $this->logException($index, $error);
130
            throw new RuntimeException($error);
131
        }
132 32
    }
133
134
    /**
135
     * Get the config and load it to Solr
136
     *
137
     * @param BaseIndex $instance
138
     * @return ConfigStore
139
     */
140 32
    protected function createConfigForIndex(BaseIndex $instance): ConfigStore
141
    {
142 32
        $storeConfig = SolrCoreService::config()->get('store');
143 32
        $configStore = $this->getStore($storeConfig);
144 32
        $instance->uploadConfig($configStore);
145
146 32
        return $configStore;
147
    }
148
149
    /**
150
     * Get the store for the given config
151
     *
152
     * @param $storeConfig
153
     * @return ConfigStore
154
     */
155 32
    protected function getStore($storeConfig): ConfigStore
156
    {
157 32
        $store = static::$storeModes[$storeConfig['mode']];
158 32
        $configStore = Injector::inst()->create($store, $storeConfig);
159
160
        // Allow changing the configStore if it needs to change to a different store
161 32
        $this->extend('onBeforeConfig', $configStore, $storeConfig);
162
163 32
        return $configStore;
164
    }
165
166
    /**
167
     * Log an exception error
168
     *
169
     * @param $index
170
     * @param Exception $error
171
     * @throws GuzzleException
172
     * @throws ValidationException
173
     */
174
    private function logException($index, Exception $error): void
175
    {
176
        $this->getLogger()->error($error);
177
        $msg = sprintf(
178
            'Error loading core %s,' . PHP_EOL .
179
            'Please log in to the CMS to find out more about Configuration errors' . PHP_EOL,
180
            $index
181
        );
182
        SolrLogger::logMessage('ERROR', $msg, $index);
183
    }
184
}
185