CodeIgniter4 icon indicating copy to clipboard operation
CodeIgniter4 copied to clipboard

Bug: render `Parser` default value with empty array

Open ddevsr opened this issue 3 years ago • 9 comments

PHP Version

7.4

CodeIgniter4 Version

4.2.6

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Windows

Which server did you use?

apache

Database

MySQL 5.7

What happened?

See comment #6550, empty array cannot parsing default value.

Steps to Reproduce

$parser = new Parser($this->config, $this->viewsDir, $this->loader);

$obj = (object) '';

$data = [
      'value1' => 0.0,
      'value2' => [],
      'value3' => $obj->scalar,
      'value4' => false,
];

$template = '{ value1|default(foo) } { value2|default(bar) } { value3|default(baz) } { value4|default(john) }';
$parser->setData($data);

echo $parser->renderString($template);

Expected Output

Result is foo bar baz john

Anything else?

No response

ddevsr avatar Sep 19 '22 14:09 ddevsr

What do you want to show when you set an array to a variable ? { variable } Or why do you need to set an array?

kenjis avatar Sep 20 '22 00:09 kenjis

That's odd! empty([]) is definitely true - I wonder if this is somehow getting interpolated as empty['']) (which is false)? I think that we still allow array types here, and address this as a bug in another PR.

@MGatner say need still allow array types. When testing with [] or [''] get result error.

ddevsr avatar Sep 20 '22 00:09 ddevsr

An array cannot be converted to a string. So we cannot show an array in the web page. Or it is converted to Array with PHP warning if we use PHP view.

I don't see the use case of an array.

kenjis avatar Sep 20 '22 01:09 kenjis

    public function testDefaultManyValue()
    {
        $parser = new Parser($this->config, $this->viewsDir, $this->loader);

        $obj = (object) '';

        $data = [
            'value1' => 0.0,
            'value2' => [['test' => '']],
            'value3' => $obj->scalar,
            'value4' => false,
        ];

        $template = '{ value1|default(foo) } {value2}{ test|default(bar) }{/value2} { value3|default(baz) } { value4|default(john) }';

        $parser->setData($data);
        $this->assertSame('foo bar baz john', $parser->renderString($template));
    }

With this its OK, but if use case array from database is []?

ddevsr avatar Sep 20 '22 02:09 ddevsr

By the way, when 0.0 comes, why do we show the default value? It seems it should show 0.0.

kenjis avatar Sep 20 '22 02:09 kenjis

With this its OK, but if use case array from database is []?

Do you mean the value of test is []? In that case, what value will come when it is not empty array?

kenjis avatar Sep 20 '22 03:09 kenjis

No, i mean what if 'data' => []

    public function testDefaultArrayValue()
    {
        $parser = new Parser($this->config, $this->viewsDir, $this->loader);

        $data = [
            'data' => [
                [
                    'field_no'    => 1,
                    'field_title' => 'Mouse',
                    'field_amount'=> 20,
                ],
                [
                    'field_no'    => 2,
                    'field_title' => 'Keyboard',
                    'field_amount'=> 44,
                ],
            ],
        ];

        $template = '{data}[{ field_no|default(bar) }] { field_title|default(bar) } = { field_amount|default(bar) }\n{/data}';

        $parser->setData($data);
        $this->assertSame('[1] Mouse = 20\n[2] Keyboard = 44\n', $parser->renderString($template));
    }

or

    public function index()
    {
        $parser = \Config\Services::parser();
        $data = [
            'blog_title'   => 'My Blog Title',
            'blog_heading' => 'My Blog Heading',
            'blog_entries' => [
                ['title' => 'Title 1', 'body' => 'Body 1'],
                ['title' => 'Title 2', 'body' => 'Body 2'],
                ['title' => 'Title 3', 'body' => 'Body 3'],
                ['title' => 'Title 4', 'body' => 'Body 4'],
                ['title' => 'Title 5', 'body' => 'Body 5'],
            ],
        ];
        
        return $parser->setData($data)->render('home');
    }

home.php

<html>
<head>
    <title>{blog_title}</title>
</head>
<body>
    <h3>{blog_heading}</h3>

    {blog_entries}
        <h5>{title}</h5>
        <p>{body}</p>
    {/blog_entries}

</body>
</html>

I think better implement like Datatables, if data === [] use default print No data available image

ddevsr avatar Sep 20 '22 03:09 ddevsr

{blog_entries} is []? Do you want {blog_entries|default(No data available)}?

kenjis avatar Sep 20 '22 04:09 kenjis

Yes, like that

ddevsr avatar Sep 20 '22 06:09 ddevsr

This is not a bug.

If {blog_entries} is an array, it is not a normal pseudo-variable, not a single variable. No filters are applied to it.

Any single variable substitution can have one or more filters applied to it to modify the way it is presented. https://codeigniter4.github.io/CodeIgniter4/outgoing/view_parser.html#filters

kenjis avatar Sep 22 '22 01:09 kenjis