D10 "Invalid placeholder (context) with string" error

Created on 14 March 2023, over 1 year ago
Updated 10 November 2023, 8 months ago

Upon updating to the latest version of this module with Drupal 10 support (8.x-1.5), then upgrading our existing Drupal 9 site to Drupal 10, our site logs are inundated with the following notice / message when loading any page with a views block that contains a Views Conditional field / check.

User warning: Invalid placeholder (context) with string: "no-header" in Drupal\Component\Render\FormattableMarkup::placeholderFormat() (line 251 of /var/www/html/public_html/core/lib/Drupal/Component/Render/FormattableMarkup.php)

The value "no-header", in this instance, is what we are conditionally returning in our view, but the string value changes depending on the particular views conditional we are using.

A full trace down to the Views Conditional markup render is below:

#0 /var/www/html/public_html/core/includes/bootstrap.inc(158): _drupal_error_handler_real(512, 'Invalid placeho...', '/var/www/html/p...', 251)
#1 [internal function]: _drupal_error_handler(512, 'Invalid placeho...', '/var/www/html/p...', 251)
#2 /var/www/html/public_html/core/lib/Drupal/Component/Render/FormattableMarkup.php(251): trigger_error('Invalid placeho...', 512)
#3 /var/www/html/public_html/core/lib/Drupal/Core/StringTranslation/TranslatableMarkup.php(195): Drupal\Component\Render\FormattableMarkup::placeholderFormat('no-header', Array)
#4 /var/www/html/public_html/core/lib/Drupal/Component/Utility/ToStringTrait.php(15): Drupal\Core\StringTranslation\TranslatableMarkup->render()
#5 /var/www/html/public_html/core/lib/Drupal/Core/Render/Renderer.php(459): Drupal\Core\StringTranslation\TranslatableMarkup->__toString()
#6 /var/www/html/public_html/core/lib/Drupal/Core/Render/Renderer.php(204): Drupal\Core\Render\Renderer->doRender(Array, false)
#7 /var/www/html/public_html/modules/contrib/views_conditional/src/Plugin/views/field/ViewsConditionalField.php(243): Drupal\Core\Render\Renderer->render(Array)
#8 /var/www/html/public_html/modules/contrib/views_conditional/src/Plugin/views/field/ViewsConditionalField.php(381): Drupal\views_conditional\Plugin\views\field\ViewsConditionalField->markup(Array)
#9 /var/www/html/public_html/core/modules/views/src/Plugin/views/field/FieldPluginBase.php(1174): Drupal\views_conditional\Plugin\views\field\ViewsConditionalField->render(Object(Drupal\views\ResultRow))
#10 /var/www/html/public_html/core/modules/views/views.theme.inc(238): Drupal\views\Plugin\views\field\FieldPluginBase->advancedRender(Object(Drupal\views\ResultRow))

Investigating this further, this appears as though it might be related to core issue 3173103 πŸ› False positives when identifying what is a placeholder, for deprecation error Fixed , with recent deprecations in Drupal 10 triggering in the context array, though I'm not familiar enough with placeholder formatting to determine if there is anything that can be done to fix this at the Views Conditional module level. We only seem to be experiencing this on pages that have a Views Conditional check / field included.

πŸ› Bug report
Status

Fixed

Version

1.0

Component

Code

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @kferencz91
  • πŸ‡ΊπŸ‡ΏUzbekistan biarr

    I confirm this error when installing this module on fresh Drupal 10 installation. Any views with 'Views Conditional' resulting ```Invalid placeholder (context) with string:..``` .

  • I'm hitting this issue too. Just updated to D10 and on Views 1.5.

    User warning: Invalid placeholder (context) with string: "" in Drupal\Component\Render\FormattableMarkup::placeholderFormat() (line 245 of core/lib/Drupal/Component/Render/FormattableMarkup.php).

  • πŸ‡§πŸ‡ͺBelgium herrzhull

    Facing the same issue

  • πŸ‡¦πŸ‡ΊAustralia steventpmc

    Not really a solution, but in the meantime I've used the Disable Messages module to stop these error messages from rendering on the front-end to users. https://www.drupal.org/project/disable_messages β†’

    This might help someone in the short term.

  • πŸ‡¨πŸ‡·Costa Rica MaxMendez

    Hi,

    I faced with this warning today, in my case the problem was trigger by the options 'Translate "Then" output' and 'Translate "Or" output', i disabled both options and disappear, in my case i does not neet translation of the values and this could be a clue to solve the root problem.

  • πŸ‡§πŸ‡ͺBelgium fbreckx Antwerp

    I also have this problem. Turning off the messages is not really a help, as the translation does not come through anyway.

  • The solution provided at #6 works for those who don't need translation of the values.

  • Confirming #6, this is from the translate checkboxes.

  • πŸ‡ΊπŸ‡ΈUnited States TolstoyDotCom L.A.

    That might be related to this, please test the merge request: https://www.drupal.org/project/drupal/issues/3173103#comment-15128512 πŸ› False positives when identifying what is a placeholder, for deprecation error Fixed

  • πŸ‡ΊπŸ‡ΈUnited States msangha

    I am also having the same issue related to views conditional field in my views. This is after I upgraded from D9.5.x do D10.1.x.

    I was able to create my own patch but after core gets updated the changes are over-ridden.

    I modified this file:
    core/lib/Drupal/Component/Render/FormattableMarkup.php

    This is the function I modified. I added the switch 'c':

      protected static function placeholderFormat($string, array $args) {
        // Transform arguments before inserting them.
        foreach ($args as $key => $value) {
          if (is_null($value)) {
            // It's probably a bug to provide a null value for the placeholder arg,
            // and in D11 this will no longer be allowed. When this trigger_error
            // is removed, also remove isset $value checks inside the switch{}
            // below.
            @trigger_error(sprintf('Deprecated NULL placeholder value for key (%s) in: "%s". This will throw a PHP error in drupal:11.0.0. See https://www.drupal.org/node/3318826', (string) $key, (string) $string), E_USER_DEPRECATED);
            $value = '';
          }
          switch ($key[0]) {
            case '@':
              // Escape if the value is not an object from a class that implements
              // \Drupal\Component\Render\MarkupInterface, for example strings will
              // be escaped.
              // Strings that are safe within HTML fragments, but not within other
              // contexts, may still be an instance of
              // \Drupal\Component\Render\MarkupInterface, so this placeholder type
              // must not be used within HTML attributes, JavaScript, or CSS.
              $args[$key] = static::placeholderEscape($value);
              break;
    
            case ':':
              // Strip URL protocols that can be XSS vectors.
              $value = UrlHelper::stripDangerousProtocols($value);
              // Escape unconditionally, without checking whether the value is an
              // instance of \Drupal\Component\Render\MarkupInterface. This forces
              // characters that are unsafe for use in an "href" HTML attribute to
              // be encoded. If a caller wants to pass a value that is extracted
              // from HTML and therefore is already HTML encoded, it must invoke
              // \Drupal\Component\Render\OutputStrategyInterface::renderFromHtml()
              // on it prior to passing it in as a placeholder value of this type.
              // @todo Add some advice and stronger warnings.
              //   https://www.drupal.org/node/2569041.
              $args[$key] = Html::escape($value);
              break;
    
            case '%':
              // Similarly to @, escape non-safe values. Also, add wrapping markup
              // in order to render as a placeholder. Not for use within attributes,
              // per the warning above about
              // \Drupal\Component\Render\MarkupInterface and also due to the
              // wrapping markup.
              $args[$key] = '<em class="placeholder">' . static::placeholderEscape($value) . '</em>';
              break;
    					
    	case 'c':
    	   // 7-7-23 Copied Case @ because was getting placholder error after upgrade to D10.1.1
    	  $args[$key] = static::placeholderEscape($value);
    	  break;
    
            default:
              // Warn for random variables that won't be replaced.
              trigger_error(sprintf('Invalid placeholder (%s) with string: "%s"', $key, $string), E_USER_WARNING);
              // No replacement possible therefore we can discard the argument.
              unset($args[$key]);
              break;
          }
        }
    
  • I test merge request mentioned in #10. Success! Error message no longer flooding the logs!

  • πŸ‡ΈπŸ‡¦Saudi Arabia ishore

    #6 and #10 did not work for me, but #11 does. Thanks!

  • πŸ‡ΊπŸ‡ΈUnited States TolstoyDotCom L.A.

    Some of the proposed solutions assume the problematic keys will start with a certain letter or be of a set of strings. The solution in #10 is more general purpose. If there's a problem using it, please post the details.

  • πŸ‡¨πŸ‡¦Canada chrisck

    @TolstoyDoyCom Thanks for your MR in the other issue. I'm confirming the MR fixes my issue, as reported here.

    This looks to be a general problem in core and perhaps not specific to views_conditional.

  • πŸ‡ΊπŸ‡ΈUnited States hockey2112

    #6 worked for me.

  • πŸ‡¬πŸ‡§United Kingdom jonathan1055

    πŸ› False positives when identifying what is a placeholder, for deprecation error Fixed has been fixed. Does this solve the problem?

  • πŸ‡©πŸ‡ͺGermany marcoka

    #17 No the core patch does not fix this. Applied it to my drupal 10.1.
    #14 Yes, your changes in the merge request will work, no more warnings in the drupal logs.

  • πŸ‡ΊπŸ‡ΈUnited States TolstoyDotCom L.A.

    The core patch from the other issue is the same as the merge request mentioned in my #10 and #14 comments.

    In your site, does core/lib/Drupal/Component/Render/FormattableMarkup.php contain ctype_alnum?

  • First commit to issue fork.
  • Status changed to Needs review 9 months ago
  • Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 5.7
    last update 9 months ago
    Waiting for branch to pass
  • πŸ‡ΊπŸ‡ΈUnited States jrglasgow Idaho

    Looking at this I see that this section in src/Plugin/views/field/ViewsConditionalField.php ViewsConditionalField->render()

        // Translate text to be displayed with a context specific to this module,
        // view and display.
        $translation_context = "views_conditional:view:{$this->view->id()}";
    
        // Translate prior to replacements, otherwise the dynamic replacement
        // content results in endless translations:
        if ($this->options['then_translate']) {
          $then = $this->t($then, ['context' => $translation_context]);
        }
        if ($this->options['or_translate']) {
          $or = $this->t($or, ['context' => $translation_context]);
        }
    

    the calls to $this->t() have the $options array with the context key being passed in as the second argument, where is should be the third argument. - see StringTranslationTrait::t. This was cauaing the $options array to be treated as the $args array.

    attached is a patch that fixes this

  • Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 5.7
    last update 9 months ago
    Waiting for branch to pass
  • @jrglasgow opened merge request.
  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Thanks for the patch!

  • Status changed to RTBC 8 months ago
  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Hitting this on another project now, it's time that this gets fixed.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    MR#3 is working well

  • First commit to issue fork.
  • Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 5.7
    last update 8 months ago
    Waiting for branch to pass
  • Status changed to Fixed 8 months ago
  • πŸ‡ΊπŸ‡ΈUnited States shelane
  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Thanks very much @shelane! :)

    It's even tagged in a release. Greatly appreciated!

    https://www.drupal.org/project/views_conditional/releases/8.x-1.9 β†’

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.69.0 2024