Score:0

Specify the theme when creating content / importing content via Feeds

cn flag

I want to force all content to be created using my primary site theme. I want to do this because I am using a renderer in MYMODULE_node_presave() like this:

function MYMODULE_node_presave(NodeInterface $node) {
  $renderer = \Drupal::service('renderer');

  $content_type = $node->getType();
  if ($content_type == 'page') {
    $viewmode_render = $node->get('field_text_main_to_render')
      ->view('rendered_output');
    $processed_display = $renderer->renderPlain($viewmode_render);
    $node->set('field_text_main_display', "$processed_display");
    $node->field_text_main_display->format = 'processed';
}

My site uses Bartik as the main theme and Seven as the admin theme.

Under Appearance settings (/admin/appearance), I have checked the preference Use the administration theme when editing or creating content. This ensures that nodes are rendered in Bartik upon creation in the UI.

However, when I resave nodes on /admin/content, the nodes are re-saved with Seven, instead of Bartik. So I added a ThemeNegotiator:

/**
 * Select the correct theme for various routes.
 */
class ThemeNegotiator implements ThemeNegotiatorInterface {

  /**
   * {@inheritDoc}
   */
  public function applies(RouteMatchInterface $route_match) {
    return $this->negotiateRoute($route_match) ? TRUE : FALSE;
  }

  /**
   * {@inheritDoc}
   */
  public function determineActiveTheme(RouteMatchInterface $route_match) {
    return $this->negotiateRoute($route_match) ?: NULL;
  }

  /**
   * Select the theme for special cases.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The currently matched route.
   *
   * @return bool|string
   *   The theme name to use (string) or false (bool).
   */
  private function negotiateRoute(RouteMatchInterface $route_match) {
    $route_name = $route_match->getRouteName();
    // Admin content page must use node render theme.
    // Why: "Save content" action will use the theme of this page.
    if ($route_name === 'system.admin_content') {
      return 'bartik';
    }
    else {
      return FALSE;
    }
  }

}

Now, when I run a bulk node resave on /admin/content, nodes are rendered correctly with Bartik.

Next, I installed the Feeds module. Now, when I import nodes via CSV using Feeds, they are rendered using Seven, not Bartik. I want to force these nodes to also be rendered using Bartik, but I don't know how to do that. (For example, if there was a way to use negotiateRoute in the ThemeNegotiator, that would be fine, but I don't know how to set that up.) Any ideas?

4uk4 avatar
cn flag
I would use the theme negotiator in a sub-request, where the controller returns a response with the rendered node. See this as example how to make a sub-request and also how to avoid a core bug: https://drupal.stackexchange.com/questions/303396/making-an-http-subrequest-causes-currentroutematch-to-have-the-wrong-route
Score:0
de flag

Content can be rendered in any theme, and is rendered in the current theme at any given time. You do not save content as belonging to a theme. Rather, if you want different themes to show content, you can try the Switch Page Theme module.

cn flag
"You do not save content as belonging to a theme." Yes, generally this is the case. But as stated in my question, I'm using `hook_node_presave()` to render some fields and save the rendered output, which is saving the content as belonging to a specific theme. So I need to control which theme is used to render the content for this specific content save.
Jaypan avatar
de flag
Those elements will be rendered in the current theme at the time of rendering. In your case, that is probably on the path at which the import happens, so you could use the above module to set the theme for the feed path. That said, it doesn't seem like a great architectural design to be storing the rendered HTML - what if you want to change your theme in the future, or search on that field. Usually you'll want to store data, and render on output, caching the rendered output if it's a costly build. I personally would consider architectural restructuring over theme manipulation.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.