Passed
Push — hans/Index-all-fluent-options ( 33af16...2afa88 )
by Simon
07:48
created

SolrConfigureTask   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Test Coverage

Coverage 71.43%

Importance

Changes 12
Bugs 0 Features 0
Metric Value
eloc 51
c 12
b 0
f 0
dl 0
loc 156
ccs 35
cts 49
cp 0.7143
rs 10
wmc 12

6 Methods

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