Passed
Push — sheepy/introspection ( 9a33c8...7d1300 )
by Marco
05:54
created

SolrConfigureTask   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Importance

Changes 11
Bugs 1 Features 0
Metric Value
wmc 16
eloc 49
c 11
b 1
f 0
dl 0
loc 150
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getLoggerFactory() 0 3 1
A getStore() 0 17 3
A getLogger() 0 3 1
A setLogger() 0 3 1
A createConfigForIndex() 0 7 1
A configureIndex() 0 29 5
A run() 0 22 3
1
<?php
2
3
4
namespace Firesphere\SolrSearch\Tasks;
5
6
use Exception;
7
use Firesphere\SolrSearch\Indexes\BaseIndex;
8
use Firesphere\SolrSearch\Interfaces\ConfigStore;
9
use Firesphere\SolrSearch\Services\SolrCoreService;
10
use Firesphere\SolrSearch\Stores\FileConfigStore;
11
use Firesphere\SolrSearch\Stores\PostConfigStore;
12
use GuzzleHttp\Exception\RequestException;
13
use Psr\Log\LoggerInterface;
14
use ReflectionException;
15
use RuntimeException;
16
use SilverStripe\Control\HTTPRequest;
17
use SilverStripe\Core\Injector\Injector;
18
use SilverStripe\Dev\BuildTask;
19
20
class SolrConfigureTask extends BuildTask
21
{
22
    private static $segment = 'SolrConfigureTask';
23
24
    protected $title = 'Configure Solr cores';
25
26
    protected $description = 'Create or reload a Solr Core by adding or reloading a configuration.';
27
28
    /**
29
     * @var LoggerInterface
30
     */
31
    protected $logger;
32
33
    public function __construct()
34
    {
35
        parent::__construct();
36
        $this->setLogger($this->getLoggerFactory());
37
    }
38
39
    /**
40
     * @return LoggerInterface log channel
41
     */
42
    protected function getLoggerFactory(): LoggerInterface
43
    {
44
        return Injector::inst()->get(LoggerInterface::class);
45
    }
46
47
    /**
48
     * Implement this method in the task subclass to
49
     * execute via the TaskRunner
50
     *
51
     * @param HTTPRequest $request
52
     * @return bool|Exception
53
     * @throws ReflectionException
54
     */
55
    public function run($request)
56
    {
57
        $this->extend('onBeforeSolrConfigureTask', $request);
58
59
        $indexes = (new SolrCoreService())->getValidIndexes();
60
61
        foreach ($indexes as $index) {
62
            try {
63
                $this->configureIndex($index);
64
                $this->extend('onAfterSolrConfigureTask', $request);
65
            } catch (RequestException $e) {
66
                $this->logger->error($e->getResponse()->getBody()->getContents());
67
                $this->logger->error(sprintf('Core loading failed for %s', $index));
68
                // Continue to the next index
69
                continue;
70
            }
71
            $this->extend('onAfterConfigureIndex', $index);
72
        }
73
74
        $this->extend('onAfterSolrConfigureTask');
75
76
        return true;
77
    }
78
79
    /**
80
     * Update the index on the given store
81
     *
82
     * @param string $index
83
     */
84
    protected function configureIndex($index): void
85
    {
86
        /** @var BaseIndex $instance */
87
        $instance = Injector::inst()->get($index);
88
89
        $index = $instance->getIndexName();
90
91
        // Then tell Solr to use those config files
92
        /** @var SolrCoreService $service */
93
        $service = Injector::inst()->get(SolrCoreService::class);
94
95
        // Assuming a core that doesn't exist doesn't have uptime, as per Solr docs
96
        // And it has a start time.
97
        // You'd have to be pretty darn fast to hit 0 uptime and 0 starttime for an existing core!
98
        $status = $service->coreStatus($index);
99
        $configStore = $this->createConfigForIndex($instance);
100
        // Default to create
101
        $method = 'coreCreate';
102
        $message = 'created';
103
        // Switch to reload if the core is loaded
104
        if ($status && ($status->getUptime() && $status->getStartTime() !== null)) {
105
            $method = 'coreReload';
106
            $message = 'reloaded';
107
        }
108
        try {
109
            $service->$method($index, $configStore);
110
            $this->logger->info(sprintf('Core %s successfully %s', $index, $message));
111
        } catch (RequestException $e) {
112
            throw new RuntimeException($e);
113
        }
114
    }
115
116
    /**
117
     * @param BaseIndex $instance
118
     * @return ConfigStore
119
     */
120
    protected function createConfigForIndex(BaseIndex $instance): ConfigStore
121
    {
122
        $storeConfig = SolrCoreService::config()->get('store');
123
        $configStore = $this->getStore($storeConfig);
124
        $instance->uploadConfig($configStore);
125
126
        return $configStore;
127
    }
128
129
    /**
130
     * @param $storeConfig
131
     * @return ConfigStore
132
     */
133
    protected function getStore($storeConfig): ConfigStore
134
    {
135
        $configStore = null;
136
137
        /** @var ConfigStore $configStore */
138
        if ($storeConfig['mode'] === 'post') {
139
            $configStore = Injector::inst()->create(PostConfigStore::class, $storeConfig);
140
        } elseif ($storeConfig['mode'] === 'file') {
141
            $configStore = Injector::inst()->create(FileConfigStore::class, $storeConfig);
142
        }// elseif ($storeConfig['mode'] === 'webdav') {
143
        // @todo Add webdav store
144
        //}
145
146
        // Allow changing the configStore if it needs to change to a different store
147
        $this->extend('onBeforeConfig', $configStore, $storeConfig);
148
149
        return $configStore;
150
    }
151
152
    /**
153
     * Get the monolog logger
154
     *
155
     * @return LoggerInterface
156
     */
157
    public function getLogger(): LoggerInterface
158
    {
159
        return $this->logger;
160
    }
161
162
    /**
163
     * Assign a new logger
164
     *
165
     * @param LoggerInterface $logger
166
     */
167
    public function setLogger(LoggerInterface $logger): void
168
    {
169
        $this->logger = $logger;
170
    }
171
}
172