Conditional keywords ignored if keyword doesn't exist


(*) #1

I’m attempting to show HTML based upon a conditional keyword involving the file type of a given File asset. I have this sample code (simplified) in a Default Format for an Asset Listing using the following conditional keyword:

%begin_asset_file_type^eq:svg%
  <img class="card-img-top img-fluid" src="%asset_url%" alt="%asset_file_type%">
%end_asset%

If the keyword is present, the logic is fine and the <img> tag is shown for SVG files. However, the condition appears to be ignored (or resolved always as true) entirely if the keyword asset_file_type isn’t present, resulting in HTML still being outputted. For clarity, I’m talking about when the keyword is not just empty, but non-existent; such when the Default Format is rendering an non-File Asset type like a Page which doesn’t have an asset_file_type keyword. For any of these assets, the conditional appears ignored resulting in the the <img> tag is outputted anyway, like so:

    <img class="card-img-top img-fluid" src="[url to asset]" alt="">

(noting the blank alt attribute, which indicates the “non-existent” keyword). I tested this further with a junk keyword like:

%begin_asset_foobar%
  Foobar
%end_asset%

and Foobar appears for all assets, because none have the keyword asset_foobar.

Is this behaviour intentional or a bug? My expectation would be that referencing a non-existent value would evaluate to a false, causing the condition not to pass. This current behaviour causes further unexpected issues when I’m writing `%else_begin_asset_file_name%, because that logic will always evaluate as true. Is there a way of working around the issue?

The aim here is to have a single Default Format that changes HTML output very slightly depending on conditions like these. I know I could create a separate type format for each different Asset type, but this would involve repeating hundreds of lines of HTML for each and every type.

Matrix Version: 5.3.3.0


(Peter McLeod) #2

Hi

could use something like below to just check the filename:

%begin_asset_attribute_title^contains:.svg%

This should only apply to ‘file’ assets, but you might need to add some additonal modifies filter out files such as ‘name.svg.jpg’ … if this causes issues for you as well.

Thanks
Peter


(*) #3

Thanks for the suggestion, but the .svg isn’t necessarily part of the Title attribute; this field appears to also to be the asset’s Short Name / Friendly Name from my tests. So, it won’t apply when a more descriptive name is specified. This is why I was going after the file type itself.

Matrix’s implementation of determining ‘filetype’ is similarly based on substrings (it gets the substring after the first-to-right period char), but it’s a little harder to change the file name without something blowing up. In my tests, attempting to change a .jpg filename resulted in a slew of ‘[SYSTEM_ROOT]/fudge/image/image_manip.inc’ errors.

In any case, the core issue is that the logic/processing behind the conditional appears to be faulty because it’s treating an undefined value as true.

Cheers,
David


(Peter McLeod) #4

Sorry - had meant %begin_asset_name^contains:.svg% in the previous post.

Yeah might be hard to determine an ‘svg’ file type without the .svg extension, as they are just xml, and added (I’m assuming) as generic ‘file’ or ‘xml’ assets in Matrix.

You might be able use something like an xslt asset/keyword to check for the svg tags in the file content, or a regex etc.

Otherwise, can you control the creation of the files at all to make it easier to manage? Or modify existing files to make them easier to work with?

With the issue re the logic - you could probably reverse the condition to avoid this e.g.:

%begin_asset_file_type^neq:svg%
%else_asset%
  <img class="card-img-top img-fluid" src="%asset_url%" alt="%asset_file_type%">
%end_asset%

Not sure if this will help you any further, though.
Thanks
Peter


(Bart Banda) #5

I’ll report that as a bug as it would be good to get it to handle invalid keywords like that in the begin/else formats.

You should be able to do what Peter suggested as a workaround in the meantime though.

You can also nest conditions as well, like:

%begin_asset_type^contains:File%
    %begin_asset_file_type^eq:svg%
      <img class="card-img-top img-fluid" src="%asset_url%" alt="%asset_file_type%">
    %end_asset%
%end_asset%

Alternatively just use:

%begin_asset_url^contains:\.svg%
  <img class="card-img-top img-fluid" src="%asset_url%" alt="%asset_file_type%">
%end_asset%

(*) #6

Great, thanks @PeterM for the suggestion on the reverse logic. I had to restructure a long if-else statement to make it work, but that’s a slick workaround for now.

@Bart Thanks for reporting it as a bug. If you could link to the report URL in Squiz Map, I’d be keen to keep up with its progress.

With your suggestions, the main issue with using nested conditions is that I have multiple else branches like so. I’d omitted these from my original to keep the question focussed on the issue with keyword logic. Here’s my example:

%begin_asset_X%
...
%else_begin_asset_Y%
...
%else_begin_asset_type^contains:File%
  %begin_asset_file_type^eq:svg%
    ...
  %end_begin%
%else_asset_Z%
  <!-- Never reached if ^contains:File succeeds but ^eq:svg fails -->
%else_asset%
  <!-- Never reached either if ^contains:File succeeds but ^eq:svg fails -->
  ...
%

so if I go and nest a condition inside one else branch, the other else branches can no longer be reached if the top-level condition succeeds but the nested condition fails. Ideally, in a full programming language you’d be okay because you’d use AND/OR operators and have full logic at your disposal, but that’s not available here. In this case, I know I could copy-paste the code under the %else_asset% branch, but then you’ve got duplicate code.

The asset URL test is a decent solution in this case, though it’d be more robust if there were an endswith or inline regex match in keywords. I know there’s the existing preg_match keyword but you’d got to create a dedicated Regex asset specifically for that test and that could easily add up to dozens of assets for basic one-off tests like \.svg$.

All that said, that works around the issue for this specific test / keyword but there’ll be other situations where the same data isn’t available in another keyword. For now, @PeterM’s suggestion works as long as I try all valid keywords first at the top level %begin_%, and then put the reverse logic beneath the %else_asset% block.


(Bart Banda) #7

Squizmap is here: https://squizmap.squiz.net/matrix/10342

I’m curious to know the full format/requirement of the asset listing, as there might be an easier way then to create your format for the different asset types rather than doing multiple begin/else_begin/else/end keywords?

In 5.4 this would be a perfect job for Server Side JS! :slight_smile:
https://matrix.squiz.net/manuals/concepts/chapters/server-side-javascript