Skip to content

Commit

Permalink
feat: add CheckPhpIni class
Browse files Browse the repository at this point in the history
  • Loading branch information
kenjis committed Feb 27, 2024
1 parent 89f0360 commit efb9e42
Show file tree
Hide file tree
Showing 2 changed files with 214 additions and 0 deletions.
151 changes: 151 additions & 0 deletions system/Security/CheckPhpIni.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

declare(strict_types=1);

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Security;

use CodeIgniter\CLI\CLI;
use CodeIgniter\View\Table;

/**
* Checks php.ini settings
*
* @used-by \CodeIgniter\Commands\Utilities\PhpIniCheck
* @see \CodeIgniter\Security\CheckPhpIniTest
*/
class CheckPhpIni
{
/**
* @param bool $isCli Set false if you run via Web
*
* @return string|void HTML string or void in CLI
*/
public static function run(bool $isCli = true)
{
$output = static::checkIni();

$thead = ['Directive', 'Global', 'Current', 'Recommended', 'Remark'];
$tbody = [];

// CLI
if ($isCli) {
self::outputForCli($output, $thead, $tbody);

return;
}

// Web
return self::outputForWeb($output, $thead, $tbody);
}

private static function outputForCli(array $output, array $thead, array $tbody): void
{
foreach ($output as $directive => $values) {
$current = $values['current'];
$notRecommended = false;

if ($values['recommended'] !== '') {
if ($values['recommended'] !== $values['current']) {
$notRecommended = true;
}

$current = $notRecommended
? CLI::color($values['current'] === '' ? 'n/a' : $values['current'], 'red')
: $values['current'];
}

$directive = $notRecommended ? CLI::color($directive, 'red') : $directive;
$tbody[] = [
$directive, $values['global'], $current, $values['recommended'], $values['remark'],
];
}

CLI::table($tbody, $thead);
}

private static function outputForWeb(array $output, array $thead, array $tbody): string
{
foreach ($output as $directive => $values) {
$current = $values['current'];
$notRecommended = false;

if ($values['recommended'] !== '') {
if ($values['recommended'] !== $values['current']) {
$notRecommended = true;
}

if ($values['current'] === '') {
$current = 'n/a';
}

$current = $notRecommended
? '<span style="color: red">' . $current . '</span>'
: $current;
}

$directive = $notRecommended
? '<span style="color: red">' . $directive . '</span>'
: $directive;
$tbody[] = [
$directive, $values['global'], $current, $values['recommended'], $values['remark'],
];
}

$table = new Table();
$template = [
'table_open' => '<table border="1" cellpadding="4" cellspacing="0">',
];
$table->setTemplate($template);

$table->setHeading($thead);

return '<pre>' . $table->generate($tbody) . '</pre>';
}

/**
* @internal Used for testing purposes only.
* @testTag
*/
public static function checkIni(): array
{
$items = [
'error_reporting' => ['recommended' => '5111'],
'display_errors' => ['recommended' => '0'],
'display_startup_errors' => ['recommended' => '0'],
'log_errors' => [],
'error_log' => [],
'default_charset' => ['recommended' => 'UTF-8'],
'memory_limit' => ['remark' => '> post_max_size'],
'post_max_size' => ['remark' => '> upload_max_filesize'],
'upload_max_filesize' => ['remark' => '< post_max_size'],
'request_order' => ['recommended' => 'GP'],
'variables_order' => ['recommended' => 'GPCS'],
'date.timezone' => ['recommended' => 'UTC'],
'mbstring.language' => ['recommended' => 'neutral'],
];

$output = [];
$ini = ini_get_all();

foreach ($items as $key => $values) {
$output[$key] = [
'global' => $ini[$key]['global_value'],
'current' => $ini[$key]['local_value'],
'recommended' => $values['recommended'] ?? '',
'remark' => $values['remark'] ?? '',
];
}

// [directive => [current_value, recommended_value]]
return $output;
}
}
63 changes: 63 additions & 0 deletions tests/system/Security/CheckPhpIniTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Security;

use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\Mock\MockInputOutput;

/**
* @internal
*
* @group Others
*/
final class CheckPhpIniTest extends CIUnitTestCase
{
public function testCheckIni()
{
$output = CheckPhpIni::checkIni();

$expected = [
'global' => '',
'current' => '1',
'recommended' => '0',
'remark' => '',
];
$this->assertSame($expected, $output['display_errors']);
}

public function testRunCli()
{
// Set MockInputOutput to CLI.
$io = new MockInputOutput();
CLI::setInputOutput($io);

CheckPhpIni::run(true);

// Get the whole output string.
$output = $io->getOutput();

$this->assertStringContainsString('display_errors', $output);

// Remove MockInputOutput.
CLI::resetInputOutput();
}

public function testRunWeb()
{
$output = CheckPhpIni::run(false);

$this->assertStringContainsString('display_errors', $output);
}
}

0 comments on commit efb9e42

Please sign in to comment.