Passed
Push — fix-9163 ( 64dde5...3df94b )
by Sam
17:47 queued 10:54
created

Installer::writeConfigYaml()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 31
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 22
nc 2
nop 1
dl 0
loc 31
rs 9.568
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Dev\Install;
4
5
use Exception;
6
use SilverStripe\Control\Cookie;
7
use SilverStripe\Control\HTTPApplication;
8
use SilverStripe\Control\HTTPRequest;
9
use SilverStripe\Control\HTTPRequestBuilder;
10
use SilverStripe\Core\Convert;
11
use SilverStripe\Core\CoreKernel;
12
use SilverStripe\Core\EnvironmentLoader;
13
use SilverStripe\Core\Kernel;
14
use SilverStripe\Core\Path;
15
use SilverStripe\ORM\DatabaseAdmin;
16
use SilverStripe\Security\DefaultAdminService;
17
use SilverStripe\Security\Security;
18
use SilverStripe\Control\Middleware\URLSpecialsMiddleware\SessionEnvTypeSwitcher;
19
20
/**
21
 * This installer doesn't use any of the fancy SilverStripe stuff in case it's unsupported.
22
 */
23
class Installer
24
{
25
    use InstallEnvironmentAware;
26
    use SessionEnvTypeSwitcher;
27
28
    /**
29
     * Errors during install
30
     *
31
     * @var array
32
     */
33
    protected $errors = [];
34
35
    /**
36
     * value='' attribute placeholder for password fields
37
     */
38
    const PASSWORD_PLACEHOLDER = '********';
39
40
    public function __construct($basePath = null)
41
    {
42
        $this->initBaseDir($basePath);
43
    }
44
45
    /**
46
     * Installer error
47
     *
48
     * @param string $message
49
     */
50
    protected function error($message = null)
51
    {
52
        $this->errors[] = $message;
53
    }
54
55
    protected function installHeader()
56
    {
57
        $clientPath = RESOURCES_DIR . (PUBLIC_DIR
58
            ? '/vendor/silverstripe/framework/src/Dev/Install/client'
59
            : '/silverstripe/framework/src/Dev/Install/client');
60
        ?>
61
        <html>
62
        <head>
63
            <meta charset="utf-8"/>
64
            <title>Installing SilverStripe...</title>
65
            <link rel="stylesheet" type="text/css" href="<?=$clientPath; ?>/styles/install.css"/>
66
            <script src="//code.jquery.com/jquery-1.7.2.min.js"></script>
67
        </head>
68
        <body>
69
        <div class="install-header">
70
            <div class="inner">
71
                <div class="brand">
72
                    <h1>SilverStripe</h1>
73
                </div>
74
            </div>
75
        </div>
76
77
        <div id="Navigation">&nbsp;</div>
78
        <div class="clear"><!-- --></div>
79
80
        <div class="main">
81
            <div class="inner">
82
                <h2>Installing SilverStripe...</h2>
83
84
                <p>I am now running through the installation steps (this should take about 30 seconds)</p>
85
86
                <p>If you receive a fatal error, refresh this page to continue the installation</p>
87
                <ul>
88
        <?php
89
    }
90
91
    public function install($config)
92
    {
93
        // Render header
94
        $this->installHeader();
95
        $isIIS = $this->isIIS();
96
        $isApache = $this->isApache();
97
        $projectDir = $this->getProjectDir();
98
        $projectSrcDir = $this->getProjectSrcDir();
99
100
        flush();
101
102
        // Send install stats
103
        if (!empty($config['stats'])) {
104
            $this->sendInstallStats($config);
105
        }
106
107
        // Cleanup _config.php
108
        $basePath = $this->getBaseDir();
109
        $appConfigPath = $basePath . "{$projectDir}/_config.php";
110
        if (file_exists($appConfigPath)) {
111
            // Truncate the contents of _config instead of deleting it - we can't re-create it because Windows handles permissions slightly
112
            // differently to UNIX based filesystems - it takes the permissions from the parent directory instead of retaining them
113
            $fh = fopen($appConfigPath, 'wb');
114
            fclose($fh);
0 ignored issues
show
Bug introduced by
It seems like $fh can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, 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

114
            fclose(/** @scrutinizer ignore-type */ $fh);
Loading history...
115
        }
116
117
        // Write all files
118
        $this->writeIndexPHP();
119
        $this->writeConfigPHP($config);
120
        $this->writeConfigYaml($config);
121
        $this->writeConfigEnv($config);
122
123
        // Write other stuff
124
        if (!$this->checkModuleExists('cms')) {
125
            $rootURLControllerPath = $basePath . "{$projectSrcDir}/RootURLController.php";
126
            $this->writeToFile($rootURLControllerPath, <<<PHP
127
<?php
128
129
use SilverStripe\\Control\\Controller;
130
131
class RootURLController extends Controller
132
{
133
    public function index()
134
    {
135
        echo "<html>Your site is now set up. Start adding controllers to app/src to get started.</html>";
136
    }
137
}
138
PHP
139
            );
140
        }
141
142
        // Write the appropriate web server configuration file for rewriting support
143
        if ($this->hasRewritingCapability()) {
144
            if ($isApache) {
145
                $this->createHtaccess();
146
            } elseif ($isIIS) {
147
                $this->createWebConfig();
148
            }
149
        }
150
151
        // Build request
152
        $request = HTTPRequestBuilder::createFromEnvironment();
153
154
        // Install kernel (fix to dev)
155
        $kernel = new CoreKernel(Path::normalise($basePath));
156
        $kernel->setEnvironment(Kernel::DEV);
157
        $app = new HTTPApplication($kernel);
158
159
        // Build db within HTTPApplication
160
        $app->execute($request, function (HTTPRequest $request) use ($config) {
161
            // Suppress cookie errors on install
162
            Cookie::config()->set('report_errors', false);
163
164
            // Start session and execute
165
            $request->getSession()->init($request);
166
167
            // Output status
168
            $this->statusMessage("Building database schema...");
169
170
            // Setup DB
171
            $dbAdmin = new DatabaseAdmin();
172
            $dbAdmin->setRequest($request);
173
            $dbAdmin->pushCurrent();
174
            $dbAdmin->doInit();
175
            $dbAdmin->doBuild(true);
176
177
            // Create default administrator user and group in database
178
            // (not using Security::setDefaultAdmin())
179
            $username = $config['admin']['username'];
180
            $password = $config['admin']['password'];
181
            $adminMember = DefaultAdminService::singleton()
182
                ->findOrCreateAdmin(
183
                    $username,
184
                    _t('SilverStripe\\Security\\DefaultAdminService.DefaultAdminFirstname', 'Default Admin')
185
                );
186
            $adminMember->Email = $username;
187
            $adminMember->Password = $password;
188
            $adminMember->PasswordEncryption = Security::config()->get('encryption_algorithm');
189
190
            try {
191
                $this->statusMessage('Creating default CMS admin account...');
192
                $adminMember->write();
193
            } catch (Exception $e) {
194
                $this->statusMessage(
195
                    sprintf('Warning: Default CMS admin account could not be created (error: %s)', $e->getMessage())
196
                );
197
            }
198
199
            $request->getSession()->set('username', $username);
200
            $request->getSession()->set('password', $password);
201
            $request->getSession()->save($request);
202
        }, true);
203
204
        // Check result of install
205
        if (!$this->errors) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->errors of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
206
            // switch the session to Dev mode so that
207
            // flush does not require authentication
208
            // for the first time after installation
209
            $request['isDev'] = '1';
210
            $this->setSessionEnvType($request);
211
            unset($request['isDev']);
212
            $request->getSession()->save($request);
213
214
            if (isset($_SERVER['HTTP_HOST']) && $this->hasRewritingCapability()) {
215
                $this->statusMessage("Checking that friendly URLs work...");
216
                $this->checkRewrite();
217
            } else {
218
                $params = http_build_query($request->getVars() + ['flush' => '']);
219
220
                $destinationURL = 'index.php/' .
221
                    ($this->checkModuleExists('cms') ? "home/successfullyinstalled?$params" : "?$params");
222
223
                echo <<<HTML
224
                <li>SilverStripe successfully installed; I am now redirecting you to your SilverStripe site...</li>
225
                <script>
226
                    setTimeout(function() {
227
                        window.location = "$destinationURL";
228
                    }, 2000);
229
                </script>
230
                <noscript>
231
                <li><a href="$destinationURL">Click here to access your site.</a></li>
232
                </noscript>
233
HTML;
234
            }
235
        } else {
236
            // Output all errors
237
            $this->statusMessage('Encountered ' . count($this->errors) . ' errors during install:');
238
            echo "<ul>";
239
            foreach ($this->errors as $error) {
240
                $this->statusMessage($error);
241
            }
242
            echo "</ul>";
243
            $this->statusMessage('Please <a href="install.php">Click here</a> to return to the installer.');
244
        }
245
246
        return $this->errors;
247
    }
248
249
    protected function writeIndexPHP()
250
    {
251
        $content = <<<'PHP'
252
<?php
253
254
use SilverStripe\Control\HTTPApplication;
255
use SilverStripe\Control\HTTPRequestBuilder;
256
use SilverStripe\Core\CoreKernel;
257
258
// Find autoload.php
259
if (file_exists(__DIR__ . '/vendor/autoload.php')) {
260
    require __DIR__ . '/vendor/autoload.php';
261
} elseif (file_exists(__DIR__ . '/../vendor/autoload.php')) {
262
    require __DIR__ . '/../vendor/autoload.php';
263
} else {
264
    echo "autoload.php not found";
265
    die;
266
}
267
268
// Build request and detect flush
269
$request = HTTPRequestBuilder::createFromEnvironment();
270
271
// Default application
272
$kernel = new CoreKernel(BASE_PATH);
273
$app = new HTTPApplication($kernel);
274
$response = $app->handle($request);
275
$response->output();
276
PHP;
277
        $path = $this->getPublicDir() . 'index.php';
278
        $this->writeToFile($path, $content, true);
279
    }
280
281
    /**
282
     * Write all .env files
283
     *
284
     * @param $config
285
     */
286
    protected function writeConfigEnv($config)
287
    {
288
        if (!$config['usingEnv']) {
289
            return;
290
        }
291
292
        $path = $this->getBaseDir() . '.env';
293
        $vars = [];
294
295
        // Retain existing vars
296
        $env = new EnvironmentLoader();
297
        if (file_exists($path)) {
298
            $vars = $env->loadFile($path) ?: [];
299
        }
300
301
        // Set base URL
302
        if (!isset($vars['SS_BASE_URL']) && isset($_SERVER['HTTP_HOST'])) {
303
            $vars['SS_BASE_URL'] = 'http://' . $_SERVER['HTTP_HOST'] . BASE_URL;
304
        }
305
306
        // Set DB env
307
        if (empty($config['db']['database'])) {
308
            $vars['SS_DATABASE_CHOOSE_NAME'] = true;
309
        } else {
310
            $vars['SS_DATABASE_NAME'] = $config['db']['database'];
311
        }
312
        $vars['SS_DATABASE_CLASS'] = $config['db']['type'];
313
        if (isset($config['db']['server'])) {
314
            $vars['SS_DATABASE_SERVER'] = $config['db']['server'];
315
        }
316
        if (isset($config['db']['username'])) {
317
            $vars['SS_DATABASE_USERNAME'] = $config['db']['username'];
318
        }
319
        if (isset($config['db']['password'])) {
320
            $vars['SS_DATABASE_PASSWORD'] = $config['db']['password'];
321
        }
322
        if (isset($config['db']['path'])) {
323
            $vars['SS_DATABASE_PATH'] = $config['db']['path'];
324
            // sqlite compat
325
            $vars['SS_SQLITE_DATABASE_PATH'] = $config['db']['path'];
326
        }
327
        if (isset($config['db']['key'])) {
328
            $vars['SS_DATABASE_KEY'] = $config['db']['key'];
329
            // sqlite compat
330
            $vars['SS_SQLITE_DATABASE_KEY'] = $config['db']['key'];
331
        }
332
333
        // Write all env vars
334
        $lines = [
335
            '# Generated by SilverStripe Installer'
336
        ];
337
        ksort($vars);
338
        foreach ($vars as $key => $value) {
339
            $lines[] = $key . '="' . addcslashes($value, '"') . '"';
340
        }
341
342
        $this->writeToFile('.env', implode("\n", $lines));
343
344
        // Re-load env vars for installer access
345
        $env->loadFile($path);
346
    }
347
348
    /**
349
     * Write all *.php files
350
     *
351
     * @param array $config
352
     */
353
    protected function writeConfigPHP($config)
354
    {
355
        $configPath = $this->getProjectDir() . DIRECTORY_SEPARATOR . "_config.php";
356
        if ($config['usingEnv']) {
357
            $this->writeToFile($configPath, "<?php\n ");
358
            return;
359
        }
360
361
        // Create databaseConfig
362
        $lines = [];
363
        foreach ($config['db'] as $key => $value) {
364
            $lines[] = sprintf(
365
                "    '%s' => '%s'",
366
                addslashes($key),
367
                addslashes($value)
368
            );
369
        }
370
        $databaseConfigContent = implode(",\n", $lines);
371
        $this->writeToFile($configPath, <<<PHP
372
<?php
373
374
use SilverStripe\\ORM\\DB;
375
376
DB::setConfig([
377
{$databaseConfigContent}
378
]);
379
380
PHP
381
        );
382
    }
383
384
    /**
385
     * Write yml files
386
     *
387
     * @param array $config
388
     */
389
    protected function writeConfigYaml($config)
390
    {
391
        // Escape user input for safe insertion into PHP file
392
        $locale = $this->ymlString($config['locale']);
393
        $projectDir = $this->getProjectDir();
394
395
        // Set either specified, or no theme
396
        if ($config['theme'] && $config['theme'] !== 'tutorial') {
397
            $theme = $this->ymlString($config['theme']);
398
            $themeYML = <<<YML
399
    - '\$public'
400
    - '$theme'
401
    - '\$default'
402
YML;
403
        } else {
404
            $themeYML = <<<YML
405
    - '\$public'
406
    - '\$default'
407
YML;
408
        }
409
410
        // Write theme.yml
411
        $this->writeToFile("{$projectDir}/_config/theme.yml", <<<YML
412
---
413
Name: mytheme
414
---
415
SilverStripe\\View\\SSViewer:
416
  themes:
417
$themeYML
418
SilverStripe\\i18n\\i18n:
419
  default_locale: '$locale'
420
YML
421
        );
422
    }
423
424
    /**
425
     * Escape yml string
426
     *
427
     * @param string $string
428
     * @return mixed
429
     */
430
    protected function ymlString($string)
431
    {
432
        // just escape single quotes using ''
433
        return str_replace("'", "''", $string);
434
    }
435
436
    /**
437
     * Write file to given location
438
     *
439
     * @param string $filename
440
     * @param string $content
441
     * @param bool $absolute If $filename is absolute path set to true
442
     * @return bool
443
     */
444
    public function writeToFile($filename, $content, $absolute = false)
445
    {
446
        // Get absolute / relative paths by either combining or removing base from path
447
        list($absolutePath, $relativePath) = $absolute
448
            ? [
449
                $filename,
450
                substr($filename, strlen($this->getBaseDir()))]
451
            : [
452
                $this->getBaseDir() . $filename,
453
                $filename
454
            ];
455
        $this->statusMessage("Setting up $relativePath");
456
457
        if ((@$fh = fopen($absolutePath, 'wb')) && fwrite($fh, $content) && fclose($fh)) {
0 ignored issues
show
Bug introduced by
It seems like $fh can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, 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

457
        if ((@$fh = fopen($absolutePath, 'wb')) && fwrite($fh, $content) && fclose(/** @scrutinizer ignore-type */ $fh)) {
Loading history...
Bug introduced by
It seems like $fh can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, 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

457
        if ((@$fh = fopen($absolutePath, 'wb')) && fwrite(/** @scrutinizer ignore-type */ $fh, $content) && fclose($fh)) {
Loading history...
458
            // Set permissions to writable
459
            @chmod($absolutePath, 0775);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

459
            /** @scrutinizer ignore-unhandled */ @chmod($absolutePath, 0775);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
460
            return true;
461
        }
462
        $this->error("Couldn't write to file $relativePath");
463
        return false;
464
    }
465
466
    /**
467
     * Ensure root .htaccess is setup
468
     */
469
    public function createHtaccess()
470
    {
471
        $start = "### SILVERSTRIPE START ###\n";
472
        $end = "\n### SILVERSTRIPE END ###";
473
474
        $base = dirname($_SERVER['SCRIPT_NAME']);
475
        $base = Convert::slashes($base, '/');
476
477
        if ($base != '.') {
478
            $baseClause = "RewriteBase '$base'\n";
479
        } else {
480
            $baseClause = "";
481
        }
482
        if (strpos(strtolower(php_sapi_name()), "cgi") !== false) {
483
            $cgiClause = "RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]\n";
484
        } else {
485
            $cgiClause = "";
486
        }
487
        $rewrite = <<<TEXT
488
# Deny access to templates (but allow from localhost)
489
<Files *.ss>
490
    Order deny,allow
491
    Deny from all
492
    Allow from 127.0.0.1
493
</Files>
494
495
# Deny access to IIS configuration
496
<Files web.config>
497
    Order deny,allow
498
    Deny from all
499
</Files>
500
501
# Deny access to YAML configuration files which might include sensitive information
502
<Files ~ "\.ya?ml$">
503
    Order allow,deny
504
    Deny from all
505
</Files>
506
507
# Route errors to static pages automatically generated by SilverStripe
508
ErrorDocument 404 /assets/error-404.html
509
ErrorDocument 500 /assets/error-500.html
510
511
<IfModule mod_rewrite.c>
512
513
    # Turn off index.php handling requests to the homepage fixes issue in apache >=2.4
514
    <IfModule mod_dir.c>
515
        DirectoryIndex disabled
516
        DirectorySlash On
517
    </IfModule>
518
519
    SetEnv HTTP_MOD_REWRITE On
520
    RewriteEngine On
521
    $baseClause
522
    $cgiClause
523
524
    # Deny access to potentially sensitive files and folders
525
    RewriteRule ^vendor(/|$) - [F,L,NC]
526
    RewriteRule ^\.env - [F,L,NC]
527
    RewriteRule silverstripe-cache(/|$) - [F,L,NC]
528
    RewriteRule composer\.(json|lock) - [F,L,NC]
529
    RewriteRule (error|silverstripe|debug)\.log - [F,L,NC]
530
531
    # Process through SilverStripe if no file with the requested name exists.
532
    # Pass through the original path as a query parameter, and retain the existing parameters.
533
    # Try finding framework in the vendor folder first
534
    RewriteCond %{REQUEST_URI} ^(.*)$
535
    RewriteCond %{REQUEST_FILENAME} !-f
536
    RewriteRule .* index.php
537
</IfModule>
538
TEXT;
539
540
        $htaccessPath = $this->getPublicDir() . '.htaccess';
541
        if (file_exists($htaccessPath)) {
542
            $htaccess = file_get_contents($htaccessPath);
543
544
            if (strpos($htaccess, '### SILVERSTRIPE START ###') === false
545
                && strpos($htaccess, '### SILVERSTRIPE END ###') === false
546
            ) {
547
                $htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n";
548
            }
549
550
            if (strpos($htaccess, '### SILVERSTRIPE START ###') !== false
551
                && strpos($htaccess, '### SILVERSTRIPE END ###') !== false
552
            ) {
553
                $start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###'))
554
                    . "### SILVERSTRIPE START ###\n";
555
                $end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###'));
556
            }
557
        }
558
559
        $this->writeToFile($htaccessPath, $start . $rewrite . $end, true);
560
    }
561
562
    /**
563
     * Writes basic configuration to the web.config for IIS
564
     * so that rewriting capability can be use.
565
     */
566
    public function createWebConfig()
567
    {
568
        $content = <<<TEXT
569
<?xml version="1.0" encoding="utf-8"?>
570
<configuration>
571
    <system.webServer>
572
        <security>
573
            <requestFiltering>
574
                <hiddenSegments applyToWebDAV="false">
575
                    <add segment="silverstripe-cache" />
576
                    <add segment="composer.json" />
577
                    <add segment="composer.lock" />
578
                </hiddenSegments>
579
                <fileExtensions allowUnlisted="true" >
580
                    <add fileExtension=".ss" allowed="false"/>
581
                    <add fileExtension=".yml" allowed="false"/>
582
                </fileExtensions>
583
            </requestFiltering>
584
        </security>
585
        <rewrite>
586
            <rules>
587
                <rule name="SilverStripe Clean URLs" stopProcessing="true">
588
                    <match url="^(.*)$" />
589
                    <conditions>
590
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
591
                    </conditions>
592
                    <action type="Rewrite" url="index.php" appendQueryString="true" />
593
                </rule>
594
            </rules>
595
        </rewrite>
596
    </system.webServer>
597
</configuration>
598
TEXT;
599
600
        $path = $this->getPublicDir() . 'web.config';
601
        $this->writeToFile($path, $content, true);
602
    }
603
604
    public function checkRewrite()
605
    {
606
        $params = http_build_query(['flush' => '']);
607
608
        $destinationURL = rtrim(BASE_URL, '/') . '/' . (
609
            $this->checkModuleExists('cms')
610
                ? "home/successfullyinstalled?$params"
611
                : "?$params"
612
        );
613
614
        echo <<<HTML
615
<li id="ModRewriteResult">Testing...</li>
616
<script>
617
    if (typeof $ == 'undefined') {
618
        document.getElementById('ModeRewriteResult').innerHTML = "I can't run jQuery ajax to set rewriting; I will redirect you to the homepage to see if everything is working.";
619
        setTimeout(function() {
620
            window.location = "$destinationURL";
621
        }, 10000);
622
    } else {
623
        $.ajax({
624
            method: 'get',
625
            url: 'InstallerTest/testrewrite',
626
            complete: function(response) {
627
                var r = response.responseText.replace(/[^A-Z]?/g,"");
628
                if (r === "OK") {
629
                    $('#ModRewriteResult').html("Friendly URLs set up successfully; I am now redirecting you to your SilverStripe site...")
630
                    setTimeout(function() {
631
                        window.location = "$destinationURL";
632
                    }, 2000);
633
                } else {
634
                    $('#ModRewriteResult').html("Friendly URLs are not working. This is most likely because a rewrite module isn't configured "
635
                        + "correctly on your site. You may need to get your web host or server administrator to do this for you: "
636
                        + "<ul>"
637
                        + "<li><strong>mod_rewrite</strong> or other rewrite module is enabled on your web server</li>"
638
                        + "<li><strong>AllowOverride All</strong> is set for the directory where SilverStripe is installed</li>"
639
                        + "</ul>");
640
                }
641
            }
642
        });
643
    }
644
</script>
645
<noscript>
646
    <li><a href="$destinationURL">Click here</a> to check friendly URLs are working. If you get a 404 then something is wrong.</li>
647
</noscript>
648
HTML;
649
    }
650
651
    /**
652
     * Show an installation status message.
653
     * The output differs depending on whether this is CLI or web based
654
     *
655
     * @param string $msg
656
     */
657
    public function statusMessage($msg)
658
    {
659
        echo "<li>$msg</li>\n";
660
        flush();
661
    }
662
663
    /**
664
     * @param $config
665
     */
666
    protected function sendInstallStats($config)
667
    {
668
        // Try to determine the database version from the helper
669
        $dbType = $config['db']['type'];
670
        $helper = $this->getDatabaseConfigurationHelper($dbType);
671
        if ($helper) {
0 ignored issues
show
introduced by
$helper is of type SilverStripe\Dev\Install...baseConfigurationHelper, thus it always evaluated to true.
Loading history...
672
            $databaseVersion = $dbType . ': ' . $helper->getDatabaseVersion($config['db']);
673
        } else {
674
            $databaseVersion = $dbType;
675
        }
676
677
        $args = http_build_query(array_filter([
678
            'SilverStripe' => $config['version'],
679
            'PHP' => phpversion(),
680
            'Database' => $databaseVersion,
681
            'WebServer' => $this->findWebserver(),
682
            'ID' => empty($_SESSION['StatsID']) ? null : $_SESSION['StatsID']
683
        ]));
684
        $url = "http://ss2stat.silverstripe.com/Installation/add?{$args}";
685
        @$_SESSION['StatsID'] = file_get_contents($url);
686
    }
687
}
688