Passed
Push — master ( 5f60a5...391298 )
by Timo
24:49
created

AbstractModuleController::switchCoreAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 9
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 2
crap 2
1
<?php
2
namespace ApacheSolrForTypo3\Solr\Controller\Backend\Search;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2010-2017 dkd Internet Service GmbH <[email protected]>
8
 *  All rights reserved
9
 *
10
 *  This script is part of the TYPO3 project. The TYPO3 project is
11
 *  free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 3 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  The GNU General Public License can be found at
17
 *  http://www.gnu.org/copyleft/gpl.html.
18
 *
19
 *  This script is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  This copyright notice MUST APPEAR in all copies of the script!
25
 ***************************************************************/
26
27
use ApacheSolrForTypo3\Solr\ConnectionManager;
28
use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository;
29
use ApacheSolrForTypo3\Solr\Site;
30
use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection as SolrCoreConnection;
31
use ApacheSolrForTypo3\Solr\System\Mvc\Backend\Component\Exception\InvalidViewObjectNameException;
32
use ApacheSolrForTypo3\Solr\System\Mvc\Backend\Service\ModuleDataStorageService;
33
use TYPO3\CMS\Backend\Template\Components\Menu\Menu;
34
use TYPO3\CMS\Backend\Utility\BackendUtility;
35
use TYPO3\CMS\Backend\View\BackendTemplateView;
36
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
37
use TYPO3\CMS\Core\Messaging\AbstractMessage;
38
use TYPO3\CMS\Core\Utility\GeneralUtility;
39
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
40
use TYPO3\CMS\Extbase\Mvc\View\NotFoundView;
41
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
42
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
43
44
/**
45
 * Abstract Module
46
 *
47
 * @property BackendTemplateView $view
48
 */
49
abstract class AbstractModuleController extends ActionController
50
{
51
    /**
52
     * Backend Template Container
53
     *
54
     * @var string
55
     */
56
    protected $defaultViewObjectName = BackendTemplateView::class;
57
58
    /**
59
     * In the pagetree selected page UID
60
     *
61
     * @var int
62
     */
63
    protected $selectedPageUID;
64
65
    /**
66
     * Holds the requested page UID because the selected page uid,
67
     * might be overwritten by the automatic site selection.
68
     *
69
     * @var int
70
     */
71
    protected $requestedPageUID;
72
73
    /**
74
     * @var Site
75
     */
76
    protected $selectedSite;
77
78
    /**
79
     * @var SolrCoreConnection
80
     */
81
    protected $selectedSolrCoreConnection;
82
83
    /**
84
     * @var Menu
85
     */
86
    protected $coreSelectorMenu = null;
87
88
    /**
89
     * @var ConnectionManager
90
     */
91
    protected $solrConnectionManager = null;
92
93
    /**
94
     * @var ModuleDataStorageService
95
     */
96
    protected $moduleDataStorageService = null;
97
98
    /**
99
     * Initializes the controller and sets needed vars.
100
     */
101
    protected function initializeAction()
102
    {
103
        parent::initializeAction();
104
        $this->solrConnectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
105
        $this->moduleDataStorageService = GeneralUtility::makeInstance(ModuleDataStorageService::class);
106
107
        $this->selectedPageUID = (int)GeneralUtility::_GP('id');
108
        if ($this->request->hasArgument('id')) {
109
            $this->selectedPageUID = (int)$this->request->getArgument('id');
110
        }
111
112
        $this->requestedPageUID = $this->selectedPageUID;
113
114
        /* @var SiteRepository $siteRepository */
115
        $siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
116
117
        // Autoselect the only one available site
118
        if (count($siteRepository->getAvailableSites()) == 1) {
119
            $this->selectedSite = $siteRepository->getFirstAvailableSite();
120
            $this->selectedPageUID = $this->selectedSite->getRootPageId();
121
            return;
122
        }
123
124
        if ($this->selectedPageUID < 1) {
125
            return;
126
        }
127
128
        try {
129
            $this->selectedSite = $siteRepository->getSiteByPageId($this->selectedPageUID);
130
        } catch (\InvalidArgumentException $exception) {
131
            return;
132
        }
133
    }
134
135
    /**
136
     * Set up the doc header properly here
137
     *
138
     * @param ViewInterface $view
139
     * @return void
140
     */
141
    protected function initializeView(ViewInterface $view)
142
    {
143
        parent::initializeView($view);
144
        $this->view->assign('pageUID', $this->selectedPageUID);
145
        if ($view instanceof NotFoundView || $this->selectedPageUID < 1) {
146
            return;
147
        }
148
        $this->view->getModuleTemplate()->addJavaScriptCode('mainJsFunctions', '
149
                top.fsMod.recentIds["searchbackend"] = ' . (int)$this->selectedPageUID . ';'
150
        );
151
        if (null === $this->selectedSite) {
152
            return;
153
        }
154
155
        /* @var BackendUserAuthentication $beUser */
156
        $beUser = $GLOBALS['BE_USER'];
157
        $permissionClause = $beUser->getPagePermsClause(1);
158
        $pageRecord = BackendUtility::readPageAccess($this->selectedSite->getRootPageId(), $permissionClause);
159
160
        if (false === $pageRecord) {
161
            throw new \InvalidArgumentException(vsprintf('There is something wrong with permissions for page "%s" for backend user "%s".', [$this->selectedSite->getRootPageId(), $beUser->user['username']]), 1496146317);
162
        }
163
        $this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation($pageRecord);
164
    }
165
166
    /**
167
     * Generates selector menu in backends doc header using selected page from page tree.
168
     *
169
     * @param string|null $uriToRedirectTo
170
     */
171
    public function generateCoreSelectorMenuUsingPageTree(string $uriToRedirectTo = null)
172
    {
173
        if ($this->selectedPageUID < 1 || null === $this->selectedSite) {
174
            return;
175
        }
176
177
        if ($this->view instanceof NotFoundView) {
178
            $this->initializeSelectedSolrCoreConnection();
179
            return;
180
        }
181
182
        $this->generateCoreSelectorMenu($this->selectedSite, $uriToRedirectTo);
183
    }
184
185
    /**
186
     * Generates Core selector Menu for given Site.
187
     *
188
     * @param Site $site
189
     * @param string|null $uriToRedirectTo
190
     * @throws InvalidViewObjectNameException
191
     */
192
    protected function generateCoreSelectorMenu(Site $site, string $uriToRedirectTo = null)
193
    {
194
        if (!$this->view instanceof BackendTemplateView) {
195
            throw new InvalidViewObjectNameException(vsprintf(
196
                'The controller "%s" must use BackendTemplateView to be able to generate menu for backends docheader. \
197
                Please set `protected $defaultViewObjectName = BackendTemplateView::class;` field in your controller.',
198
                [static::class]), 1493804179);
199
        }
200
        $this->view->getModuleTemplate()->setFlashMessageQueue($this->controllerContext->getFlashMessageQueue());
201
202
        $this->coreSelectorMenu = $this->view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
203
        $this->coreSelectorMenu->setIdentifier('component_core_selector_menu');
204
205
        if (!isset($uriToRedirectTo)) {
206
            $uriToRedirectTo = $this->uriBuilder->reset()->uriFor();
207
        }
208
209
        $this->initializeSelectedSolrCoreConnection();
210
        $cores = $this->solrConnectionManager->getConnectionsBySite($site);
211
        foreach ($cores as $core) {
212
            $coreAdmin = $core->getAdminService();
213
            $menuItem = $this->coreSelectorMenu->makeMenuItem();
214
            $menuItem->setTitle($coreAdmin->getPath());
215
            $uri = $this->uriBuilder->reset()->uriFor('switchCore',
216
                [
217
                    'corePath' => $coreAdmin->getPath(),
218
                    'uriToRedirectTo' => $uriToRedirectTo
219
                ]
220
            );
221
            $menuItem->setHref($uri);
222
223
            if ($coreAdmin->getPath() == $this->selectedSolrCoreConnection->getAdminService()->getPath()) {
224
                $menuItem->setActive(true);
225
            }
226
            $this->coreSelectorMenu->addMenuItem($menuItem);
227
        }
228
229
        $this->view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->addMenu($this->coreSelectorMenu);
230
    }
231
232
    /**
233
     * Switches used core.
234
     *
235
     * Note: Does not check availability of core in site. All this stuff is done in the generation step.
236
     *
237
     * @param string $corePath
238
     * @param string $uriToRedirectTo
239
     */
240
    public function switchCoreAction(string $corePath, string $uriToRedirectTo)
241
    {
242
        $moduleData = $this->moduleDataStorageService->loadModuleData();
243
        $moduleData->setCore($corePath);
244
245
        $this->moduleDataStorageService->persistModuleData($moduleData);
246
        $message = LocalizationUtility::translate('coreselector_switched_successfully', 'solr', [$corePath]);
247
        $this->addFlashMessage($message);
248
        $this->redirectToUri($uriToRedirectTo);
249
    }
250
251
    /**
252
     * Initializes the solr core connection considerately to the components state.
253
     * Uses and persists default core connection if persisted core in Site does not exist.
254
     *
255
     */
256
    private function initializeSelectedSolrCoreConnection()
257
    {
258
        $moduleData = $this->moduleDataStorageService->loadModuleData();
259
260
        $solrCoreConnections = $this->solrConnectionManager->getConnectionsBySite($this->selectedSite);
261
        $currentSolrCorePath = $moduleData->getCore();
262
        if (empty($currentSolrCorePath)) {
263
            $this->initializeFirstAvailableSolrCoreConnection($solrCoreConnections, $moduleData);
264
            return;
265
        }
266
        foreach ($solrCoreConnections as $solrCoreConnection) {
267
            if ($solrCoreConnection->getAdminService()->getPath() == $currentSolrCorePath) {
268
                $this->selectedSolrCoreConnection = $solrCoreConnection;
269
            }
270
        }
271
        if (!$this->selectedSolrCoreConnection instanceof SolrCoreConnection && count($solrCoreConnections) > 0) {
272
            $this->initializeFirstAvailableSolrCoreConnection($solrCoreConnections, $moduleData);
273
            $message = LocalizationUtility::translate('coreselector_switched_to_default_core', 'solr', [$currentSolrCorePath, $this->selectedSite->getLabel(), $this->selectedSolrCoreConnection->getAdminService()->getPath()]);
274
            $this->addFlashMessage($message, '', AbstractMessage::NOTICE);
275
        }
276
    }
277
278
    /**
279
     * @param SolrCoreConnection[] $solrCoreConnections
280
     */
281
    private function initializeFirstAvailableSolrCoreConnection(array $solrCoreConnections, $moduleData)
282
    {
283
        if (empty($solrCoreConnections)) {
284
            return;
285
        }
286
        $this->selectedSolrCoreConnection = $solrCoreConnections[0];
287
        $moduleData->setCore($this->selectedSolrCoreConnection->getAdminService()->getPath());
288
        $this->moduleDataStorageService->persistModuleData($moduleData);
289
    }
290
}
291