How to create global variable as html - twig

$value = sha1("anything");
$secure = '<input type = "hidden" value = "'.$value.'"/>';
$this->twig->addGlobal('anything',$secure);
After this I access this variable like this on template
{{ anything }}
The big surprise print this variable don't escaped like this
<input type = "hidden" value = "8867c88b56e0bfb82cffaf15a66bc8d107d6754a"/>
I want to print as html tag. But it worked when I used {{ anything|raw }}, I wish it worked without using raw filter

You can mark the variable as safe, without the filter raw, if you wrap it in a Twig\Markup instance, e.g.
$value = sha1("anything");
$secure = new \Twig\Markup('<input type = "hidden" value = "'.$value.'"/>', 'UTF-8');
$this->twig->addGlobal('anything',$secure);

Related

If twig replace isnt called, replace by nothing

I want to give my users control over an input field via twig replace. So I created a var
<input type='text' %attr%>
Now with twig:
{{ var | replace({"%attr%":"id='12'"}) | raw}}
But if my users dont use replace, I dont want to display %attr% in the input field.
Is there a native twig way to do this?
As already commented, this is a bad design and it would be better to rethink your strategy. Anyhow a possible solution would be to write a custom filter and use that one over the raw filter.
By adding the option is_safe to the filter, the filter will behave exactly like raw, but you have more control over the end result.
In this case, you could replace %attr% if it hasn't been replaced by the filter replace before. You could even extend this list if needed be
$twig->addFilter(new \Twig\TwigFilter('safe', function($val) {
return str_replace([
'%attr%',
],[
'',
], $val);
}, ['is_safe' => ['html']]);
After you've added the filter to twig, you can use this filter anywhere:
{{ var | replace({"%attr%":"id='12'"}) | safe }}
{{ var | safe }}

ColdFusion - Taking a string and breaking it down into individual variables

I am receiving a string from another application that contains various pieces of information. The items are always in the same order, but the length of variable information can change. Each item is separated by an underscore and prefixed by a letter and colon.
Example:
A:12345678_B:5482945_C:20220911_D:20230402_E:3.94
Ideally, I want to break it down so that (in Coldfusion) I can end up with a series of variable that I would set as the values of A,B,C,D and E above.
Does anyone know any easy way to do this?
Thanks!
I think #Will is missing one small part of your requirement, which is
I can end up with a series of variable[s] that I would set as the values of A,B,C,D and E above"
To me this demonstrates more what you want to achieve:
raw = "A:12345678_B:5482945_C:20220911_D:20230402_E:3.94"
asArray = raw.listToArray("_")
asStruct = asArray.reduce((struct, kvAsString) => {
var key = kvAsString.listFirst(":")
var value = kvAsString.listRest(":")
struct[key] = value
return struct
}, {})
writeDump(asStruct)
(runnable # trycf.com: https://trycf.com/gist/e84aea475957e27b5dea2643e7c207ad/acf2021?theme=monokai)
Whilst this does not create "a series of variables" it does separate out the key from the value, and from there you can append that to whatever scope you need the variables in (eg: variables.append(asStruct))
In future please:
show us what you've already tried
give us the full intended result, don't just describe it.
Basically: always include code when you ask questions.
Gives you an array of the items. If you're handy with Regular Expressions, this could be even simpler. This is Lucee compatible. Adobe CFML didn't like the var commands outside of a function.
<cfscript>
var aNewItems = [];
var sString = "A:12345678_B:5482945_C:20220911_D:20230402_E:3.94";
var aItems = listToArray(sString, "_");
for( var sLetter in aItems){
aNewItems.append(listFirst(sLetter, ":"));
}
writeDump(aNewItems);
</cfscript>
Here's an Adobe CFML version that worked on TryCF.com:
<cfscript>
local.aNewItems = [];
local.sString = "A:12345678_B:5482945_C:20220911_D:20230402_E:3.94";
local.aItems = listToArray(local.sString, "_");
for( local.sLetter in aItems){
local.aNewItems.append(listFirst(local.sLetter, ":"));
}
writeDump(local.aNewItems);
</cfscript>
And just for fun, here is a list function answer:
<cfset TheString = 'A:12345678_B:5482945_C:20220911_D:20230402_E:3.94'>
<cfoutput>
<cfloop list = #TheString# index = "NameValue" delimiters = "_">
Variable #ListFirst(NameValue, ":")# = #ListLast(NameValue, ":")# <br>
</cfloop>
</cfoutput>
Run code here ==> https://trycf.com/gist/34321917c06643de1d3c25b611243466/acf2021?theme=monokai

Dotliquid: value from string

Is there a way to get the value from a string?
For example:
"SomeString" has the value "Edward".
Input:
{% assign variable = 'SomeString' %}
{{ variable }}
Output:
SomeString
Note: SomeString is a constructed string during runtime, so I in fact need to get the value from a string --> I can't remove the quotes in the assignment.
There is nothing in DotLiquid which allows to do that, however it is always possible to create your own Tag or to build the template at run time.
public sealed class RuntimeAssign : Tag
{
...
}
Template.RegisterTag<RuntimeAssign>("runtimeassign");

Coding Implode In Twig

How can one use the equivalent of the implode function in a Twig environment?
For example, the contents of the variable $data1 = "input your name" and the variable $data2 = "input your address".
How to create a variable $result = "input your name, input your address" in Twig?
I'm guessing you're looking for the join filter. It works exactly like implode does in php. Quoting from the manual page:
The join filter returns a string which is the concatenation of the items of a sequence:
{{ [1, 2, 3]|join }}
{# returns 123 #}
The separator between elements is an empty string per default, but you can define it with the optional first parameter:
{{ [1, 2, 3]|join('|') }}
{# returns 1|2|3 #}

Twig - use quotation mark as separator for join filter

I pass my template an array of strings which I would like to convert to a jaavascript array:
Controller file (php):
$myVar = array('a','b','c');
Desired html:
var myVar = ["a","b","c"];
I try the following code (twig):
var myVar = ["{{ myVar | join('","') }}"];
But the twig generator converts the quotation marks to html entities and this is the result:
var myVar = ["a","b","c"];
Some idea?
You need to apply the raw filter:
var myVar = ["{{ myVar | join('","') | raw }}"];
Maerlyn's answer will work, however the drawback with it is that the values in the myVar array will be outputted raw too, which, depending on the origin of that variable, could lead to vulnerabilities in your website, such as XSS.
I found two ways to do this while maintaining the escaping on the array values. The first is using a loop with an if statement to check whether it's the last iteration to determine whether we need to output the "glue" used in the join or not:
var myVar = [{% for val in myVar %}"{{ val }}"{% if loop.last == false %},{% endif %}{% endfor %}]
The second way is to let PHP your PHP handle everything, including the escaping, and then output the raw string in Twig:
$arr = array_map(
function($value) {
return '"' . htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . '"';
},
$arr
);
$myVar = '[' . implode(',', $arr) . ']';
Then pass the $myVar variable to your view, and then you can just do:
{{ myVar|raw }}

Resources