1<?php
2/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
3
4namespace Icinga\Module\Setup;
5
6use PDOException;
7use Icinga\Web\Form;
8use Icinga\Web\Wizard;
9use Icinga\Web\Request;
10use Icinga\Application\Config;
11use Icinga\Application\Icinga;
12use Icinga\Module\Setup\Forms\ModulePage;
13use Icinga\Module\Setup\Forms\WelcomePage;
14use Icinga\Module\Setup\Forms\SummaryPage;
15use Icinga\Module\Setup\Forms\DbResourcePage;
16use Icinga\Module\Setup\Forms\AuthBackendPage;
17use Icinga\Module\Setup\Forms\AdminAccountPage;
18use Icinga\Module\Setup\Forms\LdapDiscoveryPage;
19//use Icinga\Module\Setup\Forms\LdapDiscoveryConfirmPage;
20use Icinga\Module\Setup\Forms\LdapResourcePage;
21use Icinga\Module\Setup\Forms\RequirementsPage;
22use Icinga\Module\Setup\Forms\GeneralConfigPage;
23use Icinga\Module\Setup\Forms\AuthenticationPage;
24use Icinga\Module\Setup\Forms\DatabaseCreationPage;
25use Icinga\Module\Setup\Forms\UserGroupBackendPage;
26use Icinga\Module\Setup\Steps\DatabaseStep;
27use Icinga\Module\Setup\Steps\GeneralConfigStep;
28use Icinga\Module\Setup\Steps\ResourceStep;
29use Icinga\Module\Setup\Steps\AuthenticationStep;
30use Icinga\Module\Setup\Steps\UserGroupStep;
31use Icinga\Module\Setup\Utils\EnableModuleStep;
32use Icinga\Module\Setup\Utils\DbTool;
33use Icinga\Module\Setup\Requirement\OSRequirement;
34use Icinga\Module\Setup\Requirement\ClassRequirement;
35use Icinga\Module\Setup\Requirement\PhpConfigRequirement;
36use Icinga\Module\Setup\Requirement\PhpModuleRequirement;
37use Icinga\Module\Setup\Requirement\PhpVersionRequirement;
38use Icinga\Module\Setup\Requirement\ConfigDirectoryRequirement;
39use Icinga\Module\Monitoring\Forms\Config\Transport\ApiTransportForm;
40
41/**
42 * Icinga Web 2 Setup Wizard
43 */
44class WebWizard extends Wizard implements SetupWizard
45{
46    /**
47     * The privileges required by Icinga Web 2 to create the database and a login
48     *
49     * @var array
50     */
51    protected $databaseCreationPrivileges = array(
52        'CREATE',
53        'CREATE USER', // MySQL
54        'CREATEROLE' // PostgreSQL
55    );
56
57    /**
58     * The privileges required by Icinga Web 2 to setup the database
59     *
60     * @var array
61     */
62    protected $databaseSetupPrivileges = array(
63        'CREATE',
64        'ALTER', // MySQL only
65        'REFERENCES'
66    );
67
68    /**
69     * The privileges required by Icinga Web 2 to operate the database
70     *
71     * @var array
72     */
73    protected $databaseUsagePrivileges = array(
74        'SELECT',
75        'INSERT',
76        'UPDATE',
77        'DELETE',
78        'EXECUTE',
79        'TEMPORARY', // PostgreSql
80        'CREATE TEMPORARY TABLES' // MySQL
81    );
82
83    /**
84     * The database tables operated by Icinga Web 2
85     *
86     * @var array
87     */
88    protected $databaseTables = array(
89        'icingaweb_group',
90        'icingaweb_group_membership',
91        'icingaweb_user',
92        'icingaweb_user_preference'
93    );
94
95    /**
96     * Register all pages and module wizards for this wizard
97     */
98    protected function init()
99    {
100        $this->addPage(new WelcomePage());
101        $this->addPage(new ModulePage());
102        $this->addPage(new RequirementsPage());
103        $this->addPage(new AuthenticationPage());
104        $this->addPage(new DbResourcePage(array('name' => 'setup_auth_db_resource')));
105        $this->addPage(new DatabaseCreationPage(array('name' => 'setup_auth_db_creation')));
106        $this->addPage(new LdapDiscoveryPage());
107        //$this->addPage(new LdapDiscoveryConfirmPage());
108        $this->addPage(new LdapResourcePage());
109        $this->addPage(new AuthBackendPage());
110        $this->addPage(new UserGroupBackendPage());
111        $this->addPage(new AdminAccountPage());
112        $this->addPage(new GeneralConfigPage());
113        $this->addPage(new DbResourcePage(array('name' => 'setup_config_db_resource')));
114        $this->addPage(new DatabaseCreationPage(array('name' => 'setup_config_db_creation')));
115        $this->addPage(new SummaryPage(array('name' => 'setup_summary')));
116
117        if (($modulePageData = $this->getPageData('setup_modules')) !== null) {
118            $modulePage = $this->getPage('setup_modules')->populate($modulePageData);
119            foreach ($modulePage->getModuleWizards() as $moduleWizard) {
120                $this->addPage($moduleWizard);
121            }
122        }
123    }
124
125    /**
126     * Setup the given page that is either going to be displayed or validated
127     *
128     * @param   Form        $page       The page to setup
129     * @param   Request     $request    The current request
130     */
131    public function setupPage(Form $page, Request $request)
132    {
133        if ($page->getName() === 'setup_requirements') {
134            $page->setWizard($this);
135        } elseif ($page->getName() === 'setup_authentication_backend') {
136            /** @var AuthBackendPage $page */
137
138            $authData = $this->getPageData('setup_authentication_type');
139            if ($authData['type'] === 'db') {
140                $page->setResourceConfig($this->getPageData('setup_auth_db_resource'));
141            } elseif ($authData['type'] === 'ldap') {
142                $page->setResourceConfig($this->getPageData('setup_ldap_resource'));
143
144                $suggestions = $this->getPageData('setup_ldap_discovery');
145                if (isset($suggestions['backend'])) {
146                    $page->setSuggestions($suggestions['backend']);
147                }
148
149                if ($this->getDirection() === static::FORWARD) {
150                    $backendConfig = $this->getPageData('setup_authentication_backend');
151                    if ($backendConfig !== null && $request->getPost('name') !== $backendConfig['name']) {
152                        $pageData = & $this->getPageData();
153                        unset($pageData['setup_usergroup_backend']);
154                    }
155                }
156            }
157
158            if ($this->getDirection() === static::FORWARD) {
159                $backendConfig = $this->getPageData('setup_authentication_backend');
160                if ($backendConfig !== null && $request->getPost('backend') !== $backendConfig['backend']) {
161                    $pageData = & $this->getPageData();
162                    unset($pageData['setup_usergroup_backend']);
163                }
164            }
165        /*} elseif ($page->getName() === 'setup_ldap_discovery_confirm') {
166            $page->setResourceConfig($this->getPageData('setup_ldap_discovery'));*/
167        } elseif ($page->getName() === 'setup_auth_db_resource') {
168            $page->addDescription(mt(
169                'setup',
170                'Now please configure the database resource where to store users and user groups.'
171            ));
172            $page->addDescription(mt(
173                'setup',
174                'Note that the database itself does not need to exist at this time as'
175                . ' it is going to be created once the wizard is about to be finished.'
176            ));
177        } elseif ($page->getName() === 'setup_usergroup_backend') {
178            $page->setResourceConfig($this->getPageData('setup_ldap_resource'));
179            $page->setBackendConfig($this->getPageData('setup_authentication_backend'));
180        } elseif ($page->getName() === 'setup_admin_account') {
181            $page->setBackendConfig($this->getPageData('setup_authentication_backend'));
182            $page->setGroupConfig($this->getPageData('setup_usergroup_backend'));
183            $authData = $this->getPageData('setup_authentication_type');
184            if ($authData['type'] === 'db') {
185                $page->setResourceConfig($this->getPageData('setup_auth_db_resource'));
186            } elseif ($authData['type'] === 'ldap') {
187                $page->setResourceConfig($this->getPageData('setup_ldap_resource'));
188            }
189        } elseif ($page->getName() === 'setup_auth_db_creation' || $page->getName() === 'setup_config_db_creation') {
190            $page->setDatabaseSetupPrivileges(
191                array_unique(array_merge($this->databaseCreationPrivileges, $this->databaseSetupPrivileges))
192            );
193            $page->setDatabaseUsagePrivileges($this->databaseUsagePrivileges);
194            $page->setResourceConfig(
195                $this->getPageData('setup_auth_db_resource') ?: $this->getPageData('setup_config_db_resource')
196            );
197        } elseif ($page->getName() === 'setup_summary') {
198            $page->setSubjectTitle('Icinga Web 2');
199            $page->setSummary($this->getSetup()->getSummary());
200        } elseif ($page->getName() === 'setup_config_db_resource') {
201            $page->addDescription(mt(
202                'setup',
203                'Now please configure the database resource where to store user preferences.'
204            ));
205            $page->addDescription(mt(
206                'setup',
207                'Note that the database itself does not need to exist at this time as'
208                . ' it is going to be created once the wizard is about to be finished.'
209            ));
210
211            $ldapData = $this->getPageData('setup_ldap_resource');
212            if ($ldapData !== null && $request->getPost('name') === $ldapData['name']) {
213                $page->error(
214                    mt('setup', 'The given resource name must be unique and is already in use by the LDAP resource')
215                );
216            }
217        } elseif ($page->getName() === 'setup_ldap_resource') {
218            $suggestion = $this->getPageData('setup_ldap_discovery');
219            if (isset($suggestion['resource'])) {
220                $page->populate($suggestion['resource']);
221            }
222
223            if ($this->getDirection() === static::FORWARD) {
224                $resourceConfig = $this->getPageData('setup_ldap_resource');
225                if ($resourceConfig !== null && $request->getPost('name') !== $resourceConfig['name']) {
226                    $pageData = & $this->getPageData();
227                    unset($pageData['setup_usergroup_backend']);
228                }
229            }
230        } elseif ($page->getName() === 'setup_general_config') {
231            $authData = $this->getPageData('setup_authentication_type');
232            if ($authData['type'] === 'db') {
233                $page
234                    ->create($this->getRequestData($page, $request))
235                    ->getElement('global_config_backend')
236                    ->setValue('db');
237                $page->info(
238                    mt(
239                        'setup',
240                        'Note that choosing "Database" as preference storage causes'
241                        . ' Icinga Web 2 to use the same database as for authentication.'
242                    ),
243                    false
244                );
245            }
246        } elseif ($page->getName() === 'setup_authentication_type' && $this->getDirection() === static::FORWARD) {
247            $authData = $this->getPageData($page->getName());
248            if ($authData !== null && $request->getPost('type') !== $authData['type']) {
249                // Drop any existing page data in case the authentication type has changed,
250                // otherwise it will conflict with other forms that depend on this one
251                $pageData = & $this->getPageData();
252                unset($pageData['setup_admin_account']);
253                unset($pageData['setup_authentication_backend']);
254
255                if ($authData['type'] === 'db') {
256                    unset($pageData['setup_auth_db_resource']);
257                    unset($pageData['setup_auth_db_creation']);
258                } elseif ($request->getPost('type') === 'db') {
259                    unset($pageData['setup_config_db_resource']);
260                    unset($pageData['setup_config_db_creation']);
261                }
262            }
263        }
264    }
265
266    /**
267     * Return the new page to set as current page
268     *
269     * {@inheritdoc} Runs additional checks related to some registered pages.
270     *
271     * @param   string  $requestedPage      The name of the requested page
272     * @param   Form    $originPage         The origin page
273     *
274     * @return  Form                        The new page
275     *
276     * @throws  InvalidArgumentException    In case the requested page does not exist or is not permitted yet
277     */
278    protected function getNewPage($requestedPage, Form $originPage)
279    {
280        $skip = false;
281        $newPage = parent::getNewPage($requestedPage, $originPage);
282        if ($newPage->getName() === 'setup_auth_db_resource') {
283            $authData = $this->getPageData('setup_authentication_type');
284            $skip = $authData['type'] !== 'db';
285        } elseif ($newPage->getname() === 'setup_ldap_discovery') {
286            $authData = $this->getPageData('setup_authentication_type');
287            $skip = $authData['type'] !== 'ldap';
288        /*} elseif ($newPage->getName() === 'setup_ldap_discovery_confirm') {
289            $skip = false === $this->hasPageData('setup_ldap_discovery');*/
290        } elseif ($newPage->getName() === 'setup_ldap_resource') {
291            $authData = $this->getPageData('setup_authentication_type');
292            $skip = $authData['type'] !== 'ldap';
293        } elseif ($newPage->getName() === 'setup_usergroup_backend') {
294            $backendConfig = $this->getPageData('setup_authentication_backend');
295            $skip = $backendConfig['backend'] !== 'ldap';
296        } elseif ($newPage->getName() === 'setup_config_db_resource') {
297            $authData = $this->getPageData('setup_authentication_type');
298            $configData = $this->getPageData('setup_general_config');
299            $skip = $authData['type'] === 'db' || $configData['global_config_backend'] !== 'db';
300        } elseif (in_array($newPage->getName(), array('setup_auth_db_creation', 'setup_config_db_creation'))) {
301            if (($newPage->getName() === 'setup_auth_db_creation' || $this->hasPageData('setup_config_db_resource'))
302                && (($config = $this->getPageData('setup_auth_db_resource')) !== null
303                    || ($config = $this->getPageData('setup_config_db_resource')) !== null)
304                    && !$config['skip_validation']
305            ) {
306                $db = new DbTool($config);
307
308                try {
309                    $db->connectToDb(); // Are we able to login on the database?
310                    if (array_search(reset($this->databaseTables), $db->listTables(), true) === false) {
311                        // In case the database schema does not yet exist the
312                        // user needs the privileges to setup the database
313                        $skip = $db->checkPrivileges($this->databaseSetupPrivileges, $this->databaseTables);
314                    } else {
315                        // In case the database schema exists the user needs the required privileges
316                        // to operate the database, if those are missing we ask for another user
317                        $skip = $db->checkPrivileges($this->databaseUsagePrivileges, $this->databaseTables);
318                    }
319                } catch (PDOException $_) {
320                    try {
321                        $db->connectToHost(); // Are we able to login on the server?
322                        // It is not possible to reliably determine whether a database exists or not if a user can't
323                        // log in to the database, so we just require the user to be able to create the database
324                        $skip = $db->checkPrivileges(
325                            array_unique(
326                                array_merge($this->databaseCreationPrivileges, $this->databaseSetupPrivileges)
327                            ),
328                            $this->databaseTables
329                        );
330                    } catch (PDOException $_) {
331                        // We are NOT able to login on the server..
332                    }
333                }
334            } else {
335                $skip = true;
336            }
337        }
338
339        return $skip ? $this->skipPage($newPage) : $newPage;
340    }
341
342    /**
343     * Add buttons to the given page based on its position in the page-chain
344     *
345     * @param   Form    $page   The page to add the buttons to
346     */
347    protected function addButtons(Form $page)
348    {
349        parent::addButtons($page);
350
351        $pages = $this->getPages();
352        $index = array_search($page, $pages, true);
353        if ($index === 0) {
354            $page->getElement(static::BTN_NEXT)->setLabel(
355                mt('setup', 'Start', 'setup.welcome.btn.next')
356            );
357        } elseif ($index === count($pages) - 1) {
358            $page->getElement(static::BTN_NEXT)->setLabel(
359                mt('setup', 'Setup Icinga Web 2', 'setup.summary.btn.finish')
360            );
361        }
362
363        $authData = $this->getPageData('setup_authentication_type');
364        $veto = $page->getName() === 'setup_authentication_backend' && $authData['type'] === 'db';
365        if (! $veto && in_array($page->getName(), array(
366            'setup_authentication_backend',
367            'setup_auth_db_resource',
368            'setup_config_db_resource',
369            'setup_ldap_resource',
370            'setup_monitoring_ido',
371            'setup_icingadb_resource',
372            'setup_icingadb_redis',
373            'setup_icingadb_api_transport'
374        ))) {
375            $page->addElement(
376                'submit',
377                'backend_validation',
378                array(
379                    'ignore'                => true,
380                    'label'                 => t('Validate Configuration'),
381                    'data-progress-label'   => t('Validation In Progress'),
382                    'decorators'            => array('ViewHelper')
383                )
384            );
385            $page->getDisplayGroup('buttons')->addElement($page->getElement('backend_validation'));
386        }
387
388        if ($page->getName() === 'setup_command_transport') {
389            if ($page->getSubForm('transport_form')->getSubForm('transport_form') instanceof ApiTransportForm) {
390                $page->addElement(
391                    'submit',
392                    'transport_validation',
393                    array(
394                        'ignore'                => true,
395                        'label'                 => t('Validate Configuration'),
396                        'data-progress-label'   => t('Validation In Progress'),
397                        'decorators'            => array('ViewHelper')
398                    )
399                );
400                $page->getDisplayGroup('buttons')->addElement($page->getElement('transport_validation'));
401            }
402        }
403    }
404
405    /**
406     * Clear the session being used by this wizard
407     *
408     * @param   bool    $removeToken    If true, the setup token will be removed
409     */
410    public function clearSession($removeToken = true)
411    {
412        parent::clearSession();
413
414        if ($removeToken) {
415            $tokenPath = Config::resolvePath('setup.token');
416            if (file_exists($tokenPath)) {
417                @unlink($tokenPath);
418            }
419        }
420    }
421
422    /**
423     * Return the setup for this wizard
424     *
425     * @return  Setup
426     */
427    public function getSetup()
428    {
429        $pageData = $this->getPageData();
430        $setup = new Setup();
431
432        if (isset($pageData['setup_auth_db_resource'])
433            && !$pageData['setup_auth_db_resource']['skip_validation']
434            && (! isset($pageData['setup_auth_db_creation'])
435                || !$pageData['setup_auth_db_creation']['skip_validation']
436            )
437        ) {
438            $setup->addStep(
439                new DatabaseStep(array(
440                    'tables'            => $this->databaseTables,
441                    'privileges'        => $this->databaseUsagePrivileges,
442                    'resourceConfig'    => $pageData['setup_auth_db_resource'],
443                    'adminName'         => isset($pageData['setup_auth_db_creation']['username'])
444                        ? $pageData['setup_auth_db_creation']['username']
445                        : null,
446                    'adminPassword'     => isset($pageData['setup_auth_db_creation']['password'])
447                        ? $pageData['setup_auth_db_creation']['password']
448                        : null,
449                    'schemaPath'        => Config::module('setup')
450                        ->get('schema', 'path', Icinga::app()->getBaseDir('etc' . DIRECTORY_SEPARATOR . 'schema'))
451                ))
452            );
453        } elseif (isset($pageData['setup_config_db_resource'])
454            && !$pageData['setup_config_db_resource']['skip_validation']
455            && (! isset($pageData['setup_config_db_creation'])
456                || !$pageData['setup_config_db_creation']['skip_validation']
457            )
458        ) {
459            $setup->addStep(
460                new DatabaseStep(array(
461                    'tables'            => $this->databaseTables,
462                    'privileges'        => $this->databaseUsagePrivileges,
463                    'resourceConfig'    => $pageData['setup_config_db_resource'],
464                    'adminName'         => isset($pageData['setup_config_db_creation']['username'])
465                        ? $pageData['setup_config_db_creation']['username']
466                        : null,
467                    'adminPassword'     => isset($pageData['setup_config_db_creation']['password'])
468                        ? $pageData['setup_config_db_creation']['password']
469                        : null,
470                    'schemaPath'        => Config::module('setup')
471                        ->get('schema', 'path', Icinga::app()->getBaseDir('etc' . DIRECTORY_SEPARATOR . 'schema'))
472                ))
473            );
474        }
475
476        $setup->addStep(
477            new GeneralConfigStep(array(
478                'generalConfig' => $pageData['setup_general_config'],
479                'resourceName'  => isset($pageData['setup_auth_db_resource']['name'])
480                    ? $pageData['setup_auth_db_resource']['name']
481                    : (isset($pageData['setup_config_db_resource']['name'])
482                        ? $pageData['setup_config_db_resource']['name']
483                        : null
484                    )
485            ))
486        );
487
488        $adminAccountType = $pageData['setup_admin_account']['user_type'];
489        if ($adminAccountType === 'user_group') {
490            $adminAccountData = array('groupname' => $pageData['setup_admin_account'][$adminAccountType]);
491        } else {
492            $adminAccountData = array('username' => $pageData['setup_admin_account'][$adminAccountType]);
493            if ($adminAccountType === 'new_user' && !$pageData['setup_auth_db_resource']['skip_validation']
494                && (! isset($pageData['setup_auth_db_creation'])
495                    || !$pageData['setup_auth_db_creation']['skip_validation']
496                )
497            ) {
498                $adminAccountData['resourceConfig'] = $pageData['setup_auth_db_resource'];
499                $adminAccountData['password'] = $pageData['setup_admin_account']['new_user_password'];
500            }
501        }
502        $authType = $pageData['setup_authentication_type']['type'];
503        $setup->addStep(
504            new AuthenticationStep(array(
505                'adminAccountData'  => $adminAccountData,
506                'backendConfig'     => $pageData['setup_authentication_backend'],
507                'resourceName'      => $authType === 'db' ? $pageData['setup_auth_db_resource']['name'] : (
508                    $authType === 'ldap' ? $pageData['setup_ldap_resource']['name'] : null
509                )
510            ))
511        );
512
513        if ($authType !== 'external') {
514            $setup->addStep(
515                new UserGroupStep(array(
516                    'backendConfig'     => $pageData['setup_authentication_backend'],
517                    'groupConfig'       => isset($pageData['setup_usergroup_backend'])
518                        ? $pageData['setup_usergroup_backend']
519                        : null,
520                    'resourceName'      => $authType === 'db'
521                        ? $pageData['setup_auth_db_resource']['name']
522                        : $pageData['setup_ldap_resource']['name'],
523                    'resourceConfig'    => $authType === 'db'
524                        ? $pageData['setup_auth_db_resource']
525                        : null,
526                    'username'          => $authType === 'db'
527                        ? $pageData['setup_admin_account'][$adminAccountType]
528                        : null
529                ))
530            );
531        }
532
533        if (isset($pageData['setup_auth_db_resource'])
534            || isset($pageData['setup_config_db_resource'])
535            || isset($pageData['setup_ldap_resource'])
536        ) {
537            $setup->addStep(
538                new ResourceStep(array(
539                    'dbResourceConfig'      => isset($pageData['setup_auth_db_resource'])
540                        ? array_diff_key($pageData['setup_auth_db_resource'], array('skip_validation' => null))
541                        : (isset($pageData['setup_config_db_resource'])
542                            ? array_diff_key($pageData['setup_config_db_resource'], array('skip_validation' => null))
543                            : null
544                        ),
545                    'ldapResourceConfig'    => isset($pageData['setup_ldap_resource'])
546                        ? array_diff_key($pageData['setup_ldap_resource'], array('skip_validation' => null))
547                        : null
548                ))
549            );
550        }
551
552        foreach ($this->getWizards() as $wizard) {
553            if ($wizard->isComplete()) {
554                $setup->addSteps($wizard->getSetup()->getSteps());
555            }
556        }
557
558        $setup->addStep(new EnableModuleStep(array_keys($this->getPage('setup_modules')->getCheckedModules())));
559
560        return $setup;
561    }
562
563    /**
564     * Return the requirements of this wizard
565     *
566     * @return  RequirementSet
567     */
568    public function getRequirements($skipModules = false)
569    {
570        $set = new RequirementSet();
571
572        $set->add(new PhpVersionRequirement(array(
573            'condition'     => array('>=', '5.6'),
574            'description'   => mt(
575                'setup',
576                'Running Icinga Web 2 requires PHP version 5.6.'
577            )
578        )));
579
580        $set->add(new OSRequirement(array(
581            'optional'      => true,
582            'condition'     => 'linux',
583            'description'   => mt(
584                'setup',
585                'Icinga Web 2 is developed for and tested on Linux. While we cannot'
586                . ' guarantee they will, other platforms may also perform as well.'
587            )
588        )));
589
590        $set->add(new PhpModuleRequirement(array(
591            'condition'     => 'OpenSSL',
592            'description'   => mt(
593                'setup',
594                'The PHP module for OpenSSL is required to generate cryptographically safe password salts.'
595            )
596        )));
597
598        $set->add(new PhpModuleRequirement(array(
599            'optional'      => true,
600            'condition'     => 'JSON',
601            'description'   => mt(
602                'setup',
603                'The JSON module for PHP is required for various export functionalities as well as APIs.'
604            )
605        )));
606
607        $set->add(new PhpModuleRequirement(array(
608            'optional'      => true,
609            'condition'     => 'LDAP',
610            'description'   => mt(
611                'setup',
612                'If you\'d like to authenticate users using LDAP the corresponding PHP module is required.'
613            )
614        )));
615
616        $set->add(new PhpModuleRequirement(array(
617            'optional'      => true,
618            'condition'     => 'INTL',
619            'description'   => mt(
620                'setup',
621                'If you want your users to benefit from language, timezone and date/time'
622                . ' format negotiation, the INTL module for PHP is required.'
623            )
624        )));
625
626        // TODO(6172): Remove this requirement once we do not ship dompdf with Icinga Web 2 anymore
627        $set->add(new PhpModuleRequirement(array(
628            'optional'      => true,
629            'condition'     => 'DOM',
630            'description'   => mt(
631                'setup',
632                'To be able to export views and reports to PDF, the DOM module for PHP is required.'
633            )
634        )));
635
636        $set->add(new PhpModuleRequirement(array(
637            'optional'      => true,
638            'condition'     => 'GD',
639            'description'   => mt(
640                'setup',
641                'In case you want views being exported to PDF, you\'ll need the GD extension for PHP.'
642            )
643        )));
644
645        $set->add(new PhpModuleRequirement(array(
646            'optional'      => true,
647            'condition'     => 'Imagick',
648            'description'   => mt(
649                'setup',
650                'In case you want graphs being exported to PDF as well, you\'ll need the ImageMagick extension for PHP.'
651            )
652        )));
653
654        $mysqlSet = new RequirementSet(true);
655        $mysqlSet->add(new PhpModuleRequirement(array(
656            'optional'      => true,
657            'condition'     => 'pdo_mysql',
658            'alias'         => 'PDO-MySQL',
659            'description'   => mt(
660                'setup',
661                'To store users or preferences in a MySQL database the PDO-MySQL module for PHP is required.'
662            )
663        )));
664        $mysqlSet->add(new ClassRequirement(array(
665            'optional'      => true,
666            'condition'     => 'Zend_Db_Adapter_Pdo_Mysql',
667            'alias'         => mt('setup', 'Zend database adapter for MySQL'),
668            'description'   => mt(
669                'setup',
670                'The Zend database adapter for MySQL is required to access a MySQL database.'
671            ),
672            'textAvailable' => mt(
673                'setup',
674                'The Zend database adapter for MySQL is available.',
675                'setup.requirement.class'
676            ),
677            'textMissing'   => mt(
678                'setup',
679                'The Zend database adapter for MySQL is missing.',
680                'setup.requirement.class'
681            )
682        )));
683        $set->merge($mysqlSet);
684
685        $pgsqlSet = new RequirementSet(true);
686        $pgsqlSet->add(new PhpModuleRequirement(array(
687            'optional'      => true,
688            'condition'     => 'pdo_pgsql',
689            'alias'         => 'PDO-PostgreSQL',
690            'description'   => mt(
691                'setup',
692                'To store users or preferences in a PostgreSQL database the PDO-PostgreSQL module for PHP is required.'
693            )
694        )));
695        $pgsqlSet->add(new ClassRequirement(array(
696            'optional'      => true,
697            'condition'     => 'Zend_Db_Adapter_Pdo_Pgsql',
698            'alias'         => mt('setup', 'Zend database adapter for PostgreSQL'),
699            'description'   => mt(
700                'setup',
701                'The Zend database adapter for PostgreSQL is required to access a PostgreSQL database.'
702            ),
703            'textAvailable' => mt(
704                'setup',
705                'The Zend database adapter for PostgreSQL is available.',
706                'setup.requirement.class'
707            ),
708            'textMissing'   => mt(
709                'setup',
710                'The Zend database adapter for PostgreSQL is missing.',
711                'setup.requirement.class'
712            )
713        )));
714        $set->merge($pgsqlSet);
715
716        $set->add(new ConfigDirectoryRequirement(array(
717            'condition'     => Icinga::app()->getConfigDir(),
718            'description'   => mt(
719                'setup',
720                'The Icinga Web 2 configuration directory defaults to "/etc/icingaweb2", if' .
721                ' not explicitly set in the environment variable "ICINGAWEB_CONFIGDIR".'
722            )
723        )));
724
725        if (! $skipModules) {
726            foreach ($this->getWizards() as $wizard) {
727                $set->merge($wizard->getRequirements());
728            }
729        }
730
731        return $set;
732    }
733}
734