Completed
Push — master ( 3ac426...d3ebfb )
by Craig
07:17
created

AjaxInstallController::installModule()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 4
nop 1
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Zikula package.
5
 *
6
 * Copyright Zikula Foundation - http://zikula.org/
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zikula\Bundle\CoreInstallerBundle\Controller;
13
14
use RandomLib\Factory;
15
use Symfony\Component\DependencyInjection\ContainerInterface;
16
use Symfony\Component\HttpFoundation\JsonResponse;
17
use Symfony\Component\HttpFoundation\Request;
18
use Zikula\BlocksModule\Entity\BlockEntity;
19
use Zikula\BlocksModule\Entity\BlockPlacementEntity;
20
use Zikula\Bundle\CoreBundle\Bundle\Bootstrap as CoreBundleBootstrap;
21
use Zikula\Core\Event\GenericEvent;
22
use Zikula\ExtensionsModule\Api\VariableApi;
23
use Zikula\Bundle\CoreBundle\YamlDumper;
24
use Zikula\Core\CoreEvents;
25
use Zikula\ZAuthModule\Entity\AuthenticationMappingEntity;
26
use Zikula\ZAuthModule\ZAuthConstant;
27
28
/**
29
 * Class AjaxInstallController
30
 */
31
class AjaxInstallController extends AbstractController
32
{
33
    /**
34
     * @var YamlDumper
35
     */
36
    private $yamlManager;
37
38
    public function __construct(ContainerInterface $container)
39
    {
40
        parent::__construct($container);
41
        $this->yamlManager = new YamlDumper($this->container->get('kernel')->getRootDir() .'/config', 'custom_parameters.yml');
42
    }
43
44
    public function ajaxAction(Request $request)
45
    {
46
        $stage = $request->request->get('stage');
47
        $status = $this->executeStage($stage);
48
49
        return new JsonResponse(['status' => $status]);
50
    }
51
52
    public function commandLineAction($stage)
53
    {
54
        return $this->executeStage($stage);
55
    }
56
57
    private function executeStage($stageName)
58
    {
59
        switch ($stageName) {
60
            case "bundles":
61
                return $this->createBundles();
62
            case "install_event":
63
                return $this->fireEvent(CoreEvents::CORE_INSTALL_PRE_MODULE);
64
            case "extensions":
65
                return $this->installModule('ZikulaExtensionsModule');
66
            case "settings":
67
                return $this->installModule('ZikulaSettingsModule');
68
            case "theme":
69
                return $this->installModule('ZikulaThemeModule');
70
            case "admin":
71
                return $this->installModule('ZikulaAdminModule');
72
            case "permissions":
73
                return $this->installModule('ZikulaPermissionsModule');
74
            case "groups":
75
                return $this->installModule('ZikulaGroupsModule');
76
            case "blocks":
77
                return $this->installModule('ZikulaBlocksModule');
78
            case "users":
79
                return $this->installModule('ZikulaUsersModule');
80
            case "zauth":
81
                return $this->installModule('ZikulaZAuthModule');
82
            case "security":
83
                return $this->installModule('ZikulaSecurityCenterModule');
84
            case "categories":
85
                return $this->installModule('ZikulaCategoriesModule');
86
            case "mailer":
87
                return $this->installModule('ZikulaMailerModule');
88
            case "search":
89
                return $this->installModule('ZikulaSearchModule');
90
            case "routes":
91
                return $this->installModule('ZikulaRoutesModule');
92
            case "menu":
93
                return $this->installModule('ZikulaMenuModule');
94
            case "updateadmin":
95
                return $this->updateAdmin();
96
            case "loginadmin":
97
                $params = $this->decodeParameters($this->yamlManager->getParameters());
98
99
                return $this->loginAdmin($params);
100
            case "activatemodules":
101
                return $this->reSyncAndActivateModules();
102
            case "categorize":
103
                return $this->categorizeModules();
104
            case "createblocks":
105
                return $this->createBlocks();
106
            case "finalizeparameters":
107
                return $this->finalizeParameters();
108
            case "installassets":
109
                return $this->installAssets();
110
            case "protect":
111
                return $this->protectFiles();
112
        }
113
//        \System::setInstalling(false); @todo need to probably set a parameter for this?
114
115
        return true;
116
    }
117
118
    private function createBundles()
119
    {
120
        $kernel = $this->container->get('kernel');
121
        $boot = new CoreBundleBootstrap();
122
        $helper = $this->container->get('zikula_core.internal.bootstrap_helper');
123
        $helper->createSchema();
124
        $helper->load();
125
        $bundles = [];
126
        // this neatly autoloads
127
        $boot->getPersistedBundles($kernel, $bundles);
128
129
        return true;
130
    }
131
132
    private function categorizeModules()
133
    {
134
        reset(\ZikulaKernel::$coreModules);
135
        $systemModulesCategories = [
136
            'ZikulaExtensionsModule' => $this->translator->__('System'),
137
            'ZikulaPermissionsModule' => $this->translator->__('Users'),
138
            'ZikulaGroupsModule' => $this->translator->__('Users'),
139
            'ZikulaBlocksModule' => $this->translator->__('Layout'),
140
            'ZikulaUsersModule' => $this->translator->__('Users'),
141
            'ZikulaZAuthModule' => $this->translator->__('Users'),
142
            'ZikulaThemeModule' => $this->translator->__('Layout'),
143
            'ZikulaSecurityCenterModule' => $this->translator->__('Security'),
144
            'ZikulaCategoriesModule' => $this->translator->__('Content'),
145
            'ZikulaMailerModule' => $this->translator->__('System'),
146
            'ZikulaSearchModule' => $this->translator->__('Content'),
147
            'ZikulaAdminModule' => $this->translator->__('System'),
148
            'ZikulaSettingsModule' => $this->translator->__('System'),
149
            'ZikulaRoutesModule' => $this->translator->__('System'),
150
            'ZikulaMenuModule' => $this->translator->__('Content'),
151
            'ZikulaPageLockModule' => $this->translator->__('Content'),
152
        ];
153
154
        foreach (\ZikulaKernel::$coreModules as $systemModule => $bundleClass) {
155
            $this->setModuleCategory($systemModule, $systemModulesCategories[$systemModule]);
156
        }
157
158
        return true;
159
    }
160
161
    private function createBlocks()
162
    {
163
        $installer = new \Zikula\BlocksModule\BlocksModuleInstaller();
164
        $installer->setBundle($this->container->get('kernel')->getModule('ZikulaBlocksModule'));
165
        $installer->setContainer($this->container);
166
        // create the default blocks.
167
        $installer->defaultdata();
168
        $this->createMainMenuBlock();
169
170
        return true;
171
    }
172
173
    /**
174
     * This function inserts the admin's user data
175
     */
176
    private function updateAdmin()
177
    {
178
        $entityManager = $this->container->get('doctrine')->getManager();
179
        $params = $this->decodeParameters($this->yamlManager->getParameters());
180
181
        $nowUTC = new \DateTime(null, new \DateTimeZone('UTC'));
182
183
        /** @var \Zikula\UsersModule\Entity\UserEntity $userEntity */
184
        $userEntity = $entityManager->find('ZikulaUsersModule:UserEntity', 2);
185
        $userEntity->setUname($params['username']);
186
        $userEntity->setEmail($params['email']);
187
        $userEntity->setActivated(1);
188
        $userEntity->setUser_Regdate($nowUTC);
189
        $userEntity->setLastlogin($nowUTC);
190
        $entityManager->persist($userEntity);
191
192
        $mapping = new AuthenticationMappingEntity();
193
        $mapping->setUid($userEntity->getUid());
194
        $mapping->setUname($userEntity->getUname());
195
        $mapping->setEmail($userEntity->getEmail());
196
        $mapping->setVerifiedEmail(true);
197
        $mapping->setPass($this->container->get('zikula_zauth_module.api.password')->getHashedPassword($params['password']));
198
        $mapping->setMethod(ZAuthConstant::AUTHENTICATION_METHOD_UNAME);
199
        $entityManager->persist($mapping);
200
201
        $entityManager->flush();
202
203
        return true;
204
    }
205
206
    private function finalizeParameters()
207
    {
208
        $params = $this->decodeParameters($this->yamlManager->getParameters());
209
        $variableApi = $this->container->get('zikula_extensions_module.api.variable');
210
        $variableApi->getAll(VariableApi::CONFIG); // forces initialization of API
211
        $variableApi->set(VariableApi::CONFIG, 'language_i18n', $params['locale']);
212
        // Set the System Identifier as a unique string.
213
        $variableApi->set(VariableApi::CONFIG, 'system_identifier', str_replace('.', '', uniqid(rand(1000000000, 9999999999), true)));
214
        // add admin email as site email
215
        $variableApi->set(VariableApi::CONFIG, 'adminmail', $params['email']);
216
        // regenerate the theme list
217
        $this->container->get('zikula_theme_module.helper.bundle_sync_helper')->regenerate();
218
219
        // add remaining parameters and remove unneeded ones
220
        unset($params['username'], $params['password'], $params['email'], $params['dbtabletype']);
221
        $params['datadir'] = !empty($params['datadir']) ? $params['datadir'] : 'userdir';
222
        $RandomLibFactory = new Factory();
223
        $generator = $RandomLibFactory->getMediumStrengthGenerator();
224
        $params['secret'] = $generator->generateString(50);
225
        $params['url_secret'] = $generator->generateString(10);
226
        // Configure the Request Context
227
        // see http://symfony.com/doc/current/cookbook/console/sending_emails.html#configuring-the-request-context-globally
228
        $params['router.request_context.host'] = isset($params['router.request_context.host']) ? $params['router.request_context.host'] : $this->container->get('request')->getHost();
229
        $params['router.request_context.scheme'] = isset($params['router.request_context.scheme']) ? $params['router.request_context.scheme'] : 'http';
230
        $params['router.request_context.base_url'] = isset($params['router.request_context.base_url']) ? $params['router.request_context.base_url'] : $this->container->get('request')->getBasePath();
231
        $params['umask'] = isset($params['umask']) ? $params['umask'] : null;
232
        $this->yamlManager->setParameters($params);
233
234
        // clear the cache
235
        $this->container->get('zikula.cache_clearer')->clear('symfony.config');
236
237
        return true;
238
    }
239
240
    private function installAssets()
241
    {
242
        $this->container->get('zikula_extensions_module.extension_helper')->installAssets();
243
244
        return true;
245
    }
246
247
    private function protectFiles()
248
    {
249
        // protect config.php and parameters.yml files
250
        foreach ([
251
            realpath($this->container->get('kernel')->getRootDir() . '/../app/config/parameters.yml')
252
        ] as $file) {
253
            @chmod($file, 0400);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
254
            if (!is_readable($file)) {
255
                @chmod($file, 0440);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
256
                if (!is_readable($file)) {
257
                    @chmod($file, 0444);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
258
                }
259
            }
260
        }
261
262
        // set installed = true
263
        $params = $this->yamlManager->getParameters();
264
        $params['installed'] = true;
265
        // set currently installed version into parameters
266
        $params[\ZikulaKernel::CORE_INSTALLED_VERSION_PARAM] = \ZikulaKernel::VERSION;
267
268
        $this->yamlManager->setParameters($params);
269
        // clear the cache
270
        $this->container->get('zikula.cache_clearer')->clear('symfony.config');
271
272
        return true;
273
    }
274
275
    private function createMainMenuBlock()
276
    {
277
        // Create the Main Menu Block
278
        $_em = $this->container->get('doctrine')->getManager();
279
        $menuModuleEntity = $_em->getRepository('ZikulaExtensionsModule:ExtensionEntity')->findOneBy(['name' => 'ZikulaMenuModule']);
280
        $blockEntity = new BlockEntity();
281
        $mainMenuString = $this->translator->__('Main menu');
282
        $blockEntity->setTitle($mainMenuString);
283
        $blockEntity->setBkey('ZikulaMenuModule:\Zikula\MenuModule\Block\MenuBlock');
284
        $blockEntity->setBlocktype('Menu');
285
        $blockEntity->setDescription($mainMenuString);
286
        $blockEntity->setModule($menuModuleEntity);
287
        $blockEntity->setProperties([
288
            'name' => 'mainMenu',
289
            'options' => '{"template": "ZikulaMenuModule:Override:bootstrap_fontawesome.html.twig"}'
290
        ]);
291
        $_em->persist($blockEntity);
292
293
        $topNavPosition = $_em->getRepository('ZikulaBlocksModule:BlockPositionEntity')->findOneBy(['name' => 'topnav']);
294
        $placement = new BlockPlacementEntity();
295
        $placement->setBlock($blockEntity);
296
        $placement->setPosition($topNavPosition);
297
        $placement->setSortorder(0);
298
        $_em->persist($placement);
299
300
        $_em->flush();
301
    }
302
303
    private function fireEvent($eventName)
304
    {
305
        $event = new GenericEvent();
306
        $this->container->get('event_dispatcher')->dispatch($eventName, $event);
307
        if ($event->isPropagationStopped()) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !$event->isPropagationStopped();.
Loading history...
308
            return false;
309
        }
310
311
        return true;
312
    }
313
}
314