Completed
Push — master ( 079a66...ee0f97 )
by Andreas
14:21
created

midcom_config_test::add()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 3
dl 0
loc 7
ccs 5
cts 5
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package midcom
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
/**
10
 * Collection of simple helper methods for testing site configuration
11
 *
12
 * @package midcom
13
 */
14
class midcom_config_test
15
{
16
    const OK = 0;
17
    const WARNING = 1;
18
    const ERROR = 2;
19
20
    private $messages = [
21
        'midcom' => [],
22
        'php' => [],
23
        'external' => []
24
    ];
25
26
    private $section;
27
28
    private $status = self::OK;
29
30 1
    public function check()
31
    {
32 1
        $this->check_midcom();
33 1
        $this->check_php();
34 1
        $this->check_external();
35 1
    }
36
37 1
    public function get_status() : int
38
    {
39 1
        return $this->status;
40
    }
41
42 1
    private function add(string $testname, int $result_code, string $recommendations = '&nbsp;')
43
    {
44 1
        $this->messages[$this->section][$testname] = [
45 1
            'result' => $result_code,
46 1
            'message' => $recommendations
47
        ];
48 1
        $this->status = max($this->status, $result_code);
49 1
    }
50
51 1
    private function check_midcom()
52
    {
53 1
        $this->section = 'midcom';
54
55
        // Validate the Cache Base Directory.
56 1
        $cachedir = midcom::get()->config->get('cache_base_directory');
57 1
        if (!is_dir($cachedir)) {
58
            $this->add('MidCOM cache base directory', self::ERROR, "The configured MidCOM cache base directory ({$cachedir}) does not exist or is not a directory. You have to create it as a directory writable by the Apache user.");
59 1
        } elseif (!is_writable($cachedir)) {
60
            $this->add('MidCOM cache base directory', self::ERROR, "The configured MidCOM cache base directory ({$cachedir}) is not writable by the Apache user. You have to create it as a directory writable by the Apache user.");
61
        } else {
62 1
            $this->add('MidCOM cache base directory', self::OK, $cachedir);
0 ignored issues
show
Bug introduced by
It seems like $cachedir can also be of type null; however, parameter $recommendations of midcom_config_test::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

62
            $this->add('MidCOM cache base directory', self::OK, /** @scrutinizer ignore-type */ $cachedir);
Loading history...
63
        }
64
65 1
        $lang = midcom::get()->i18n->get_current_language();
66 1
        $locale = Locale::getDefault();
67 1
        if ($lang != substr($locale, 0, 2)) {
68
            $this->add('MidCOM language', self::WARNING, 'Language is set to "' . $lang . '", but the locale "' . $locale . '" is used. This might lead to problems in datamanager number inputs if decimal separators diverge');
69
        } else {
70 1
            $this->add('MidCOM language', self::OK, $locale);
71
        }
72
73 1
        $this->check_rcs();
74 1
    }
75
76 1
    private function check_rcs()
77
    {
78 1
        $config = midcom::get()->config;
79 1
        if ($config->get('midcom_services_rcs_enable')) {
80
            try {
81 1
                $config = new midcom_services_rcs_config($config);
82 1
                $config->test_rcs_config();
83 1
                $this->add("MidCOM RCS", self::OK);
84
            } catch (midcom_error $e) {
85 1
                $this->add("MidCOM RCS", self::ERROR, $e->getMessage());
86
            }
87
        } else {
88
            $this->add("MidCOM RCS", self::WARNING, "The MidCOM RCS service is disabled.");
89
        }
90 1
    }
91
92 1
    private function check_php()
93
    {
94 1
        $this->section = 'php';
95
96 1
        $cur_limit = $this->ini_get_filesize('memory_limit');
97 1
        if ($cur_limit >= (40 * 1024 * 1024)) {
98 1
            $this->add('Setting: memory_limit', self::OK, ini_get('memory_limit'));
99
        } else {
100
            $this->add('Setting: memory_limit', self::ERROR, "MidCOM requires a minimum memory limit of 40 MB to operate correctly. Smaller amounts will lead to PHP Errors. Detected limit was {$cur_limit}.");
101
        }
102
103 1
        $upload_limit = $this->ini_get_filesize('upload_max_filesize');
104 1
        if ($upload_limit >= (50 * 1024 * 1024)) {
105
            $this->add('Setting: upload_max_filesize', self::OK, ini_get('upload_max_filesize'));
106
        } else {
107 1
            $this->add('Setting: upload_max_filesize',
108 1
                             self::WARNING, "To make bulk uploads (for exampe in the Image Gallery) useful, you should increase the Upload limit to something above 50 MB. (Current setting: {$upload_limit})");
109
        }
110
111 1
        $post_limit = $this->ini_get_filesize('post_max_size');
112 1
        if ($post_limit >= $upload_limit) {
113 1
            $this->add('Setting: post_max_size', self::OK, ini_get('post_max_size'));
114
        } else {
115
            $this->add('Setting: post_max_size', self::WARNING, 'post_max_size should be larger than upload_max_filesize, as both limits apply during uploads.');
116
        }
117
118 1
        if (ini_get("opcache.enable") == "1") {
119 1
            $this->add("OPCache", self::OK);
120
        } else {
121
            $this->add("OPCache", self::WARNING, "OPCache is recommended for efficient MidCOM operation");
122
        }
123
124 1
        if (!class_exists('Memcached')) {
125 1
            $this->add('Memcache', self::WARNING, 'The PHP memcached module is recommended for efficient MidCOM operation.');
126
        } elseif (!midcom::get()->config->get('cache_module_memcache_backend')) {
127
            $this->add('Memcache', self::WARNING, 'The PHP memcached module is recommended for efficient MidCOM operation. It is available but is not set to be in use.');
128
        } elseif (midcom::get()->cache->memcache->is_operational()) {
0 ignored issues
show
Bug introduced by
The property memcache does not seem to exist on midcom_services_cache.
Loading history...
129
            $this->add('Memcache', self::OK);
130
        } else {
131
            $this->add('Memcache', self::ERROR, "The PHP memcached module is available and set to be in use, but it cannot be connected to.");
132
        }
133
134 1
        if (!function_exists('exif_read_data')) {
135
            $this->add('EXIF reader', self::WARNING, 'PHP-EXIF is not available. It required for proper operation of Image Gallery components.');
136
        } else {
137 1
            $this->add('EXIF reader', self::OK);
138
        }
139 1
    }
140
141 1
    private function ini_get_filesize(string $setting) : int
142
    {
143 1
        $result = ini_get($setting);
144 1
        $last_char = substr($result, -1);
145 1
        if ($last_char == 'M') {
146 1
            $result = substr($result, 0, -1) * 1024 * 1024;
147
        } elseif ($last_char == 'K') {
148
            $result = substr($result, 0, -1) * 1024;
149
        } elseif ($last_char == 'G') {
150
            $result = substr($result, 0, -1) * 1024 * 1024 * 1024;
151
        }
152 1
        return $result;
153
    }
154
155 1
    private function check_external()
156
    {
157 1
        $this->section = 'external';
158
        // ImageMagick
159 1
        $cmd = midcom::get()->config->get('utility_imagemagick_base') . "identify -version";
160 1
        exec($cmd, $output, $result);
161 1
        if ($result !== 0 && $result !== 1) {
162
            $this->add('ImageMagick', self::ERROR, 'The existence ImageMagick toolkit could not be verified, it is required for all kinds of image processing in MidCOM.');
163
        } else {
164 1
            $this->add('ImageMagick', self::OK);
165
        }
166
167 1
        $this->check_for_utility('jpegtran', self::WARNING, 'The jpegtran utility is used for lossless JPEG operations, even though ImageMagick can do the same conversions, the lossless features provided by this utility are used where appropriate, so its installation is recommended unless it is known to cause problems.', 'The jpegtran utility is used for lossless rotations of JPEG images. If there are problems with image rotations, disabling jpegtran, which will cause ImageMagick to be used instead, probably helps.');
168
169 1
        if (midcom::get()->config->get('indexer_backend')) {
170
            $this->check_for_utility('catdoc', self::ERROR, 'Catdoc is required to properly index Microsoft Word documents. It is strongly recommended to install it, otherwise Word documents will be indexed as binary files.');
171
            $this->check_for_utility('pdftotext', self::ERROR, 'pdftotext is required to properly index Adobe PDF documents. It is strongly recommended to install it, otherwise PDF documents will be indexed as binary files.');
172
            $this->check_for_utility('unrtf', self::ERROR, 'unrtf is required to properly index Rich Text Format documents. It is strongly recommended to install it, otherwise RTF documents will be indexed as binary files.');
173
        }
174 1
    }
175
176 1
    private function check_for_utility(string $testname, int $fail_code, string $fail_recommendations, string $recommendations = '&nbsp;')
177
    {
178 1
        $executable = midcom::get()->config->get("utility_{$testname}");
179 1
        if ($executable === null) {
180
            $this->add($testname, $fail_code, "The path to the utility {$testname} is not configured. {$fail_recommendations}");
181 1
        } elseif (!exec('which which')) {
182
            $this->add('which', self::ERROR, "The 'which' utility cannot be found.");
183
        } else {
184 1
            exec("which {$executable}", $output, $exitcode);
185 1
            if ($exitcode == 0) {
186
                $this->add($testname, self::OK, $recommendations);
187
            } else {
188 1
                $this->add($testname, $fail_code, "The utility {$testname} is not correctly configured: File ({$executable}) not found. {$fail_recommendations}");
189
            }
190
        }
191 1
    }
192
193
    public function show()
194
    {
195
        echo '<table>';
196
197
        $this->print_section('MidCOM ' . midcom::VERSION, $this->messages['midcom']);
198
        $this->print_section($_SERVER['SERVER_SOFTWARE'], $this->messages['php']);
199
        $this->print_section('External Utilities', $this->messages['external']);
200
201
        echo '</table>';
202
    }
203
204
    private function print_section(string $heading, array $messages)
205
    {
206
        echo "  <tr>\n";
207
        echo "    <th colspan=\"2\">{$heading}</th>\n";
208
        echo "  </tr>\n";
209
210
        foreach ($messages as $testname => $data) {
211
            echo "  <tr class=\"test\">\n    <th>\n";
212
            switch ($data['result']) {
213
                case self::OK:
214
                    echo "    <i class='fa fa-check' style='color: green;' title='OK'></i>";
215
                    break;
216
217
                case self::WARNING:
218
                    echo "    <i class='fa fa-exclamation-triangle' style='color: orange;' title='WARNING'></i>";
219
                    break;
220
221
                case self::ERROR:
222
                    echo "    <i class='fa fa-exclamation-circle' style='color: red;' title='ERROR'></i>";
223
                    break;
224
225
                default:
226
                    throw new midcom_error("Unknown error code {$data['result']}.");
227
            }
228
229
            echo " {$testname}</th>\n";
230
            echo "    <td>{$data['message']}</td>\n";
231
            echo "  </tr>\n";
232
        }
233
    }
234
}
235