<?php
/**
 * tests for methods under Config file generator
 */

declare(strict_types=1);

namespace PhpMyAdmin\Tests\Setup;

use PhpMyAdmin\Config\ConfigFile;
use PhpMyAdmin\Setup\ConfigGenerator;
use PhpMyAdmin\Tests\AbstractTestCase;
use ReflectionClass;

class ConfigGeneratorTest extends AbstractTestCase
{
    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp(): void
    {
        parent::setUp();
        parent::loadDefaultConfig();
    }

    /**
     * Test for ConfigGenerator::getConfigFile
     *
     * @group medium
     */
    public function testGetConfigFile(): void
    {
        unset($_SESSION['eol']);

        parent::setGlobalConfig();

        $GLOBALS['server'] = 0;
        $cf = new ConfigFile();
        $_SESSION['ConfigFile0'] = [
            'a',
            'b',
            'c',
        ];
        $_SESSION['ConfigFile0']['Servers'] = [
            [
                1,
                2,
                3,
            ],
        ];

        $cf->setPersistKeys(['1/', 2]);

        $result = ConfigGenerator::getConfigFile($cf);

        $this->assertStringContainsString(
            "<?php\n" .
            "/*\n" .
            " * Generated configuration file\n" .
            ' * Generated by: phpMyAdmin ' .
            $GLOBALS['PMA_Config']->get('PMA_VERSION') . " setup script\n",
            $result
        );

        $this->assertStringContainsString(
            "/* Servers configuration */\n" .
            '$i = 0;' . "\n\n" .
            "/* Server: localhost [0] */\n" .
            '$i++;' . "\n" .
            '$cfg[\'Servers\'][$i][\'0\'] = 1;' . "\n" .
            '$cfg[\'Servers\'][$i][\'1\'] = 2;' . "\n" .
            '$cfg[\'Servers\'][$i][\'2\'] = 3;' . "\n\n" .
            "/* End of servers configuration */\n\n",
            $result
        );

        $this->assertStringContainsString(
            '?>',
            $result
        );
    }

    /**
     * Test for ConfigGenerator::getVarExport
     */
    public function testGetVarExport(): void
    {
        $reflection = new ReflectionClass(ConfigGenerator::class);
        $method = $reflection->getMethod('getVarExport');
        $method->setAccessible(true);

        $this->assertEquals(
            '$cfg[\'var_name\'] = 1;' . "\n",
            $method->invoke(null, 'var_name', 1, "\n")
        );

        $this->assertEquals(
            '$cfg[\'var_name\'] = array (' .
            "\n);\n",
            $method->invoke(null, 'var_name', [], "\n")
        );

        $this->assertEquals(
            '$cfg[\'var_name\'] = array(1, 2, 3);' . "\n",
            $method->invoke(
                null,
                'var_name',
                [
                    1,
                    2,
                    3,
                ],
                "\n"
            )
        );

        $this->assertEquals(
            '$cfg[\'var_name\'][\'1a\'] = \'foo\';' . "\n" .
            '$cfg[\'var_name\'][\'b\'] = \'bar\';' . "\n",
            $method->invoke(
                null,
                'var_name',
                [
                    '1a' => 'foo',
                    'b' => 'bar',
                ],
                "\n"
            )
        );
    }

    /**
     * Test for ConfigGenerator::isZeroBasedArray
     */
    public function testIsZeroBasedArray(): void
    {
        $reflection = new ReflectionClass(ConfigGenerator::class);
        $method = $reflection->getMethod('isZeroBasedArray');
        $method->setAccessible(true);

        $this->assertFalse(
            $method->invoke(
                null,
                [
                    'a' => 1,
                    'b' => 2,
                ]
            )
        );

        $this->assertFalse(
            $method->invoke(
                null,
                [
                    0 => 1,
                    1 => 2,
                    3 => 3,
                ]
            )
        );

        $this->assertTrue(
            $method->invoke(
                null,
                []
            )
        );

        $this->assertTrue(
            $method->invoke(
                null,
                [
                    1,
                    2,
                    3,
                ]
            )
        );
    }

    /**
     * Test for ConfigGenerator::exportZeroBasedArray
     */
    public function testExportZeroBasedArray(): void
    {
        $reflection = new ReflectionClass(ConfigGenerator::class);
        $method = $reflection->getMethod('exportZeroBasedArray');
        $method->setAccessible(true);

        $arr = [
            1,
            2,
            3,
            4,
        ];

        $result = $method->invoke(null, $arr, "\n");

        $this->assertEquals(
            'array(1, 2, 3, 4)',
            $result
        );

        $arr = [
            1,
            2,
            3,
            4,
            7,
            'foo',
        ];

        $result = $method->invoke(null, $arr, "\n");

        $this->assertEquals(
            'array(' . "\n" .
            '    1,' . "\n" .
            '    2,' . "\n" .
            '    3,' . "\n" .
            '    4,' . "\n" .
            '    7,' . "\n" .
            '    \'foo\')',
            $result
        );
    }
}
