> The aim in my mind would be to make escaping easier to do right, for
people who aren't already using a framework or templating engine with its
own solution.
> The current implementation doesn't seem to share these priorities; it
feels like a building block for framework developers, who probably have
their own solutions already.

No! You don't understand what I'm trying to explain. This feature will be
useful for ALL applications without template engine - frameworks, CMS,
custom core. You say that frameworks have their own solutions already. But
the problem IS NOT that we don't have a solution. PHP already has built-in
function htmlspecialchars(), Yii has Html::escape(), Zend has
$this->escape(). This is not the problem. The problem IS that developer
must call these functions everywhere manually.

<div>
    <div data-user-id="<?= Html::escape($profile->user->id) ?>">
        <?= Html::escape($profile->name) ?>
    </div>
    <div>
        <?= Html::escape($profile->description) ?>
    </div>
    <div>
        <?= Html::escape($profile->age) ?>
    </div>
    <div>
        <?= Html::escape($profile->position->name) ?>
    </div>
    <div>
        <?= Html::escape($profile->group->name) ?>
    </div>
    <div>
        <?= Html::escape($profile->organisation->address) ?>
    </div>
</div>

This is the same as calling constructor manually after every 'new'
statement: (new User)->__construct(...), (new Profile)->__construct(...).
We have special function '__construct', which is called automatically. I
suggest similar way for escaping. And because we cannot set the same magic
function name for all applications I suggest to do this by registering a
callable.
This is not intended for people who don't have escaping functions, this is
intended for people who already have escaping functions. RFC suggests the
way how to call these functions automatically. And people who don't have
escaping function may define it once, and it also will be called
automatically.



> - you can define automatic escaping for a whole file or a block within a
file
> - there is an extra filter to skip the automatic escaping (not the same
as unescaping)
> - the above can be done with any "context", but the default is HTML
> - a "context" is not just the argument to a single all-powerful "escape"
function; you can register a new context by name, > without reimplementing
any of the existing functionality
> - other template functions can say that their output shouldn't be
escaped, or that their input should be pre-escaped
> - other functionality of the system is aware of these notions, and
designed to behave sensibly

> I don't think there's any way PHP can ever reach that level of
sophistication, because most of the language knows nothing about "context";
the feature we build in is only ever going to be a simple short-hand for
some basic function calls.

Almost all of these points can be done with the system described in the
RFC. Application can allow or restrict new contexts (without reimplementing
any of the existing functionality). Any behavior can be defined in
userland, we just need a point of extension.

<?php
class CsvTemplate
{
    protected $escapers = [];


    function render()
    {
        set_escape_handler([$this, 'escape']);
        include $this->templateFile;
        restore_escape_handler();
    }

    function escape($str, $context = 'csv')
    {
        switch ($context) {
            case 'csv':
                return $this->escapeCsv($str);
            break;

            case 'raw':
                return $str;
            break;

            default:
                if (isset($this->escapers[$context])) {
                    return call_user_func($this->escapers[$context], $str);
                }

                throw new Exception('Unknown context');
            break;
        }
    }

    function setEscaper($context, $callable)
    {
        ...
    }
}
?>

header1;header2;
<?* $data['field1'] ?>;<?* (int)$data['field2'], 'raw' ?>;



> But secondly, because people are lazy, or misunderstand, or make mistakes
when they're in a hurry. Your RFC isn't going to magically fix all those
things.

It exactly is going to fix all those things. If people will use this
operator with HTML escaping by default, standard <?= ?> operator will not
be needed.



> Just a thought, but I can't help thinking that "improved escape
facilities and syntax" are a mere patch for a more than superficial problem.
> The problem of differentiating HTML strings, which to not require
escaping, from other string, which do, could actually be viewed as a deeper
problem, which is the inability to tell string types apart.
> /** @var string product description as HTML, do not escape this */
> public $description;

This is another problem, and it depends on your infrastructure or business
logic. Only your application or model knows what is stored in
'$description'. What if I have a site for learning HTML and my
'$description' contains an example with HTML, which should be HTML-encoded
on the page with a lesson, so that it will look like source code? This is
not a task of escaping system.



> And a more intelligent escape function, like:
>
>    typedef HTML extends string;
>
>    class ProductView
>    {
>        /** @var HTML product description */
>        public $description;
>    }
>
>    function html($str) {
>        return $str instanceof HTML ? $str : htmlspecialchars($str);
>    }

You can do this now by defining class 'HTML' with '__toString' method,
without any typedefs. What is the problem? And anyway you must call your
'html()' function everywhere, and this is the problem.

Reply via email to