GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — 2.9 ( 633947...59760f )
by Thorsten
13:00
created

PMF_Installer   F

Complexity

Total Complexity 83

Size/Duplication

Total Lines 891
Duplicated Lines 7.63 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 83
c 1
b 0
f 1
lcom 1
cbo 18
dl 68
loc 891
rs 1.0434

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
C checkBasicStuff() 20 43 8
A checkPreUpgrade() 0 16 4
A checkMinimumPhpVersion() 0 8 2
B checkFilesystemPermissions() 0 26 6
C checkNoncriticalSettings() 4 26 8
A checkSessionSettings() 0 4 1
F startInstall() 44 349 49
A cleanUpFiles() 0 15 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like PMF_Installer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PMF_Installer, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
use Symfony\Component\ClassLoader\Psr4ClassLoader;
4
use Elasticsearch\ClientBuilder;
5
use Psr\Log\NullLogger;
6
use GuzzleHttp\Ring\Client\CurlHandler;
7
8
/**
9
 * The Installer class installs phpMyFAQ. Classy.
10
 *
11
 * PHP Version 5.5
12
 *
13
 * This Source Code Form is subject to the terms of the Mozilla Public License,
14
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
15
 * obtain one at http://mozilla.org/MPL/2.0/.
16
 *
17
 * @category  phpMyFAQ
18
 * @author    Florian Anderiasch <[email protected]>
19
 * @copyright 2012-2016 phpMyFAQ Team
20
 * @license   http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
21
 * @link      http://www.phpmyfaq.de
22
 * @since     2012-08-27
23
 */
24
if (!defined('IS_VALID_PHPMYFAQ')) {
25
    exit();
26
}
27
28
/**
29
 * Installer.
30
 *
31
 * @category  phpMyFAQ
32
 * @author    Florian Anderiasch <[email protected]>
33
 * @copyright 2012-2016 phpMyFAQ Team
34
 * @license   http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
35
 * @link      http://www.phpmyfaq.de
36
 * @since     2012-08-27
37
 */
38
class PMF_Installer
39
{
40
    /**
41
     * PMF_System object.
42
     *
43
     * @var PMF_System
44
     */
45
    protected $_system;
46
47
    /**
48
     * Array with user rights.
49
     *
50
     * @var array
51
     */
52
    protected $_mainRights = array(
53
        //1 => "adduser",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
54
        array(
55
            'name' => 'adduser',
56
            'description' => 'Right to add user accounts',
57
        ),
58
        //2 => "edituser",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
59
        array(
60
            'name' => 'edituser',
61
            'description' => 'Right to edit user accounts',
62
        ),
63
        //3 => "deluser",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
64
        array(
65
            'name' => 'deluser',
66
            'description' => 'Right to delete user accounts',
67
        ),
68
        //4 => "addbt",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
69
        array(
70
            'name' => 'addbt',
71
            'description' => 'Right to add faq entries',
72
        ),
73
        //5 => "editbt",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
74
        array(
75
            'name' => 'editbt',
76
            'description' => 'Right to edit faq entries',
77
        ),
78
        //6 => "delbt",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
79
        array(
80
            'name' => 'delbt',
81
            'description' => 'Right to delete faq entries',
82
        ),
83
        //7 => "viewlog",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
84
        array(
85
            'name' => 'viewlog',
86
            'description' => 'Right to view logfiles',
87
        ),
88
        //8 => "adminlog",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
89
        array(
90
            'name' => 'adminlog',
91
            'description' => 'Right to view admin log',
92
        ),
93
        //9 => "delcomment",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
94
        array(
95
            'name' => 'delcomment',
96
            'description' => 'Right to delete comments',
97
        ),
98
        //10 => "addnews",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
99
        array(
100
            'name' => 'addnews',
101
            'description' => 'Right to add news',
102
        ),
103
        //11 => "editnews",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
104
        array(
105
            'name' => 'editnews',
106
            'description' => 'Right to edit news',
107
        ),
108
        //12 => "delnews",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
109
        array(
110
            'name' => 'delnews',
111
            'description' => 'Right to delete news',
112
        ),
113
        //13 => "addcateg",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
114
        array(
115
            'name' => 'addcateg',
116
            'description' => 'Right to add categories',
117
        ),
118
        //14 => "editcateg",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
119
        array(
120
            'name' => 'editcateg',
121
            'description' => 'Right to edit categories',
122
        ),
123
        //15 => "delcateg",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
124
        array(
125
            'name' => 'delcateg',
126
            'description' => 'Right to delete categories',
127
        ),
128
        //16 => "passwd",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
129
        array(
130
            'name' => 'passwd',
131
            'description' => 'Right to change passwords',
132
        ),
133
        //17 => "editconfig",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
134
        array(
135
            'name' => 'editconfig',
136
            'description' => 'Right to edit configuration',
137
        ),
138
        //18 => "addatt", // Duplicate, removed with 2.7.3
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
139
        //array(
140
        //    'name' => 'addatt',
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
141
        //    'description' => 'Right to add attachments'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
142
        //),
143
        //19 => "backup delatt", // Duplicate, removed with 2.7.3
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
144
        //array(
145
        //    'name' => 'delatt',
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
146
        //    'description' => 'Right to delete attachments'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
147
        //),
148
        //20 => "backup",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
149
        array(
150
            'name' => 'backup',
151
            'description' => 'Right to save backups',
152
        ),
153
        //21 => "restore",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
154
        array(
155
            'name' => 'restore',
156
            'description' => 'Right to load backups',
157
        ),
158
        //22 => "delquestion",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
159
        array(
160
            'name' => 'delquestion',
161
            'description' => 'Right to delete questions',
162
        ),
163
        //23 => 'addglossary',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
164
        array(
165
            'name' => 'addglossary',
166
            'description' => 'Right to add glossary entries',
167
        ),
168
        //24 => 'editglossary',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
169
        array(
170
            'name' => 'editglossary',
171
            'description' => 'Right to edit glossary entries',
172
        ),
173
        //25 => 'delglossary'
174
        array(
175
            'name' => 'delglossary',
176
            'description' => 'Right to delete glossary entries',
177
        ),
178
        //26 => 'changebtrevs'
179
        array(
180
            'name' => 'changebtrevs',
181
            'description' => 'Right to edit revisions',
182
        ),
183
        //27 => "addgroup",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
184
        array(
185
            'name' => 'addgroup',
186
            'description' => 'Right to add group accounts',
187
        ),
188
        //28 => "editgroup",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
189
        array(
190
            'name' => 'editgroup',
191
            'description' => 'Right to edit group accounts',
192
        ),
193
        //29 => "delgroup",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
194
        array(
195
            'name' => 'delgroup',
196
            'description' => 'Right to delete group accounts',
197
        ),
198
        //30 => "addtranslation",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
199
        array(
200
            'name' => 'addtranslation',
201
            'description' => 'Right to add translation',
202
        ),
203
        //31 => "edittranslation",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
204
        array(
205
            'name' => 'edittranslation',
206
            'description' => 'Right to edit translations',
207
        ),
208
        //32 => "deltranslation",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
209
        array(
210
            'name' => 'deltranslation',
211
            'description' => 'Right to delete translations',
212
        ),
213
        // 33 => 'approverec'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
214
        array(
215
            'name' => 'approverec',
216
            'description' => 'Right to approve records',
217
        ),
218
        // 34 => 'addattachment'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
219
        array(
220
            'name' => 'addattachment',
221
            'description' => 'Right to add attachments',
222
        ),
223
        // 35 => 'editattachment'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
224
        array(
225
            'name' => 'editattachment',
226
            'description' => 'Right to edit attachments',
227
        ),
228
        // 36 => 'delattachment'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
229
        array(
230
            'name' => 'delattachment',
231
            'description' => 'Right to delete attachments',
232
        ),
233
        // 37 => 'dlattachment'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
234
        array(
235
            'name' => 'dlattachment',
236
            'description' => 'Right to download attachments',
237
        ),
238
        // 38 => 'dlattachment'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
239
        array(
240
            'name' => 'reports',
241
            'description' => 'Right to generate reports',
242
        ),
243
        // 39 => 'addfaq'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
244
        array(
245
            'name' => 'addfaq',
246
            'description' => 'Right to add FAQs in frontend',
247
        ),
248
        // 40 => 'addquestion'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
249
        array(
250
            'name' => 'addquestion',
251
            'description' => 'Right to add questions in frontend',
252
        ),
253
        // 41 => 'addcomment'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
254
        array(
255
            'name' => 'addcomment',
256
            'description' => 'Right to add comments in frontend',
257
        ),
258
        // 42 => 'editinstances'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
259
        array(
260
            'name' => 'editinstances',
261
            'description' => 'Right to edit multi-site instances',
262
        ),
263
        // 43 => 'addinstances'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
264
        array(
265
            'name' => 'addinstances',
266
            'description' => 'Right to add multi-site instances',
267
        ),
268
        // 44 => 'delinstances'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
269
        array(
270
            'name' => 'delinstances',
271
            'description' => 'Right to delete multi-site instances',
272
        ),
273
        // 45 => 'export'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
274
        array(
275
            'name' => 'export',
276
            'description' => 'Right to export the complete FAQ',
277
        ),
278
    );
279
280
    /**
281
     * Configuration array.
282
     *
283
     * @var array
284
     */
285
    protected $_mainConfig = array(
286
        'main.currentVersion' => null,
287
        'main.currentApiVersion' => null,
288
        'main.language' => '__PHPMYFAQ_LANGUAGE__',
289
        'main.languageDetection' => 'true',
290
        'main.phpMyFAQToken' => null,
291
        'main.referenceURL' => '__PHPMYFAQ_REFERENCE_URL__',
292
        'main.administrationMail' => '[email protected]',
293
        'main.contactInformations' => '',
294
        'main.enableAdminLog' => 'true',
295
        'main.enableRewriteRules' => 'false',
296
        'main.enableUserTracking' => 'true',
297
        'main.metaDescription' => 'phpMyFAQ should be the answer for all questions in life',
298
        'main.metaKeywords' => '',
299
        'main.metaPublisher' => '__PHPMYFAQ_PUBLISHER__',
300
        'main.send2friendText' => '',
301
        'main.titleFAQ' => 'phpMyFAQ Codename Proteus',
302
        'main.urlValidateInterval' => '86400',
303
        'main.enableWysiwygEditor' => 'true',
304
        'main.enableWysiwygEditorFrontend' => 'false',
305
        'main.enableMarkdownEditor' => 'false',
306
        'main.templateSet' => 'default',
307
        'main.optionalMailAddress' => 'false',
308
        'main.dateFormat' => 'Y-m-d H:i',
309
        'main.maintenanceMode' => 'false',
310
        'main.enableGravatarSupport' => 'false',
311
        'main.enableRssFeeds' => 'true',
312
        'main.enableGzipCompression' => 'true',
313
        'main.enableLinkVerification' => 'true',
314
        'main.customPdfHeader' => '',
315
        'main.customPdfHFooter' => '',
316
        'main.enableSmartAnswering' => 'true',
317
318
        'records.numberOfRecordsPerPage' => '10',
319
        'records.numberOfShownNewsEntries' => '3',
320
        'records.defaultActivation' => 'false',
321
        'records.defaultAllowComments' => 'false',
322
        'records.enableVisibilityQuestions' => 'false',
323
        'records.numberOfRelatedArticles' => '5',
324
        'records.orderby' => 'id',
325
        'records.sortby' => 'DESC',
326
        'records.orderingPopularFaqs' => 'visits',
327
        'records.disableAttachments' => 'true',
328
        'records.maxAttachmentSize' => '100000',
329
        'records.attachmentsPath' => 'attachments',
330
        'records.attachmentsStorageType' => '0',
331
        'records.enableAttachmentEncryption' => 'false',
332
        'records.defaultAttachmentEncKey' => '',
333
        'records.enableCloseQuestion' => 'false',
334
        'records.enableDeleteQuestion' => 'false',
335
        'records.autosaveActive' => 'false',
336
        'records.autosaveSecs' => '180',
337
        'records.randomSort' => 'false',
338
        'records.allowCommentsForGuests' => 'true',
339
        'records.allowQuestionsForGuests' => 'true',
340
        'records.allowNewFaqsForGuests' => 'true',
341
        'records.hideEmptyCategories' => 'false',
342
        'records.allowDownloadsForGuests' => 'false',
343
        'records.numberMaxStoredRevisions' => '10',
344
345
        'search.numberSearchTerms' => '10',
346
        'search.relevance' => 'thema,content,keywords',
347
        'search.enableRelevance' => 'false',
348
        'search.enableHighlighting' => 'true',
349
        'search.searchForSolutionId' => 'true',
350
        'search.enableElasticsearch' => 'false',
351
352
        'security.permLevel' => 'basic',
353
        'security.ipCheck' => 'false',
354
        'security.enableLoginOnly' => 'false',
355
        'security.ldapSupport' => 'false',
356
        'security.bannedIPs' => '',
357
        'security.ssoSupport' => 'false',
358
        'security.ssoLogoutRedirect' => '',
359
        'security.useSslForLogins' => 'false',
360
        'security.useSslOnly' => 'false',
361
        'security.forcePasswordUpdate' => 'false',
362
        'security.enableRegistration' => 'true',
363
364
        'spam.checkBannedWords' => 'true',
365
        'spam.enableCaptchaCode' => null,
366
        'spam.enableSafeEmail' => 'true',
367
        'spam.manualActivation' => 'true',
368
369
        'socialnetworks.enableTwitterSupport' => 'false',
370
        'socialnetworks.twitterConsumerKey' => '',
371
        'socialnetworks.twitterConsumerSecret' => '',
372
        'socialnetworks.twitterAccessTokenKey' => '',
373
        'socialnetworks.twitterAccessTokenSecret' => '',
374
        'socialnetworks.enableFacebookSupport' => 'false',
375
        'socialnetworks.disableAll' => 'false',
376
377
        'seo.metaTagsHome' => 'index, follow',
378
        'seo.metaTagsFaqs' => 'index, follow',
379
        'seo.metaTagsCategories' => 'index, follow',
380
        'seo.metaTagsPages' => 'index, follow',
381
        'seo.metaTagsAdmin' => 'noindex, nofollow',
382
    );
383
384
    /**
385
     * Constructor.
386
     *
387
     * @return PMF_Installer
388
     */
389
    public function __construct()
390
    {
391
        $this->_system = new PMF_System();
392
        $dynMainConfig = array(
393
            'main.currentVersion' => PMF_System::getVersion(),
394
            'main.currentApiVersion' => PMF_System::getApiVersion(),
395
            'main.phpMyFAQToken' => md5(uniqid(rand())),
396
            'spam.enableCaptchaCode' => (extension_loaded('gd') ? 'true' : 'false'),
397
        );
398
        $this->_mainConfig = array_merge($this->_mainConfig, $dynMainConfig);
399
    }
400
401
    /**
402
     * Check absolutely necessary stuff and die.
403
     */
404
    public function checkBasicStuff()
405
    {
406
        if (!$this->checkMinimumPhpVersion()) {
407
            printf(
408
                '<p class="alert alert-danger">Sorry, but you need PHP %s or later!</p>',
409
                PMF_System::VERSION_MINIMUM_PHP
410
            );
411
            PMF_System::renderFooter();
412
        }
413
414
        if (!function_exists('date_default_timezone_set')) {
415
            echo '<p class="alert alert-danger">Sorry, but setting a default timezone doesn\'t work in your environment!</p>';
416
            PMF_System::renderFooter();
417
        }
418
419 View Code Duplication
        if (!$this->_system->checkDatabase()) {
420
            echo '<p class="alert alert-danger">No supported database detected! Please install one of the following'.
421
                ' database systems and enable the corresponding PHP extension in php.ini:</p>';
422
            echo '<ul>';
423
            foreach ($this->_system->getSupportedDatabases() as $database) {
424
                printf('    <li>%s</li>', $database[1]);
425
            }
426
            echo '</ul>';
427
            PMF_System::renderFooter();
428
        }
429
430 View Code Duplication
        if (!$this->_system->checkRequiredExtensions()) {
431
            echo '<p class="alert alert-danger">The following extensions are missing! Please enable the PHP extension(s) in '.
432
                'php.ini.</p>';
433
            echo '<ul>';
434
            foreach ($this->_system->getMissingExtensions() as $extension) {
435
                printf('    <li>ext/%s</li>', $extension);
436
            }
437
            echo '</ul>';
438
            PMF_System::renderFooter();
439
        }
440
441
        if (!$this->_system->checkphpMyFAQInstallation()) {
442
            echo '<p class="alert alert-danger">It seems you\'re already running a version of phpMyFAQ. Please use the '.
443
                '<a href="update.php">update script</a>.</p>';
444
            PMF_System::renderFooter();
445
        }
446
    }
447
448
    /**
449
     * Checks for the minimum PHP requirement and if the database credentials file is readable.
450
     */
451
    public function checkPreUpgrade()
452
    {
453
        if (!$this->checkMinimumPhpVersion()) {
454
            printf(
455
                '<p class="alert alert-danger">Sorry, but you need PHP %s or later!</p>',
456
                PMF_System::VERSION_MINIMUM_PHP
457
            );
458
            PMF_System::renderFooter();
459
        }
460
461
        if (!is_readable(PMF_ROOT_DIR.'/inc/data.php') && !is_readable(PMF_ROOT_DIR.'/config/database.php')) {
462
            echo '<p class="alert alert-danger">It seems you never run a version of phpMyFAQ.<br>'.
463
                'Please use the <a href="setup.php">install script</a>.</p>';
464
            PMF_System::renderFooter();
465
        }
466
    }
467
468
    /**
469
     * Checks the minimum required PHP version, defined in PMF_System.
470
     *
471
     * @return bool
472
     */
473
    public function checkMinimumPhpVersion()
474
    {
475
        if (version_compare(PHP_VERSION, PMF_System::VERSION_MINIMUM_PHP, '<')) {
476
            return false;
477
        }
478
479
        return true;
480
    }
481
482
    /**
483
     * Checks if the file permissions are okay.
484
     */
485
    public function checkFilesystemPermissions()
486
    {
487
        $instanceSetup = new PMF_Instance_Setup();
488
        $instanceSetup->setRootDir(PMF_ROOT_DIR);
489
490
        $dirs = array('/attachments', '/config', '/data', '/images');
491
        $failedDirs = $instanceSetup->checkDirs($dirs);
492
        $numDirs = sizeof($failedDirs);
493
494
        if (1 <= $numDirs) {
495
            printf(
496
                '<p class="alert alert-danger">The following %s could not be created or %s not writable:</p><ul>',
497
                (1 < $numDirs) ? 'directories' : 'directory',
498
                (1 < $numDirs) ? 'are' : 'is'
499
            );
500
            foreach ($failedDirs as $dir) {
501
                echo "<li>$dir</li>\n";
502
            }
503
            printf(
504
                '</ul><p class="alert alert-danger">Please create %s manually and/or change access to chmod 775 (or '.
505
                    'greater if necessary).</p>',
506
                (1 < $numDirs) ? 'them' : 'it'
507
            );
508
            PMF_System::renderFooter();
509
        }
510
    }
511
512
    /**
513
     * Checks some non critical settings and print some hints.
514
     *
515
     * @todo We should return an array of messages
516
     */
517
    public function checkNoncriticalSettings()
518
    {
519 View Code Duplication
        if ((@ini_get('safe_mode') == 'On' || @ini_get('safe_mode') === 1)) {
520
            echo '<p class="alert alert-danger">The PHP safe mode is enabled. You may have problems when phpMyFAQ tries to write '.
521
                ' in some directories.</p>';
522
        }
523
        if (!extension_loaded('gd')) {
524
            echo '<p class="alert alert-danger">You don\'t have GD support enabled in your PHP installation. Please enable GD '.
525
                'support in your php.ini file otherwise you can\'t use Captchas for spam protection.</p>';
526
        }
527
        if (!function_exists('imagettftext')) {
528
            echo '<p class="alert alert-danger">You don\'t have Freetype support enabled in the GD extension of your PHP '.
529
                'installation. Please enable Freetype support in GD extension otherwise the Captchas for spam '.
530
                'protection will be quite easy to break.</p>';
531
        }
532
        if (!extension_loaded('curl') || !extension_loaded('openssl')) {
533
            echo '<p class="alert alert-danger">You don\'t have cURL and/or OpenSSL support enabled in your PHP installation. '.
534
                'Please enable cURL and/or OpenSSL support in your php.ini file otherwise you can\'t use the Twitter '.
535
                ' support or Elasticsearch.</p>';
536
        }
537
        if (!extension_loaded('fileinfo')) {
538
            echo '<p class="alert alert-danger">You don\'t have Fileinfo support enabled in your PHP installation. '.
539
                'Please enable Fileinfo support in your php.ini file otherwise you can\'t use our backup/restore '.
540
                'functionality.</p>';
541
        }
542
    }
543
544
    /**
545
     * Checks if we can store data via sessions. If not, e.g. an user can't
546
     * login into the admin section.
547
     *
548
     * @return bool
549
     */
550
    public function checkSessionSettings()
551
    {
552
        return true;
553
    }
554
555
    /**
556
     * Starts the installation.
557
     *
558
     * @param array $DB
559
     */
560
    public function startInstall(Array $DB = null)
561
    {
562
        $query = $uninst = $dbSetup = [];
563
564
        // Check table prefix
565
        $dbSetup['dbPrefix'] = PMF_Filter::filterInput(INPUT_POST, 'sqltblpre', FILTER_SANITIZE_STRING, '');
566
        if ('' !== $dbSetup['dbPrefix']) {
567
            PMF_Db::setTablePrefix($dbSetup['dbPrefix']);
568
        }
569
570
        // Check database entries
571
        $dbSetup['dbType'] = PMF_Filter::filterInput(INPUT_POST, 'sql_type', FILTER_SANITIZE_STRING);
572
        if (!is_null($dbSetup['dbType'])) {
573
            $dbSetup['dbType'] = trim($dbSetup['dbType']);
574
            if (!file_exists(PMF_INCLUDE_DIR.'/PMF/Instance/Database/'.ucfirst($dbSetup['dbType']).'.php')) {
575
                printf(
576
                    '<p class="alert alert-danger"><strong>Error:</strong> Invalid server type: %s</p>',
577
                    $dbSetup['dbType']
578
                );
579
                PMF_System::renderFooter(true);
580
            }
581
        } else {
582
            echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please select a database type.</p>\n";
583
            PMF_System::renderFooter(true);
584
        }
585
586
        $dbSetup['dbServer'] = PMF_Filter::filterInput(INPUT_POST, 'sql_server', FILTER_SANITIZE_STRING);
587 View Code Duplication
        if (is_null($dbSetup['dbServer']) && !PMF_System::isSqlite($dbSetup['dbType'])) {
588
            echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a database server.</p>\n";
589
            PMF_System::renderFooter(true);
590
        }
591
592
        $dbSetup['dbUser'] = PMF_Filter::filterInput(INPUT_POST, 'sql_user', FILTER_SANITIZE_STRING);
593 View Code Duplication
        if (is_null($dbSetup['dbUser']) && !PMF_System::isSqlite($dbSetup['dbType'])) {
594
            echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a database username.</p>\n";
595
            PMF_System::renderFooter(true);
596
        }
597
598
        $dbSetup['dbPassword'] = PMF_Filter::filterInput(INPUT_POST, 'sql_password', FILTER_UNSAFE_RAW);
599
        if (is_null($dbSetup['dbPassword']) && !PMF_System::isSqlite($dbSetup['dbType'])) {
600
            // Password can be empty...
601
            $dbSetup['dbPassword'] = '';
602
        }
603
604
        $dbSetup['dbDatabaseName'] = PMF_Filter::filterInput(INPUT_POST, 'sql_db', FILTER_SANITIZE_STRING);
605 View Code Duplication
        if (is_null($dbSetup['dbDatabaseName']) && !PMF_System::isSqlite($dbSetup['dbType'])) {
606
            echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a database name.</p>\n";
607
            PMF_System::renderFooter(true);
608
        }
609
610
        if (PMF_System::isSqlite($dbSetup['dbType'])) {
611
            $dbSetup['dbServer'] = PMF_Filter::filterInput(INPUT_POST, 'sql_sqlitefile', FILTER_SANITIZE_STRING);
612
            if (is_null($dbSetup['dbServer'])) {
613
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a SQLite database filename.</p>\n";
614
                PMF_System::renderFooter(true);
615
            }
616
        }
617
618
        // check database connection
619
        PMF_Db::setTablePrefix($dbSetup['dbPrefix']);
620
        $db = PMF_Db::factory($dbSetup['dbType']);
621
        $db->connect($dbSetup['dbServer'], $dbSetup['dbUser'], $dbSetup['dbPassword'], $dbSetup['dbDatabaseName']);
622
        if (!$db) {
623
            printf("<p class=\"alert alert-danger\"><strong>DB Error:</strong> %s</p>\n", $db->error());
624
            PMF_System::renderFooter(true);
625
        }
626
627
        $configuration = new PMF_Configuration($db);
628
629
        //
630
        // Check LDAP if enabled
631
        //
632
        $ldapEnabled = PMF_Filter::filterInput(INPUT_POST, 'ldap_enabled', FILTER_SANITIZE_STRING);
633
        if (extension_loaded('ldap') && !is_null($ldapEnabled)) {
634
            $ldapSetup = [];
635
636
            // check LDAP entries
637
            $ldapSetup['ldapServer'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_server', FILTER_SANITIZE_STRING);
638
            if (is_null($ldapSetup['ldapServer'])) {
639
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a LDAP server.</p>\n";
640
                PMF_System::renderFooter(true);
641
            }
642
643
            $ldapSetup['ldapPort'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_port', FILTER_VALIDATE_INT);
644
            if (is_null($ldapSetup['ldapPort'])) {
645
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a LDAP port.</p>\n";
646
                PMF_System::renderFooter(true);
647
            }
648
649
            $ldapSetup['ldapBase'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_base', FILTER_SANITIZE_STRING);
650
            if (is_null($ldapSetup['ldapBase'])) {
651
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a LDAP base search DN.</p>\n";
652
                PMF_System::renderFooter(true);
653
            }
654
655
            // LDAP User and LDAP password are optional
656
            $ldapSetup['ldapUser'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_user', FILTER_SANITIZE_STRING, '');
657
            $ldapSetup['ldapPassword'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_password', FILTER_SANITIZE_STRING, '');
658
659
            // check LDAP connection
660
            require PMF_ROOT_DIR.'/inc/PMF/Ldap.php';
661
            $ldap = new PMF_Ldap($configuration);
662
            $ldap->connect(
663
                $ldapSetup['ldapServer'],
664
                $ldapSetup['ldapPort'],
665
                $ldapSetup['ldapBase'],
666
                $ldapSetup['ldapUser'],
667
                $ldapSetup['ldapPassword']
668
            );
669
            if (!$ldap) {
670
                echo '<p class="alert alert-danger"><strong>LDAP Error:</strong> '.$ldap->error()."</p>\n";
671
                PMF_System::renderFooter(true);
672
            }
673
        }
674
675
676
        //
677
        // Check Elasticsearch if enabled
678
        //
679
        $esEnabled = PMF_Filter::filterInput(INPUT_POST, 'elasticsearch_enabled', FILTER_SANITIZE_STRING);
680
        if (!is_null($esEnabled)) {
681
            $esSetup = [];
682
            $esHostFilter = [
683
                'elasticsearch_server' => [
684
                    'filter' => FILTER_SANITIZE_STRING,
685
                    'flags' => FILTER_REQUIRE_ARRAY
686
                ]
687
            ];
688
689
            // ES hosts
690
            $esHosts = PMF_Filter::filterInputArray(INPUT_POST, $esHostFilter);
691
            if (is_null($esHosts)) {
692
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add at least one Elasticsearch host.</p>\n";
693
                PMF_System::renderFooter(true);
694
            }
695
696
            $esSetup['hosts'] = $esHosts['elasticsearch_server'];
697
698
            // ES Index name
699
            $esSetup['index'] = PMF_Filter::filterInput(INPUT_POST, 'elasticsearch_index', FILTER_SANITIZE_STRING);
700
            if (is_null($esSetup['index'])) {
701
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add an Elasticsearch index name.</p>\n";
702
                PMF_System::renderFooter(true);
703
            }
704
705
            require_once PMF_INCLUDE_DIR.'/libs/react/promise/src/functions.php';
706
707
            $psr4Loader = new Psr4ClassLoader();
708
            $psr4Loader->addPrefix('Elasticsearch', PMF_INCLUDE_DIR.'/libs/elasticsearch/src/Elasticsearch');
709
            $psr4Loader->addPrefix('GuzzleHttp\\Ring\\', PMF_INCLUDE_DIR.'/libs/guzzlehttp/ringphp/src');
710
            $psr4Loader->addPrefix('Monolog', PMF_INCLUDE_DIR.'/libs/monolog/src/Monolog');
711
            $psr4Loader->addPrefix('Psr', PMF_INCLUDE_DIR.'/libs/psr/log/Psr');
712
            $psr4Loader->addPrefix('React\\Promise\\', PMF_INCLUDE_DIR.'/libs/react/promise/src');
713
            $psr4Loader->register();
714
715
            // check LDAP connection
716
            $esHosts = array_values($esHosts['elasticsearch_server']);
717
            $esClient = ClientBuilder::create()
718
                ->setHosts($esHosts)
719
                ->build();
720
721
            if (!$esClient) {
722
                echo '<p class="alert alert-danger"><strong>Elasticsearch Error:</strong> No connection.</p>';
723
                PMF_System::renderFooter(true);
724
            }
725
        } else {
726
            $esSetup = [];
727
        }
728
729
        // check loginname
730
        $loginname = PMF_Filter::filterInput(INPUT_POST, 'loginname', FILTER_SANITIZE_STRING);
731
        if (is_null($loginname)) {
732
            echo '<p class="alert alert-danger"><strong>Error:</strong> Please add a loginname for your account.</p>';
733
            PMF_System::renderFooter(true);
734
        }
735
736
        // check user entries
737
        $password = PMF_Filter::filterInput(INPUT_POST, 'password', FILTER_SANITIZE_STRING);
738
        if (is_null($password)) {
739
            echo '<p class="alert alert-danger"><strong>Error:</strong> Please add a password for the your account.</p>';
740
            PMF_System::renderFooter(true);
741
        }
742
743
        $password_retyped = PMF_Filter::filterInput(INPUT_POST, 'password_retyped', FILTER_SANITIZE_STRING);
744
        if (is_null($password_retyped)) {
745
            echo '<p class="alert alert-danger"><strong>Error:</strong> Please add a retyped password.</p>';
746
            PMF_System::renderFooter(true);
747
        }
748
749
        if (strlen($password) <= 5 || strlen($password_retyped) <= 5) {
750
            echo '<p class="alert alert-danger"><strong>Error:</strong> Your password and retyped password are too short.'.
751
                ' Please set your password and your retyped password with a minimum of 6 characters.</p>';
752
            PMF_System::renderFooter(true);
753
        }
754
        if ($password != $password_retyped) {
755
            echo '<p class="alert alert-danger"><strong>Error:</strong> Your password and retyped password are not equal.'.
756
                ' Please check your password and your retyped password.</p>';
757
            PMF_System::renderFooter(true);
758
        }
759
760
        $language = PMF_Filter::filterInput(INPUT_POST, 'language', FILTER_SANITIZE_STRING, 'en');
761
        $realname = PMF_Filter::filterInput(INPUT_POST, 'realname', FILTER_SANITIZE_STRING, '');
762
        $email = PMF_Filter::filterInput(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL, '');
763
        $permLevel = PMF_Filter::filterInput(INPUT_POST, 'permLevel', FILTER_SANITIZE_STRING, 'basic');
764
765
        $instanceSetup = new PMF_Instance_Setup();
766
        $instanceSetup->setRootDir(PMF_ROOT_DIR);
767
768
        // Write the DB variables in database.php
769
        if (!$instanceSetup->createDatabaseFile($dbSetup)) {
770
            echo '<p class="alert alert-danger"><strong>Error:</strong> Setup cannot write to ./config/database.php.</p>';
771
            $this->_system->cleanInstallation();
772
            PMF_System::renderFooter(true);
773
        }
774
775
        // check LDAP is enabled
776 View Code Duplication
        if (extension_loaded('ldap') && !is_null($ldapEnabled) && count($ldapSetup)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
777
            if (!$instanceSetup->createLdapFile($ldapSetup, '')) {
778
                echo '<p class="alert alert-danger"><strong>Error:</strong> Setup cannot write to ./config/ldap.php.</p>';
779
                $this->_system->cleanInstallation();
780
                PMF_System::renderFooter(true);
781
            }
782
        }
783
784
        // check if Elasticsearch is enabled
785 View Code Duplication
        if (!is_null($esEnabled) && count($esSetup)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
786
            if (!$instanceSetup->createElasticsearchFile($esSetup, '')) {
787
                echo '<p class="alert alert-danger"><strong>Error:</strong> Setup cannot write to ./config/elasticsearch.php.</p>';
788
                $this->_system->cleanInstallation();
789
                PMF_System::renderFooter(true);
790
            }
791
        }
792
793
        // connect to the database using config/database.php
794
        require PMF_ROOT_DIR.'/config/database.php';
795
        $db = PMF_Db::factory($dbSetup['dbType']);
796
        $db->connect($DB['server'], $DB['user'], $DB['password'], $DB['db']);
797
        if (!$db) {
798
            printf("<p class=\"alert alert-danger\"><strong>DB Error:</strong> %s</p>\n", $db->error());
799
            $this->_system->cleanInstallation();
800
            PMF_System::renderFooter(true);
801
        }
802
803
        $databaseInstaller = PMF_Instance_Database::factory($configuration, $dbSetup['dbType']);
804
        $databaseInstaller->createTables($dbSetup['dbPrefix']);
805
806
        $stopwords = new PMF_Instance_Database_Stopwords($configuration);
807
        $stopwords->executeInsertQueries($dbSetup['dbPrefix']);
808
809
        $this->_system->setDatabase($db);
810
811
        echo '<p>';
812
813
        // Erase any table before starting creating the required ones
814
        if (!PMF_System::isSqlite($dbSetup['dbType'])) {
815
            $this->_system->dropTables($uninst);
816
        }
817
818
        // Start creating the required tables
819
        $count = 0;
820
        foreach ($query as $executeQuery) {
821
            $result = @$db->query($executeQuery);
822 View Code Duplication
            if (!$result) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
823
                echo '<p class="alert alert-danger"><strong>Error:</strong> Please install your version of phpMyFAQ once again or send
824
            us a <a href=\"http://www.phpmyfaq.de\" target=\"_blank\">bug report</a>.</p>';
825
                printf('<p class="alert alert-danger"><strong>DB error:</strong> %s</p>', $db->error());
826
                printf('<code>%s</code>', htmlentities($executeQuery));
827
                $this->_system->dropTables($uninst);
828
                $this->_system->cleanInstallation();
829
                PMF_System::renderFooter(true);
830
            }
831
            usleep(1000);
832
            ++$count;
833
            if (!($count % 10)) {
834
                echo '| ';
835
            }
836
        }
837
838
        $link = new PMF_Link(null, $configuration);
839
840
        // add main configuration, add personal settings
841
        $this->_mainConfig['main.metaPublisher'] = $realname;
842
        $this->_mainConfig['main.administrationMail'] = $email;
843
        $this->_mainConfig['main.language'] = $language;
844
        $this->_mainConfig['security.permLevel'] = $permLevel;
845
846
        foreach ($this->_mainConfig as $name => $value) {
847
            $configuration->add($name, $value);
848
        }
849
850
        $configuration->update(array('main.referenceURL' => $link->getSystemUri('/setup/index.php')));
851
        $configuration->add('security.salt', md5($configuration->getDefaultUrl()));
852
853
        // add admin account and rights
854
        $admin = new PMF_User($configuration);
855 View Code Duplication
        if (!$admin->createUser($loginname, $password, 1)) {
856
            printf(
857
                '<p class="alert alert-danger"><strong>Fatal installation error:</strong><br>'.
858
                "Couldn't create the admin user: %s</p>\n",
859
                $admin->error()
860
            );
861
            $this->_system->cleanInstallation();
862
            PMF_System::renderFooter(true);
863
        }
864
        $admin->setStatus('protected');
865
        $adminData = array(
866
            'display_name' => $realname,
867
            'email' => $email,
868
        );
869
        $admin->setUserData($adminData);
870
871
        // add default rights
872
        foreach ($this->_mainRights as $right) {
873
            $admin->perm->grantUserRight(1, $admin->perm->addRight($right));
874
        }
875
876
        // Add anonymous user account
877
        $instanceSetup->createAnonymousUser($configuration);
878
879
        // Add master instance
880
        $instanceData = array(
881
            'url' => $link->getSystemUri($_SERVER['SCRIPT_NAME']),
882
            'instance' => $link->getSystemRelativeUri('setup/index.php'),
883
            'comment' => 'phpMyFAQ '.PMF_System::getVersion(),
884
        );
885
        $faqInstance = new PMF_Instance($configuration);
886
        $faqInstance->addInstance($instanceData);
887
888
        $faqInstanceMaster = new PMF_Instance_Master($configuration);
889
        $faqInstanceMaster->createMaster($faqInstance);
890
891
        // connect to Elasticsearch if enabled
892
        if (!is_null($esEnabled) && is_file(PMF_ROOT_DIR.'/config/elasticsearch.php')) {
893
            require PMF_ROOT_DIR.'/config/elasticsearch.php';
894
895
            $configuration->setElasticsearchConfig($PMF_ES);
0 ignored issues
show
Bug introduced by
The variable $PMF_ES does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
896
897
            $esClient = ClientBuilder::create()
898
                ->setHosts($PMF_ES['hosts'])
899
                ->build();
900
901
            $configuration->setElasticsearch($esClient);
902
903
            $faqInstanceElasticsearch = new PMF_Instance_Elasticsearch($configuration);
904
            $faqInstanceElasticsearch->createIndex();
905
        }
906
907
        echo '</p>';
908
    }
909
910
    /**
911
     * Cleanup all files after an installation.
912
     */
913
    public function cleanUpFiles()
914
    {
915
        // Remove 'setup.php' file
916
        if (@unlink(basename($_SERVER['SCRIPT_NAME']))) {
917
            echo "<p class=\"alert alert-success\">The file <em>./setup/index.php</em> was deleted automatically.</p>\n";
918
        } else {
919
            echo "<p class=\"alert alert-danger\">Please delete the file <em>./setup/index.php</em> manually.</p>\n";
920
        }
921
        // Remove 'update.php' file
922
        if (@unlink(dirname($_SERVER['PATH_TRANSLATED']).'/update.php')) {
923
            echo "<p class=\"alert alert-success\">The file <em>./setup/update.php</em> was deleted automatically.</p>\n";
924
        } else {
925
            echo "<p class=\"alert alert-danger\">Please delete the file <em>./setup/update.php</em> manually.</p>\n";
926
        }
927
    }
928
}
929