Documentation or Tutorial on using Batch or Queue Services API Programmatically I am working on importing content into my drupal 8 website from an external API that returns XML data. The calls to the API take a long time to process. When I make too many queries at once it takes that much longer and it causes my site to timeout.

I have been trying to find online some direction on how to use the Batch API Service or the Queue Service programmatically in D8 but haven't as of yet found any good tutorials or documentation on this. Anyone have any good suggestions on where I can look or direction on where to start to use batch or queue services in D8? I have found many tutorials for D7 but haven't been successful in getting those two work with my D8 code.

Any suggestions would be greatly appreciated!

I have made an example module to help understanding the Queue API and the Batch API. It also shows how to use them together.

I show you here the files and its contents. I have made a lots of comment, so i think, it is easy to understand.

xml_import_example.info.yml

type: module
name: XML import example
package: Examples
description: "This module helps understanding the Batch API and Queue API with an XML import example"
core: 8.x

xml_import_example.permissions.yml

import content from xml:
  title: 'Import content from xml'
  description: 'With this permission user can import contents from a XML source'
  restrict access: TRUE

xml_import_example.routing.yml

# Get contents from the xml source
xml_import_example.get_contents_from_xml:
  path: '/get-contents-from-xml'
  defaults: { _controller: '\Drupal\xml_import_example\Controller\ImportContentFromXML::getContentsFromXMLPage' }
  requirements:
    _permission: 'import content from xml'
# Process all queue items with batch
xml_import_example.process_all_queue_items_with_batch:
  path: '/process-all-queue-items'
  defaults: { _controller: '\Drupal\xml_import_example\Controller\ImportContentFromXML::processAllQueueItemsWithBatch' }
  requirements:
    _permission: 'import content from xml'

src/Controller/ImportContentFromXML.php

<?php
/**
 * @file
 * Contains \Drupal\xml_import_example\Controller\ImportContentFromXML.
 */

namespace Drupal\xml_import_example\Controller;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Queue\QueueWorkerManager;
use Drupal\Core\Queue\QueueFactory;

/**
 * You can use this constant to set how many queued items
 * you want to be processed in one batch operation
 */
define("IMPORT_XML_BATCH_SIZE", 1);

class ImportContentFromXML extends ControllerBase {

  /**
   * We add QueueFactory and QueueWorkerManager services with the Dependency Injection solution
   */

  /**
   * @var QueueFactory
   */
  protected $queueFactory;

  /**
   * @var QueueWorkerManager
   */
  protected $queueManager;

  /**
   * {@inheritdoc}
   */
  public function __construct(QueueFactory $queue_factory, QueueWorkerManager $queue_manager) {
    $this->queue_factory = $queue_factory;
    $this->queue_manager = $queue_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $queue_factory = $container->get('queue');
    $queue_manager = $container->get('plugin.manager.queue_worker');

    return new static($queue_factory, $queue_manager);
  }

  /**
   * Get XML from the API and convert it to
   */
  protected function getContentsFromXML() {
    // Here you should get the XML content and convert it to an array of content arrays for example
    // I use now an example array of contents:
    $contents = array();

    for ($i = 1; $i <= 20; $i++) {
      $contents[] = array(
        'title' => 'Test title ' . $i,
        'body' => 'Test body ' . $i,
      );
    }

    // Return with the contents
    return $contents;
  }

  /**
   * Page where the xml source is preprocessed
   */
  public function getContentsFromXMLPage() {
    // Get contents array
    $contents = $this->getContentsFromXML();

    foreach ($contents as $content) {
      // Get the queue implementation for import_content_from_xml queue
      $queue = $this->queue_factory->get('import_content_from_xml');

      // Create new queue item
      $item = new \stdClass();
      $item->data = $content;
      $queue->createItem($item);
    }

    return array(
      '#type' => 'markup',
      '#markup' => $this->t('@count queue items are created.', array('@count' => count($contents))),
    );
  }

  /**
   * Process all queue items with batch
   */
  public function processAllQueueItemsWithBatch() {

    // Create batch which collects all the specified queue items and process them one after another
    $batch = array(
      'title' => $this->t("Process all XML Import queues with batch"),
      'operations' => array(),
      'finished' => 'Drupal\xml_import_example\Controller\ImportContentFromXML::batchFinished',
    );

    // Get the queue implementation for import_content_from_xml queue
    $queue_factory = \Drupal::service('queue');
    $queue = $queue_factory->get('import_content_from_xml');

    // Count number of the items in this queue, and create enough batch operations
    for($i = 0; $i < ceil($queue->numberOfItems() / IMPORT_XML_BATCH_SIZE); $i++) {
      // Create batch operations
      $batch['operations'][] = array('Drupal\xml_import_example\Controller\ImportContentFromXML::batchProcess', array());
    }

    // Adds the batch sets
    batch_set($batch);
    // Process the batch and after redirect to the frontpage
    return batch_process('<front>');
  }

  /**
   * Common batch processing callback for all operations.
   */
  public static function batchProcess(&$context) {

    // We can't use here the Dependency Injection solution
    // so we load the necessary services in the other way
    $queue_factory = \Drupal::service('queue');
    $queue_manager = \Drupal::service('plugin.manager.queue_worker');

    // Get the queue implementation for import_content_from_xml queue
    $queue = $queue_factory->get('import_content_from_xml');
    // Get the queue worker
    $queue_worker = $queue_manager->createInstance('import_content_from_xml');

    // Get the number of items
    $number_of_queue = ($queue->numberOfItems() < IMPORT_XML_BATCH_SIZE) ? $queue->numberOfItems() : IMPORT_XML_BATCH_SIZE;

    // Repeat $number_of_queue times
    for ($i = 0; $i < $number_of_queue; $i++) {
      // Get a queued item
      if ($item = $queue->claimItem()) {
        try {
          // Process it
          $queue_worker->processItem($item->data);
          // If everything was correct, delete the processed item from the queue
          $queue->deleteItem($item);
        }
        catch (SuspendQueueException $e) {
          // If there was an Exception trown because of an error
          // Releases the item that the worker could not process.
          // Another worker can come and process it
          $queue->releaseItem($item);
          break;
        }
      }
    }
  }

  /**
   * Batch finished callback.
   */
  public static function batchFinished($success, $results, $operations) {
    if ($success) {
     drupal_set_message(t("The contents are successfully imported from the XML source."));
    }
    else {
      $error_operation = reset($operations);
      drupal_set_message(t('An error occurred while processing @operation with arguments : @args', array('@operation' => $error_operation[0], '@args' => print_r($error_operation[0], TRUE))));
    }
  }
}

src/Plugin/QueueWorker/ImportContentFromXMLQueueBase.php

<?php

/**
 * @file
 * Contains Drupal\xml_import_example\Plugin\QueueWorker\ImportContentFromXMLQueueBase
 */

namespace Drupal\xml_import_example\Plugin\QueueWorker;

use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Queue\QueueWorkerBase;
use Drupal\Core\Queue\SuspendQueueException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\node\Entity\Node;

/**
 * Provides base functionality for the Import Content From XML Queue Workers.
 */
abstract class ImportContentFromXMLQueueBase extends QueueWorkerBase implements ContainerFactoryPluginInterface {

  // Here we don't use the Dependency Injection,
  // but the create method and __construct method are necessary to implement

  /**
   * {@inheritdoc}
   */
  public function __construct() {}

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static();
  }

  /**
   * {@inheritdoc}
   */
  public function processItem($item) {
    // Get the content array
    $content = $item->data;
    // Create node from the array
    $this->createContent($content);
  }

  /**
   * Create content
   *
   * @return int
   */
  protected function createContent($content) {
    // Create node object from the $content array
    $node = Node::create(array(
      'type'  => 'page',
      'title' => $content['title'],
      'body'  => array(
        'value'  => $content['body'],
        'format' => 'basic_html',
      ),
    ));
    $node->save();
  }
}

src/Plugin/QueueWorker/ImportContentFromXMLQueue.php

<?php

namespace Drupal\xml_import_example\Plugin\QueueWorker;

/**
 * Create node object from the imported XML content
 *
 * @QueueWorker(
 *   id = "import_content_from_xml",
 *   title = @Translation("Import Content From XML"),
 *   cron = {"time" = 60}
 * )
 */
class ImportContentFromXMLQueue extends ImportContentFromXMLQueueBase {}

So this is the working module, you can test it in you site.

If you visit the /get-contents-from-xml URL 20 queue items are made from a contents array.

The src/Plugin/QueueWorker/ImportContentFromXMLQueue.php contains this annotation:
cron = {"time" = 60}

So if you run cron, the queue items are processed for maximum 60 seconds.
You can increase or decrease this time, with that annotation.

If you remove the cron = {"time" = 60} line, cron do nothing with your queue items.

If you would like to process all the queue items in you browser, you have to visit the following url:
/process-all-queue-items

It will collect all of your queue items, creates batch operations from them, and after that it process one after another.

I hope you and others with the same question understand the usage of the Queue API and Batch API with the help of this module.

Have a nice day!


How do I get a list of all CSS and JS that are attached to a page? In Drupal 8, how do I get all CSS and JS that is attached to a page? In Drupal 7, I could use drupal_add_css() or drupal_add_js() without arguments, to get an array containing a list of all the files/inline added to a page.

I'm developing a module that will display a "preview" of the block on block configuration page. The method I chose is displaying the block code in a <iframe>, but to be properly styled, I need to output all styles with it. This is why I want to read all possible CSS/JS in this "preview" page controller.

You cannot get a list of css/js files because it is constructed very late in the render process.

However, since you want to use an iframe to achieve that goal, you can get it through the normal loading order of a drupal page.

The following is a proof of concept controller method you can use to display a block in a simplified html mode.

public function preview($block_id) {
  /** @var BlockInterface $block */
  $block = Block::load($block_id);

  /** @var BareHtmlPageRendererInterface $bare_html_page_renderer */
  $bare_html_page_renderer = \Drupal::service('bare_html_page_renderer');
  $content = [
    'preview-child' => \Drupal::entityTypeManager()->getViewBuilder('block')->view($block)
  ];

  return $bare_html_page_renderer->renderBarePage($content, 'preview-title', 'preview-theme');
}


Is it possible to add folders in config/install? I am working on a Drupal 8 module that has a fairly large number of configs (a few content types and fields, with 20-25 config files per content type), and one thought I had for organization was to put the configs for each CT into a subfolder under config/install. However, I see that the configs are not read in this case.

Which is the better way to proceed?

1) Just place everything in config/install, with 100-150 config files.

2) Create sub-modules for each content type, which would require a bit more overhead but could be done given the module's use case.

3) Is there a way to add subdirectories in config/install?

For some background, I wrote a Python daemon that does server monitoring, and  the module handles communication between the monitors and a central reporting server. Each content type corresponds to a plugin for the monitor, so someone could turn on only the plugins that they want. However, in the current iteration I would prefer to have a core set of content types that are managed by one module.

No, you can't put config in sub-folders, those are reserved for config collections (e.g. language overrides/translations).

The only option would be submodules as you already said, and it's up to you to decide if that's something that makes sense for you.

  For some background, I wrote a Python daemon that does server monitoring, and the module handles communication between the monitors and a central reporting server. Each content type corresponds to a plugin for the monitor, so someone could turn on only the plugins that they want.

Not sure I fully understand that and it's not exactly the same but our project https://www.drupal.org/project/monitoring might still be interesting? it uses plugins and a single config entity for a sensor, it is about monitoring things about a single drupal site and not other servers (We do then use sensu to collect the data and alerting).

And without having the full picture, using content types/content for something that doesn't really sound like content seems like a strange idea. In Drupal 8, it's pretty easy to create your own entity type with support for bundles, then you could make all the shared fields base fields and would probably get rid of 90% of your configuration.


Entity Reference + Views + Profile 2 | User Filtering As the title is kinda vague (couldn't for the life of me think of something more creative) here is the case.

I have an Entity Reference field on one of my Content Types that's limited to Users.

The field searched through the users via a dedicated view.

I've installed Profile 2 and added first and last names to the users of my site.

I've added all the view's fields as search parameters in the views settings (username, first name, last name, email) but only the username and email (core drupal 'fields') seem to be able to be searched for whereas the first and last name are the ones I need mostly.

Am I missing something?

I believe its because profiles are an entity unto themselves. So you are referencing users which means that if you want the profile fields to be searchable you will need to add a relationship in the view to User:Profile. Then use this relationship on the profile fields you want searchable.

Alternatively you could use entityreference to refer to the profiles directly from the content type.


CAS username field value to be manually added to the existing user on import? I installed the CAS module on a Drupal 8 site, and it is working fine. For new users, it auto-registers the user with cas_username, but I would like to import the cas_username manually for the existing Drupal 8 user.

I also tried importing users in CSV format; I have been able to add the $account(row[0],row1), but for the CAS username import, i don't know how to import it, and in which field is stored.

'uid' => NULL,
'name' => $username,
'field_first_name' => row[0],
'field_last_name' => $row[1],
'pass' => $username,
'mail' => $row[2],
'status' => 1,
'created' => REQUEST_TIME,
'roles' => array_values($config['roles']),

I tried Managing CAS username; the suggestion given is for Drupal 7, but the same method doesn't work for Drupal 8.

How do I import the CAS username in CSV?

I find out the solution for the CAS_username import in CSV method. The method of db_insert in (authmap) table, which dynamically insert the CAS_username in respective field.

The authmap table is present in external authentication module.

    db_insert('authmap')
    ->fields(array(
     'uid' => $uid,
     'provider' => 'cas',
     'authname' => $row[0],
     'data' => 'N;',
     ))
    ->execute();

So this is the method, i dynamically update the CAS_username using CSV. If any suggestions or update in that. Kindly Prescribe it.


How to make Language Switcher Block work with unpublished nodes? On a multilingual Drupal 7 site, the Language Switcher Block used to work for both published and unpublished nodes.

Example:
node/1: English, alias=map, published
node/2: German, alias=karte, published
node/3: English, alias=table, unpublished
node/4: German, alias=tabelle, unpublished

On /node/1 or /map, the Language Switcher shows the link to German and it correctly links to /de/karte. This works also the other way around.
However, on /node/3 or /table, the block does show a link to German version, but it links to /de/node/3 instead of /de/tabelle. On the German version at /de/tabelle (or /de/node/4) the block links to /node/4 instead of /table.

As far as I know, this change was introduced between Drupal 7.24 and 7.28 and might even not be a Core issue. However, I couldn't find the source of this behaviour.

Does anyone know, if it is related to some Security Issue with unpublished nodes or where I could start looking further? I tried to find it inside core modules locale/translation and language.inc and also in i18n to no avail.

I was finally able to track this change down. The source lies within a security announcement which led to the i18n-7.x-1.11 update. In /sites/all/modules/i18n/i18n_node/i18n_node.module, l. 124 there's a new line reading

'access' => !$matches[2] ? $node_translation->status : NULL,

This line shall prevent unauthorized users from even seeing the path alias of nodes they do not have access to. However, there's no real check of permissions, this line just allows the access based on the node's status. So, even for User 1 (Superadmin) the link to the translated node is inactive if the translation is unpublished.

Whether this is only a temporary fix because of the SA or even supposed to be a permanent solution, I don't know. But that's the way it is right now and if you need to switch between unpublished translations often, you might want to comment that line.

There is already an issue at d.o for that.


How can I overidde html.html.twig in a module? I have an application that is two parts: a website front-end and a restful back-end I can do with AngularJS.
The restful part is done by a module and I need to override html.html.twig.

How do I achieve this?

Overriding templates in the modules is not suggested because Drupals architecture doesn't really support multiple modules overriding same template.

However if you are still willing to do this, you have to simply add hook_theme() like this in your module file:

/**
 * Implements hook_theme().
 */
function modulename_theme() {
  return [
    // Normally theme suggestion templates are only picked up when they are in
    // themes. We explicitly define theme suggestions here so that these
    // templates in this module are picked.
    'html' => array(
    'render element' => 'elements',
    'base hook' => 'html',
  ];
}

Note: This will cause error messages in case you don't have the html.html.twig template available in the templates folder.


How do I get a node based on id in custom content type? I have a custom content type A that has a field for node id which refers to a different content type B. While creating my view for content type A, I want to identify the id in the field entered by the admin and based on the id find out what node of content type B is being referred to and generate a teaser view for B in the View of A. Does anyone have any insight on how to do this? Its more like providing a list of References with links to an Article where Article and References are both different content types.

This is exactly what the node references field modules do. For example in your Article content type, you would create a new field 'Related to References' as a node reference field and link it to relevant nodes of the References content type. The field stores the title of the referenced node and its NID which makes it a lot more user-friendly interface than using a nid.

If you're using Drupal 7.x, the current recommendation is to use the Entity Reference module which takes over from the Node Reference module in CCK.

If you're using Drupal 6.x., you want to enable the Node Reference field which is part of the CCK module. This still leaves a migration path to 7.x by upgrading to the 'References' field module, and then migrating your reference fields to Entity Reference fields.


Load and interact with a node comments from their related node I am having some trouble in my quest to build a Drupal 7 custom node based image gallery module. I've got it working, but now I need AJAX to load and manipulate comments.
What I am doing
I've created a Drupal 7 one-image-per-node image gallery; it uses relationships, EVA and even BBQ for deep linking, when viewing the 'gallery' node, EVA feeds in the thumbs and helpful attributes, e.g. URL to full image, url to actual node. I have jQuery in my gallery node, which AJAX preloads the full images on thumb click & manipulates them for fast dynamic full screen browsing, it works perfectly! Even the BBQ deep-linking which was difficult. Some of my gallery display js code is based on http://manos.malihu.gr/tuts/sideways_jquery_fullscreen_image_gallery.html.
Update
I am trying all angles to bring in the comments. I've added one possible solution below but am going to try and figure out some other/better ways of doing this.
I am unsure about Services & Json or the views json output module and if that would be useful to me in this situation?  Would json be better to call a nodes comments?
I suppose now my question remains what is the best way to do this?  Even though this is working for me now I don't think I've found the best way yet.
Well thats where Im at, once I refine this I will pull everything into a module rather than a mix of module & theme layer bits, this will be my first module that defines content types, views and well all sorts of Drupal fun!

Ok so here is one way to do it, it's not very elegant and needs improvement.

I created a comment view that has a page display which gets NID from url so when ajax calling the content with ajax my/url/89 will return the comments for node 89. This works; even Ajax_Comments are working!

Edit: Ive fixed it so it will cache the data for the user, so when traversing the gallery, it does not load the data ad-nauseum. It stores in .data and pulls it back in if the user has already viewed it.

Anyway, even though this works I feel it needs a lot of improvement and/or different approach.  Below is some of the related updated latest code.

$(function(){

  // Override the default behavior of all `a` elements so that, when
  // clicked, their `href` value is pushed onto the history hash
  // instead of being navigated to directly.
  $("a.thumb_link").click(function(){
    var href = $(this).attr( "rel" );

    // Push this URL "state" onto the history hash.
    $.bbq.pushState({ image: href });

    // Prevent the default click behavior.
    return false;
  });

// Keep a mapping of url-to-container for caching purposes.
  var cache = {

   '': $('#gall-default') // If url is '' (no fragment), display this div's content.
  };

  // Bind a callback that executes when document.location.hash changes.
  $(window).bind( "hashchange", function(e) {
    // In jQuery 1.4, use e.getState( "url" );
    var url = $.bbq.getState( "image" ); //Get State from the above push "image"

    // In this example, whenever the event is triggered, iterate over
    // all `a` elements, setting the class to "current" if the
    // href matches (and removing it otherwise).
    $("a.thumb_link").each(function(){
      var href = $(this).attr( "rel" );

      if ( href === url ) { //Mark the active thumb and launch its content!

            $(this).addClass( "current" );
            $("#gall-default").css("display","none");
            //event.preventDefault();
            var $this=this;
            $bgimg.css("display","none");
            $preloader.fadeIn("fast"); //show preloader
            //style clicked thumbnail
            $outer_container_a.each(function() {
                $(this).children(".selected").css("display","none");
            });
            $(this).children(".selected").css("display","block");
            $outer_container.data("selectedThumb",$this); //get and store next image and selected thumb
            $bg.data("nextImage",$(this).next().attr("href"));
            $bg.data("newTitle",$(this).children("img").attr("title")); //get and store new image title attribute
            itemIndex=getIndex($this); //get clicked item index
            lastItemIndex=($outer_container_a.length)-1; //get last item index
            $bgimg.attr("src", "").attr("src", $this); //switch image

            //set context for node load bits
            var node = $(this).attr( "node" );

            $("#ajax-div .inner").empty();

             if ($(this).data('comm.cachedHtml')) {
                  $('#ajax-div .inner').html($(this).data('comm.cachedHtml'));

             } else {

                var toLoad = $(this).attr('node');// Get the URL of the clicked link.
               $.ajax({ // Now load the content
                    url: toLoad,
                    cache: true,
                    beforeSend: function () {
                    $("#preloader2").fadeIn("fast");
                },
                    success: function(data) {

                      $('#ajax-div .inner').html($('#content', data));// Inject new content
                      $("#preloader2").fadeOut("fast");
                      $(this).data('comm.cachedHtml', data);
                      Drupal.attachBehaviors('#ajax-div .inner');
                    }
                });

              }

      } else { //Un-Mark Thumb & other deselecting
         $(this).removeClass( "current" );

      }
    });

    //do something  here..
  });

  // Since the event is only triggered when the hash changes, we need
  // to trigger the event now, to handle the hash the page may have
  // loaded with.
  $(window).trigger( "hashchange" );
});


Pass php variables to js without drupal behaviour I stand on the following tricky situation:

I have a node with geofield coordinates attached. I am constructing an array of points. Something like:

Array
(
[86] => Array
    (
        [0] => Array
            (
                [lat] => 39.1641410477
                [lon] => -2.633972168
            )

        [1] => Array
            (
                [lat] => 41.0420738489
                [lon] => -2.633972168
            )

        [2] => Array
            (
                [lat] => 41.0420738489
                [lon] => 1.2524414063
            )

        [3] => Array
            (
                [lat] => 39.1641410477
                [lon] => 1.2524414063
            )
        [4] => Array
            (
                [lat] => 39.1641410477
                [lon] => -2.633972168
            )
    )

[85] => Array
    (
        [0] => Array
            (
                [lat] => 39.1641410477
                [lon] => -2.633972168
            )

        [1] => Array
            (
                [lat] => 41.0420738489
                [lon] => -2.633972168
            )

        [2] => Array
            (
                [lat] => 41.0420738489
                [lon] => 1.2524414063
            )

        [3] => Array
            (
                [lat] => 39.1641410477
                [lon] => 1.2524414063
            )
        [4] => Array
            (
                [lat] => 39.1641410477
                [lon] => -2.633972168
            )
    )
)

I want to pass this to my-googlemaps.js in order to be used by google's init map
Google map is defined as:

my-map:
  header: true
js:
  js/my-googlemaps.js: { }
  https://maps.googleapis.com/maps/api/js?key=my_key&callback=initMap: {type: external, attributes: {defer: true,async: true}}
dependencies:
  - core/drupal
  - core/drupalSettings

my-googlemaps.js:
  console.log(Drupal.settings);
  function initMap() {}

This way I get Drupal.settings undefined, which makes sense I guess.
On the other hanve if I place initMap into a behavior It can not be seen as a callback as defined in googleapis.com before.

Has anyone stumbled with this before? Any idea how to attack the problem?

You can follow document.

  Attaching configurable JavaScript

  In some cases, you may want to add JavaScript to a page that depends
  on some computed PHP information.

  In this case, create a JavaScript file, define and attach a library
  just like before, but also attach JavaScript settings and have that
  JavaScript file read those settings, via drupalSettings (the successor
  to Drupal 7's Drupal.settings). However, to make drupalSettings
  available to our JavaScript file, we have to do the same work as we
  had to do to make jQuery available: we have to declare a dependency on
  it.

  So that then becomes:

cuddly-slider:
  version: 1.x
  js:
    js/cuddly-slider.js: {}
  dependencies:
    - core/jquery
    - core/drupalSettings

  and

$build['#attached']['library'][] = 'fluffiness/cuddly-slider';
$build['#attached']['drupalSettings']['fluffiness']['cuddlySlider']['foo'] = 'bar';

Where 'bar' is some calculated value.

  Then cuddly-slider.js will be able to access
  drupalSettings.fluffiness.cuddlySlider.foo (and it will === 'bar').

In your case. You need use hook_preprocess_node() to add array geofield.

function YOUR_MODULE_preprocess_node($vars) {
  // You nedd process to get $geofield
  $vars['#attached']['drupalSettings']['geoField'] = $geofield
}

and file js/my-googlemaps.js you need code.

(function($, Drupal, drupalSettings) {
  Drupal.behaviors.yourbehavior = {
    attach: function (context, settings) {
       var geoField = drupalSettings.geoField.
      // You can init map here.
    }
  };
})(jQuery, Drupal, drupalSettings);


Override page template and preserve administration navigation bar Short version; I am trying to override the default page.html.twig (in D8) for a controller from my module and the following examples I've found have not worked:

https://www.drupal.org/node/2499827
Override html.twig.html within custom module

My company is developing a custom module to embed a React app we originally built for another system inside the admin side of Drupal. As such, we would like to keep the admin navigation visible but the main body of the page should just be the react app.

So far, I have successfully embedded the app as the content of a page, but still have the page's header, footer, breadcrumbs, etc. I'm not sure if I'm declaring my module's theme incorrectly, or if my naming is wrong for my template, or something else.

Thanks in advance!

Module name: my_module

my_module.info.yaml

name: Overriding page module
description: "Module with a template that overrides the default page.html.twig"
package: mystuff

type: module
core: 8.x

my_module.module

function my_module_theme() {
    $theme['page__my_module'] = [
        'template' => 'page--my_module',
    ];

    return $theme;
}

my_module.routing.yml

my_module.content:
  path: '/hello'
  defaults:
    _controller: '\Drupal\my_module\Controller\HelloController::content'
    _title: 'Hello World'
  requirements:
    _permission: 'access content'

templates/page--my_module.html.twig

{#
  Taken from https://api.drupal.org/api/drupal/core%21themes%21seven%21templates%21page.html.twig/8.2.x
#}

      {{ page.header }}

    {{ page.pre_content }}
    {{ page.breadcrumb }}

      {{ page.highlighted }}
      {% if page.help %}

          {{ page.help }}

      {% endif %}

WHY DOESN'T THIS TEMPLATE GET USED!?

      {{ page.content }}

src/Controller/HelloController.php

<?php

namespace Drupal\my_module\Controller;

use Drupal\Core\Controller\ControllerBase;

class HelloController extends ControllerBase {
    public function content() {
        return array(
            '#type' => 'markup',
            '#theme' => 'my_module',
            '#markup' => $this->t('Hello World!')
        );
    }
}

UPDATED

Thanks to @kiamlaluno, I found I could use the theme suggestions hook to tell drupal what theme to apply. I changed my_module.module to:

<?php

function my_module_theme_suggestions_page(array $variables) {
  $path = explode('/', trim(\Drupal::service('path.current')->getPath(), '/'));
  if (isset($path[0]) && $path[0] == 'hello') {
    return 'page--my-module';
  }
}

function my_module_theme() {
    $theme['page--my-module'] = [
        'template' => 'page--my_module',
    ];

    return $theme;
}

and removed the #theme item from the controller's render array. It works now!

What the code is missing is the code that sets those variables the template file is using. Since you are using page--mymodule as template name, the module needs to implement template_preprocess_page__mymodule().
Alternatively, you can suggest a template file using hook_theme_suggestions_page().
function my_module_theme_suggestions_page(array $variables) {
  $path = explode('/', trim(\Drupal::service('path.current')->getPath(), '/'));
  if (isset($path[0]) && $path[0] == 'hello') {
    return 'page--mymodule';
  }
}

Implementing hook_theme_suggestions_page() like I show, page--mymodule.html.twig will get the variables set in template_preprocess_page(), which are the same variables passed to page.html.twig.


How to add a region block to the custom template contact form page? I trying to add a region block to custom template Contact Form page: "contact-message-feedback-form.html.twig"

Define a region (like: contact_info) to theme-name.info.yml and
add {{ page.contact_info }} in contact-message-feedback-form.html.twig

Contact form rendered successful but when add block to the region not display block in this region.

theme-name.theme:

/**
 * Implements hook_theme().
 */
function crown_ui_theme($existing, $type, $theme, $path) {
  return [
    'contact_message_feedback_form' => [
      'render element' => 'form',
    ]
  ];
}

theme-name.info.yml:

regions:
  contact_info: 'Contact Info'

contact-message-feedback-form.html.twig:

<div class="col-sm-3">
{{ page.contact_info }}
</div>

I used twig_tweak module to load and render a block on any where in Drupal.
Read more on the module docs:

https://www.drupal.org/docs/8/modules/twig-tweak/rendering-blocks-with-twig-tweak


Is it possible to show a menu in a view as buttons? I'm trying to build a page with a quick menu. Now I've created a menu by the regular way and I've shown this on the place i wanted. Now due to the way my site currently looks, this is very out of the shape I wanted it to be.

Now my question is: Is it possible to show my menu items as a view and decorate them with a button (and if possible an icon from the FontAwesome library)?

My idea would look something like this, with the blue things as buttons creating for every menu item:

A module or a work around would both be fine!

with https://www.drupal.org/project/menu_link_attributes
you can add a css classes to each menu item so that you can theme it as needed.


Modal Error Messages Displaying on Main page I have a page. Once i click on Button on that page. It opens jQuery Modal.

In that Modal Box. I'm rendering Form. I have put 1 fields test as required true.

Issue is when I click on Submit button. It closes Modal Box & showing errors on Main Page.

I need that when it clicks on Submit button. It will not close Modal Box & Display errors on Modal box instead of Main page.

I know this is pretty old so hopefully you found another solution by now. Since I happened to come across this near the top of my Google search for a slightly different issue though...

In your form_alter hook for the modal, you will need to add something like this:

$form['#prefix'] = '
';
$form['#suffix'] = '
';
$form['status_messages'] = [
    '#type' => 'status_messages',
    '#weight' => -10,
];

Then the callback function for your form that closes the modal and such will need to look something like this:

$response = new AjaxResponse();

// If there are any form errors, re-display the form.
if ($form_state->hasAnyErrors()) {
    $response->addCommand(new ReplaceCommand('#modal-form', $form));
} else {
    //Close the modal.
    $command = new CloseModalDialogCommand();
    $response->addCommand($command);
}
return $response;

This will tell it to apply the error message to your #modal-form div instead of the form in the background.


Get field machine name inside HOOK_preprocess_file_link()? I am hoping to get the field name inside the HOOK_preprocess_file_link.

Only wanting to alter the link of the file for certain field names.

Hook_preprocess_field() would probably work, but would prefer to use HOOK_preprocess_file_link().

Is it possible to get the field name in this hook?

MYMODULE.module:

function HOOK_preprocess_file_link(&$variables, $fieldName) {

  kpr($fieldName); // This returns "file_link" instead of the field name like "field_myfilefield".

}

function HOOK_preprocess_field(&$variables) {

  if (isset($variables['field_name'])) {
    $fieldName = $variables['field_name'];
  }
  HOOK_preprocess_file_link($variables, $fieldName);

}

You need to pass the field name to the file link through hook_preprocess_field()
A similar approach is used in Themable Forms module.
Check its module file.


How to make a facet search on a taxonomy term contained in a paragraph contained in a content type? On Drupal 8, I try to make a facet on a taxonomy term contained in a paragraph entity contained in a content type. Is it possible?
My stack : Druapl 8.9.0 + Search API 8.x-1.17 + Facets 8.x-1.5
In Search API, I have indexed the taxonomy from the paragraph. In database I have a new table with 2 columns entity and taxonomy. It seems OK to link node with paragraph with taxonomy id.

I have created the facet without problem but it does not display on my search page.
Is someone has realized this before? Or maybe a advise to resolve this problem.

A solution is to associate the taxonomy directly with the content type (field_ingredient_search_index in the example below) and make a hook to update it automatically.
$nodeTerms = []; // 1,2,3 = terms IDs
$erase = [];
$node->set('field_ingredient_search_index', $erase);

foreach ($node->get('field_liste_ingredients')->referencedEntities() as $enty){

  if($enty->getParagraphType()->id == 'ingredient' && isset($enty->get('field_ingredient')->target_id)) {
      $nodeTerms[] = $enty->get('field_ingredient')->target_id;
  }

}

$node->set('field_ingredient_search_index', $nodeTerms);


prevent submit in ajax call I have a form  with 2 submit in it, one of them is a button to generate codes, everytimes I click on generate form_submited called up and a record insert in db, how can I prevent form_sumit in ajax triggering?

function rah_cc_generate_form($form,$form_state){
    $form=array();

    $form['gen']=array(
        '#type' => 'fieldset',
        '#name' =>t('generate gift card code'),
        '#collapsible' => TRUE,
        '#collapsed' => false,
//        '#weight' => 5,

    );
    $form['gen']['code']=array(
            '#type' => 'textfield',
            '#title' => t('gift code'),
            '#default_value' => '',
            '#prefix' => '
',
            '#suffix' => '
',
            '#size' => variable_get('rah_gc_code_size', 8),
            '#maxlength' => 20,
            //'#required' => TRUE,
    );
    $form['gen']['price']=array(
            '#type' => 'textfield',
            '#title' => t('price'),
            '#default_value' => 10000,
            '#size' => 10,
            '#maxlength' => 20,
            '#required' => TRUE,
    );
    $form['gen']['status'] = array(
  '#type' => 'checkbox',
  '#title' => t('status'),
    '#default_value' => 1,
);

    $form['gen']['random']=array(
     '#type' => 'submit',
    '#value' => t('generate'),
    '#description' => t("if you want generate random use this plz"),
    //'#weight' => 1,
    //'#submit' => array('rah_cc_generate_random'), // If no javascript action.
    '#ajax' => array(
      'callback' => 'rah_cc_generate_ajax',
      'wrapper' => 'gc-code',
      'method' => 'replace',
      'effect' => 'fade',
      ),
   );

    $form['gen']['save']=array(
        '#type' => 'submit',
        '#value' =>t('save'),
         );
    ym($form);
    return $form;

}
function rah_cc_generate_ajax(&$form,$form_state){

    //return $form['gen']['code']['#default_value']=33;
     $form['gen']['code']['#value']=rah_cc_generate();
     //$form_state['values']['code']['und'][0]['value']=44;
     return $form['gen']['code'];

}

update
I use      'prevent'=> 'sumbit', but not get answer :(

 $form['gen']['random']=array(
     '#type' => 'submit',
    '#value' => t('generate'),
    '#description' => t("if you want generate random use this plz"),
    //'#weight' => 1,
    //'#submit' => array('rah_cc_generate_random'), // If no javascript action.
    '#ajax' => array(
      'callback' => 'rah_cc_generate_ajax',
      'wrapper' => 'gc-code',
      'method' => 'replace',
      'effect' => 'fade',
      'prevent'=> 'sumbit',
      ),
   );

$form_state variable holds 'triggering_element' element which indicates what button triggered (or also you can use #clicked_button element), example (in ajax callback function):

function my_form_submit($form, &$form_state) {
  //dpm($form_state);
  if($form_state['triggering_element']['#value'] == 'MY_ELEMENT\'S_NAME') {
    //do_operation();
  }
}


Quiz question update issues I discovered the quiz module a few hours ago and  began experimenting.

I setup a quiz node and added one multipleoption question. I added three options to the question.

The problem is when I edit the question and add to the existing 3 options, the forth and fifth options do not showup when viewing the quiz question - only the original three questions show.

Instead a new "multiple choie question" node is created - not what I intended nor asked for.

Can anyone help me understand and fix this issue?

PS: If anyone knows of a better alternative to the quiz module, please let me know.

You are dealing with a caching issue. I just added the quiz module to a fresh install of Drupal 7.28, made a quiz with one question with three choices, and when I viewed it there were three options. So far so good. Then, I went back and added two options to that question, but when I viewed it I didn't see the two new options show up.

All I had to do was take one version of the quiz and the next time I loaded the quiz the new options showed up. I suspect each user gets a cached version of the quiz when they start taking it, which would make sense in that you don't want to have a different/changed quiz for someone who is halfway through taking one.

I haven't used the quiz module at all, but it looks like it has steady, active development, which is good. You could look into Drupal Webform module as an alternative or search for Drupal Learning Management Systems, if an LMS is really what you are building.


How to create the history of particular field of content I have a content type called Fruitera, which has a select list field_fruits, which has these possible options:

Apple
Banana
Orange
Pineapple

For this I have created a view, and now I want to see the history of particular field_fruits.

Whenever we edit the content it will replaced by another fruit, I want to see previous history of field_fruits for content created in a view.

Any suggestions know how to do this?

Track Field Changes is a module that allows you to easily enable tracking/auditing on changes to fields, and has views integration.

I hope this will make your work.


Hook or event before a page gets cached Is there a hook or event I can tie into before a page gets cached. I need a hook/event that I can call so that I can run some logic on the page that is about to be cached to tell Drupal if I want a particular page to actually get cached. This is a very specific use case to the website I'm working on.

If you need to decide whenever a page should be cached from Drupal, you need to create a service that implements the \Drupal\Core\PageCache\ResponsePolicyInterface interface and it's tagged page_cache_response_policy, as described in Flexible page cache policy.

That page shows code that can be used as example. You can also use code that Drupal core actually implements, as example, like the code for the node.page_cache_response_policy.deny_node_preview service.

The code implementing the service is quite simple. It becomes more complex basing on the logic you need to apply to decide when a page should be cached.

class DenyNodePreview implements ResponsePolicyInterface {

  /**
   * The current route match.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * Constructs a deny node preview page cache policy.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The current route match.
   */
  public function __construct(RouteMatchInterface $route_match) {
    $this->routeMatch = $route_match;
  }

  /**
   * {@inheritdoc}
   */
  public function check(Response $response, Request $request) {
    if ($this->routeMatch
      ->getRouteName() === 'entity.node.preview') {
      return static::DENY;
    }
  }

}


Paginated list of group members I want to output the membership of a drupal group, but limiting the number of members shown, instead of outputting all members at once, (that i can do with the code bellow).

    $members = $group->getContentEntities('group_membership');

If you are able to build an entity query for the group members you can use $query->pager(). See block to display nodes using entityQuery with pager

If not, you have to calculate the pager variables yourself. There is only one example for a pager in core that is not using a pager query, the taxonomy terms overview OverviewTerms::buildForm. Or you can use pager_default_initialize().

And a third and probably quickest solution is to build a view for the group members.


Load Javascript when a particular form is loaded I have the code below in my own drupal module(myid):

myid.module file:

function myid_init() {
    drupal_add_js(drupal_get_path("module", "myid") . "/js/myid.js");
}

function myid_menu()
{
    $items = array();

    $items['admin/settings/myid'] = array(
        'title' => 'myid Settings',
        'description' => 'Configuration options for the myid module',
        'page callback' => 'myid_admin_settings',
        'access callback ' => 'user_access',
        'access arguments' => array('administer site configuration'),
    );
    return $items;
}

function myid_admin_settings()
{
    return drupal_get_form('myid_settings_form');
}

function myid_settings_form()
{
    $form = array();

    $form['settings'] = array(
        '#type' => 'item',
        '#title' => t("Registrar's Signature"),
        '#description' => t(''),
        '#markup' => "<canvas id='myid_registrar_signature' width='500' height='100'></canvas>",
        '#required' => TRUE,
    );
    return $form;
}

myid.js file:

1. $( document ).ready(function() {
2.     myid_retrieve_save_information();
3. });
4. function myid_retrieve_save_information(){
5.     var cnv_rsignature = document.getElementById("myid_registrar_signature");
6.     var ctx_rsignature= cnv_rsignature.getContext('2d');
7. }

Why does every time I load the page, it gets the following error pointing to Line 6 in myid.js:

Uncaught TypeError: Cannot read property 'getContext' of null

Is it because #myid_registrar_signature was not yet loaded when Line 6 was executed? Where did I went wrong?

Loading which page causes the error? The enabled modules are loaded on every page request, because your module is enabled so it is loaded on pages, it tries to get an element that is not built yet!

Look at hook_init documentation. it says:

  This hook is run at the beginning of the page request. It is typically
  used to set up global parameters that are needed later in the request.
  When this hook is called, the theme and all modules are already loaded
  in memory.This hook is not run on cached pages.To add CSS or JS that
  should be present on all pages, modules should not implement this
  hook, but declare these files in their .info file.

So you shouldn't load the js files in there.

$(document).ready does not wait for images or scripts, try $(document).load


Media module and views. Cannot make video image linked to node Using drupal 7.20,
Media 7.x-2.0-unstable7,
Media Youtube 7.x-2.0-rc2,
File Entity 7.x-2.0-unstable7,
Entity View Modes latest version.

Created new content type called "video", added video field type "Multimedia asset", Allowed remote media types "Video", Allowed URI schemes "youtube:// (YouTube videos)", "public:// (Public files)"

With Views 3 i am displaying Content: Video, File view mode "video_preset" (preset i created with Entity View modes module). But it only displaying an image, is there any working way to make that image a link?

Already tried "rewriting output of this field" thing, that not working at all.

Maybe you could try the File Entity Link module?  Here is a quote about it (from the module's project page):

Out of the box, the Media and File Entity modules attach media to entities using Fields but they provide no way to then display media in those fields as links to the parent entity. A common use-case for this would be a teaser view of a node showing an image linked to the node.
This very simple module adds an option to the "File Types" view mode settings to accomplish this (at admin/config/media/file-types/manage/image/file-display for images).


Theming a views field output using views-view-fields.html.twig I am trying to customize a views output on a view page to wrap the fields in custom markup. I need to group a set of fields to achieve the desired layout like so:

Example:

       {{ field.[field_name_1].content }}

       {{ field.[field_name_2].content }}
       {{ field.[field_name_3].content }}
       {{ field.[field_name_4].content }}

This is what I have come up with so far:

{% if view.projects_page -%}

        {{ field.field_project_image.content }}

        {{ field.field_project_header.content }}
        {{ field.field_sub_header.content }}
        {{ field.field_short_project_description.content }}

{%- endif %}

This doesn't throw any errors but also doesn't seem to work because
 {% if view.projects_page -%} does not target the view in the way I thought it would.

So the question is - How do I detect the view with a conditional so I get the output desired above?

You need to refer documentation for the working with twig template. Here you can use conditional twig :

Twig: {% if field.[field_name].content is not empty %} field.[field_name].content {% endif %}


How to change logged-in user permission in hook_node_view? Can anyone please let me know how can we achieve the following scenario

I want to change the role of the logged-in user before viewing the node. When you click on the node for viewing it, I want the roles to be changed and then display the content accordingly with the access permissions.

using  hook_node_access(),here you can check user role by using

global $user;
$roles=$user->roles;


Panels- How can I show the related terms pane only if the term being displayed has only the root as parent? I am using the awesome Panels module to override the default taxonomy display.  I am using the Related Terms content pane (built-in to Panels) to show children of the current term.

My vocabulary looks like this:

Country
State
City

What I would like to do is show the child terms (related terms pane) only for countries, not states or cities.  In other words, I would like to show the related terms pane if and only if the term has no parents except the root parent.

However, the only Visibility Rule that seems to apply is Term has Parent(s), which requires a user-created term (not the root term) to be selected.  I could select all of the terms and then check Reverse, but I have hundreds of locations and more are being added all the time, making this unfeasible.  Is there some other way?

I wrote something quick together over in Different variant for other Taxonomy hierarchy within vocabulary, that gives a selection rule for the term level.

It sounds like that would help you.


Modify metatag description programmatically Drupal 8 I modified the meta-tag title for a view in hook_preprocess_html() using the following code.

if (isset($variables['head_title'])) {
    $variables['head_title'] = $variables['page']['#title'] . " | My web";
}

Is it possible to modify the description in the same hook?

That depends on your theme and its use of $variables in combination with the description meta tag.

A code snippet for Drupal 8 that does what you want for the Bartik Theme would be the following:

function bartik_page_attachments_alter(array &$page) {
  $description = array(
    '#type' => 'html_tag',
    '#tag' => 'meta',
    '#attributes' => array(
      'name' => 'description',
      'content' => 'your description content',
    ),
  );
  $page['#attached']['html_head'][] = [$description, 'description'];
}

This was inspired by this post => https://drupal.stackexchange.com/a/134145/57183

Maybe this does solve your problem!


How can I access values of multiple select list in a form? I have a custom form in a custom module with multiple select:

$form['sponsors'] = array(
 '#type' => 'select',
 '#options' => $sponsors,
 '#multiple' => TRUE,
 '#size' => 20,
);

But I'm stumped how to access the submitted multiple values in the form_submit function. I tried to get the values by looping through the key (one guess was $form['values']['sponsors'][$key]) but no luck... anyone can point me in right direction would be appreciated!

in case whether the user may select more than one item, size value be written like this way:

'#size' => $multiple ? min(12, count($options)) : 0,

this is how used in (taxonomy.module).


What do we hook in Drupal 6 for inbound URL rewrites? Where conditional rewrite is desired, not supported by existing path modules, and where we'd prefer to stay out of .htaccess, where might we hook in Drupal 6?

Along the lines of Drupal 7 hook_URL_inbound_alter, I think.

hook_URL_inbound_alter was introduced as part of a contributed module in Drupal 6 (URL alter), and was moved to core with Drupal 7.


How to add custom month in Date field? In my academic website, I need to add graduation year as a date field but for month field, I want to add only two month (May and December).

Can I do this?

My professor want like this and i don't have any idea to solve my situation.

Can you help me?

Use hook_form_alter to change the date field on the node form you can only select those two months (and disable the rest).


Add a URL as filter criteria in Views I have a page of content type insert which adds images to my website. It currently just displays images in rows when you click to view the album name pages.

I have installed FlexSlider as I want to use that module to display all images  that are on pages that contain /Album/AlbumName in the URL  as a slideshow automatically. How do I do that in Views?

If you have a content type which has a photo filed and you want to show the photos in the form of slider, Than I will suggest to use FlxSlider.

Go to your_seite/admin/structure/types/manage/your_content/display/
Change the photo filed form to flexslider
Click the setting icon to customize the slider options
Click Save

If your want to have some sort of photo album in your site than I will suggest to use Juicebox HTML5 Responsive Image Galleries

This module provides an integration between the popular Juicebox HTML5 responsive gallery library and Drupal. Juicebox is in many ways the successor of Simpleviewer and offers a powerful cross-device solution for image galleries, sliders and more.


How to use Form API #attached and module's own scripts with jQuery Multi module? I was using jQuery Update module, but it conflicts with Views and feature requests for library version per page or per theme are consistently killed. On the other side, Views maintainers seems to assume that if UI works with distribution's jQuery, it isn't broken. Long story short, I was forced to forget about jQuery Update the way we know it.

Solution I found is jQuery Multi module, as it allows load updated jQuery only, if there is a library that requires it in use on the page. And for things like Chosen (when jQuery Update is hacked out of requirements) it works great. Now, I have problem with javascripts directly attached to forms:

$form['#attached']['js'] = array(
  drupal_get_path('module', 'aat_pc_product') . '/js/tag.js',
  drupal_get_path('module', 'aat_pc_product') . '/js/tabs.js',
  drupal_get_path('module', 'aat_pc_product') . '/js/categories.js',
);

jQuery Multi claims it can be used on any js file, but it's documentation says:

  C) Put the JS anywhere else, like in a custom module, and use hook_jqmulti_files() to load it. No need to use the alias.
  38

  D) Put the JS anywhere, use the provided alias, and don't use the jqmulti hooks or UI. Simply load with drupal_add_js() or something similar. If you're only using this method, make sure to select the 'Load Always' checkbox in the jQuery Multi config.

Now, I can't do C) as I'm using Form API and I can't do D) as it breaks Views.

Form API for #attached says:

  Description: Allows loading of CSS, Javascript, libraries,

Converting my scripts to a libraries would help, as A) and B) options for jQuery Multi are for libraries, but only examples provided by Form API are for JS and CSS files.

There is one use-case for libraries provided:

$form['#attached']['library'][] = array('system', 'jquery.cookie');

but it's there without description.

I can make my scripts library:

function amymodule_library() {
  $module_path = drupal_get_path('module', 'mymodule');
  $items = array();
  $items['mymodule_form'] = array(
    'title' => t('My Module Form'),
    'version' => '1.0.0',
    'js' => array(
        $module_path . '/js/tag.js' => array(),
        $module_path . '/js/tabs.js' => array(),
        $module_path . '/js/categories.js' => array(),
    ),
    'css' => array(
      $module_path . '/css/mymodule_form.css' => array(),
    ),
  );
  // dpr($items);
  // die();
  return $items;
}

And attach it as a library to a form:

$form['#attached']['library'] = array(
  array('mymodule', 'mymodule_form'),
);

Sadly this does not make it appear on the configuration screen:

I know it's due to the first 2 methods described in documentation:

  A) Put the JS in sites/all/libraries/ and use the UI at admin/config/system/jqmulti to select your library. All the library's JS files will be loaded with the jqmulti jQuery version. There is no need to use the alias in this case. This is ideal if you're using a prepackaged jQuery library or plugin.

  B) Put the JS in sites/all/libraries/ and use hook_jqmulti_libraries() to include the library. No need to use the alias. This is ideal if you're using a prepackaged jQuery library or plugin, and is equivalent to method A.

Of course I cannot put my scripts there, they are built in part of my module.

Now, I'm perfectly open to module hacking, if that's what needed, but if there is a way to "pretend" that my module's library is in the folder jQuery Multi wants it to be, I would be grateful to know it.

Solution seems to be to hack jQuery Multi module.

First, we want to add module-provided libraries to the list in configuration options. Function responsible for it is jqmulti_get_available_libraries():

/**
 * Returns available libraries to be used in the admin form.
 */
function jqmulti_get_available_libraries() {
  $libs = libraries_get_libraries();

  unset($libs['jquery']);
  foreach ($libs as $key => $value) {
    $libs[$key] = $key;
  }
  return $libs;
}

To display module-provided libraries, we need to add following line:

$libs += module_invoke_all('library');

Of course now it looks ugly:

List is long and hard to understand, because these are machine names only. Red colour used to distinguish element I added by hand after taking screenshot, it's all black folks.

Form element is defined in jqmulti.admin.inc, but it's the only place that ever uses jqmulti_get_available_libraries(), so we may stay inside it instead, to limit changes to narrow area. If we change this:

  foreach ($libs as $key => $value) {
    $libs[$key] = $key;
  }

to this:

foreach ($libs as $key => $value) {
  if(isset($value['title'])) {
    $libs[$key] = '' . $value['title'] . ' ' . @$value[version] . ' (' . $key . ')';
  } else {
    $libs[$key] = '' . $key . ' (' . $value . ')';
  }
}

output will get a lot more readable:

Again, blanked a project-related row but it is there all right.

But now the fun part begins. I can save, but logic is all wrong:

  Warning: scandir(sites/all/libraries/product_form): failed to open dir: No such file or directory in jqmulti_find_all_js_files() (line 180 of /var/www/sites/all/modules/jqmulti/jqmulti.module).
  Warning: scandir(): (errno 0): Success in jqmulti_find_all_js_files() (line 180 of /var/www/sites/all/modules/jqmulti/jqmulti.module).
  Warning: Invalid argument supplied for foreach() in jqmulti_find_all_js_files() (line 181 of /var/www/sites/all/modules/jqmulti/jqmulti.module).

Error is located in function jqmulti_find_all_js_files($dir) function. Obviously module still tries to use old way of scanning /sites/all/libraries even when I clicked a library that is not there. Function is called from jqmulti_get_library_files($library, $reset = FALSE) that blindly assume all files are in 'sites/all/libraries'. First, it's a bug in it's own right, second it's not sufficient. We need to change:

$base_path = 'sites/all/libraries';

to something smarter. For example:

if(isset($libraries_libraries[$library])) { // Give precedent to old way
  $path = $libraries_libraries[$library];
} elseif(isset($module_libraries[$library])) {
  $path = NULL;
  $files = array_keys($module_libraries[$library]['js']);
} else { // Fallback to the old way, for what it's worth
   $path = $base_path . '/' . $library;
}

As you can see, if module gave us files already, there is no need to play with $path, we may use it directly. So code below needs to be wrapped in if.

That's all, now it works. Without conflict with Views, but with all jQuery Multi's own issues, some especially urgent for me.


Webform rules: compare a form field to a user field I am trying to create a rule that will update a user piece of info from a webform.
The webform is a service request form and the field I want to update is a car license plate field, present both in user fields and webform fields.
I installed the Webform rules module, which exposes the webform in the rules conditions but I cannot see anything changed. No webform or webform field appears in the conditions selections.
Does this module work? Am I missing something?

I guess that you can enable Rules Forms support Submodule of Rules. This submodule shows the correct name of your form (above each respective form) to be used with Rules.

Also, see this answer, is related with Rules Forms support submodule and other steps to make a comparision form fields with rules, I think that could be useful.

Update: This is the address to download the module Rules Forms support for Drupal 7 http://drupal.org/project/rules_forms

this is an screen shot in Drupal 7 about when is enabled rules for a specific webform:


How to print a flag in a block programmatically? I am creating a module which displays a block. I have created a flag within the module, and I am trying to display it through the block_view() hook. Currently struggling to get there...

I am doing this instead of going through the template pages because there are certain conditions and functions involved to decide if I show the flag or not, making it easier for me at the minute to do this in a block.

Unfortunately, the block isn't working. Am I not displaying it correctly?

function get_involved_block_info() {
$blocks = array();
$blocks['get_involved_block'] = array(
'info' => t('Get involved block'),
'weight' => 10,
);
return $blocks;
}

function get_involved_flag_default_flags() {
$flags = array();
$flags[] = array(
'content_type' => 'node',
'name' => 'get_involved_interested',
'title' => 'Interested',
'global' => FALSE,
'types' => array('ad'),
'flag_short' => 'Join',
'flag_long' => 'I want to join',
'flag_message' => 'Your interest was registered',
'unflag_short' => 'Cancel',
'unflag_long' => 'Cancel my interest',
'unflag_message' => 'Your interest was deleted',
'show_on_page' => TRUE,
'show_on_teaser' => FALSE,
'show_on_form' => TRUE,
'status' => TRUE,
'locked' => array('name', 'types', 'global'),
);
return $flags;
}

function get_involved_block_view($delta) {
global $user;
$block = array();
if (arg(0) == 'node' && is_numeric(arg(1))) $nodeid = arg(1);
$node = node_load($nodeid);

//First of all, if the user is the author, do not show this node
if ($node->uid == $user->uid)
{
} else {

$block['title'] ='Get involved';

$block['content'] = flag_create_link('get_involved_interested', $nodeid);

  return $block;
}
}

You are adding raw PHP code as block content; you should execute it directly instead.

Try this:

$block['content'] .= flag_create_link('mymodule_interested', $node->nid);

UPDATE

You were using Flag API v1, instead of v2. Below is the full code:

function get_involved_block_info() {
  $blocks = array();
  $blocks['get_involved_block'] = array(
    'info' => t('Get involved block'),
    'weight' => 10,
  );

  return $blocks;
}

function get_involved_block_view($delta) {
  $block = array();
  switch ($delta) {
    case 'get_involved_block':
      global $user;
      $node = menu_get_object();
      // First of all, if the user is the author, do not show this node.
      if ($node && $node->uid != $user->uid) {
        $block = array();
        $block['subject'] = t('Get involved');
        $block['content'] = flag_create_link('get_involved_interested', $node->nid);

        return $block;
      }
    break;
  }
}

function get_involved_flag_default_flags() {
  $flags = array();
  // Exported flag: "Interested".
  $flags['get_involved_interested'] = array(
    'entity_type' => 'node',
    'title' => 'Interested',
    'global' => false,
    'types' => array(
      0 => 'ad',
    ),
    'flag_short' => 'Join',
    'flag_long' => 'I want to join',
    'flag_message' => 'Your interest was registered',
    'unflag_short' => 'Cancel',
    'unflag_long' => 'Cancel my interest',
    'unflag_message' => 'Your interest was deleted',
    'unflag_denied_text' => '',
    'link_type' => 'toggle',
    'weight' => 0,
    'show_on_teaser' => false,
    'show_on_form' => true,
    'status' => false,
    'locked' => array(
      'name' => 'name',
      'types' => 'types',
      'global' => 'global',
    ),
    'module' => 'get_involved',
    'api_version' => 3,
    'import_roles' => array(
      'flag' => array(),
      'unflag' => array(),
    ),
    'show_in_links' => array(
      'full' => true,
    ),
  );

  return $flags;
}


Drupal 7 block api, is this custom module correct? This is my first time attempting at writing a custom module i had a quick look over the api but forgive me if its wrong

We have been having some small issues regarding the drupal core blocks, the main page content block completely disregards the weigh assigned to it, and we are stumped for clues, no help or ideas have been found from posting on drupal or extensively searching google.

The final option we have is to manually overwrite the weight, i threw this together quickly

 <?php
 funtion hook_block_info_alter() {
$blocks['Main page content'] = array(
    'weight' => ('-9999'),
    );
 }
 ?>

Would that successfully overwrite the weight of the main page content block?

Very nearly, but not quite.

You're missing the function arguments in your hook implementation, so there's nothing there to actually alter.
The blocks array is keyed by module, then block delta, so you would need to access the block using those instead of the title as you currently are.
You're trying to overwrite the system main block in it's entirety rather than changing a property on it.
You've spelt function wrong ;)

Try:

function MYMODULE_block_info_alter(&$blocks, $theme, $code_blocks) {
  $blocks['system']['main']['weight'] = -9999;
}


EntityFieldQuery INNER JOIN I'd like to run a query using the EntityFieldQuery object. I need value from both the node and node_access table therefore I'd need to use INNER JOIN. From the d.o documentation I can't figure out how this is possible.

Here's what I have --

$query = new EntityFieldQuery();
$result = $query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'node_access')
->propertyCondition('type', 'external_link')
->propertyCondition('status', 1)
->fieldCondition('gid', '3', '=')
->fieldCondition('realm', 'domain_id', '=')
->fieldCondition('grant_view', '1', '>=')
->range(0,1)
->execute();

You can't add extra joins to an EntityFieldQuery directly (it's not supported), but you could add a tag to the query, implement hook_query_TAG_alter(), and add the join manually when the query is converted down to a standard db query.

This isn't tested but will probably get you most of the way there:

$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'node_access')
  // etc
  ->addTag('MYTAG');

// get the query results as normal

And then the query alter function:

function MYDMOULE_query_MYTAG_alter(QueryAlterableInterface $query) {
  $query->join('node_access', 'node_access', 'node_access.nid = node.nid');
}

The other way to do it would be to subclass EntityFieldQuery itself and add the join, but I think the above method is simpler in this case.


Adding conditional statements as Math expression to custom text fields in views I have created views in which i have added custom text and Math expression.
I displayed view in table format
I created one Math expression which is noticed below:

[Field 1] - [Field 2]

I have displayed this expression into another custom field in views.

Now i want to add some condition statements.
That is

If [expression] >= 0
 'display something'
else
 'other texts'

Is it possible to add conditional statement in Math expression views?

Well you can override any of the output you have from views with a template override.
Goto your Views > Display
on the right hand side in the box labelled 'other'

click on information next to 'theme'

This will give you a list of template pages you can use to over write the section you need.  A little trial and error maybe needed at first until you get used to what your being presented.

on the left hand side of the page suggested you have a link to the code you need to use.  Copy that code and paste it into the file name your targetting ( ie views-view-field--default.tpl.php ) and add in the theme/templates  folder your using.
from here on you can manipulate the code how you want using php

Hope this makes sense, as I wrote it real quick :)


View Template Override that is full page I need to create a template for a view i've created (which I know how to do) but I don't want the page to be wrapped in the drupal html.php code. I want the resulting page to be only what is in the template file I create.

How do I do this? I looked online for examples but coudn't find anything.

Thanks
C

EDIT:

I found this which does what I need for content types lab

function yourthemename_preprocess_html(&$vars) {
  if ($node = menu_get_object()) {
    if($node->type == "lab") {
      $vars['theme_hook_suggestions'][] = 'html__lab';
    }
  }
}

Then created a file called: html--lab.tpl.php

Can this method be used for me view?
does it have to be if($node->type == "lab")?
can I use something like if($view == "viewname")

Thanks

If you want views template not to be wrapped in html.tpl.php, page.tpl.php and any other template whatsoever, I would susggest to do the following:

function YOUR_MODULE_menu(){
    $items = array();
    $items['path/you/want/your/view/to/be/available/at'] = array(
        'type' => MENU_NORMAL_ITEM,
        'title' => 'View without wrapping templates',
        'page callback' => 'your_function_name',
        'access callback' => TRUE,
    );
    return $items;
}

function your_function_name() {
    print views_embed_view('your_view_name', 'your_display_name');
    exit;
}


The email address is already taken I'm trying to edit a user, but I keep getting the following error:

  The email address [their email] is already taken.

I'm not editing their email. In fact, I could open the edit page, just hit Save without changing anything, and I would still get the error.

Why am I getting this error message?

It appears that email is already in the database on another row. This can have many causes; importing users twice, creating accounts in a custom module without proper checking if the email address is available, etc.

If you do not use the account edit forms, but modify users programmatically, it can appear that the same email is added to the database twice (the form validation does not run in those cases). Then later when you try to edit one such user, it cannot save because that account should not have existed in the first place. This measure is there so users cannot sign up with the same email twice, but since the user creation and edit form are in fact the same form (and as such have the same validation), it can happen during the save of a user as well.

Double check that you have no modules that can create accounts from email addresses (eg. Drupal commerce) and check your database users table to identify the duplicate account.


cache_form error: myisam_sort_buffer_size is too small After running mysqlcheck -udbuser -p --auto-repair --optimize --databases mydrupaldb, I got the following error.

  cache_form error: myisam_sort_buffer_size is too small

Someone has suggested that it should be solved by increasing sort_buffer_size parameter, for example with myisamchk -r -q cache_form.MYI --sort_buffer_size=2G. Executing this command causes the following error.

  myisamchk: error: File 'cache_form.MYI' doesn't exist

How can I fix it?

mysqlcheck is a client utility that actually logs into mysql

myisamchk is a client utility that does not require logging in. It does require

access the raw file(s) needed, provided the datafile is not in use by the mysqld process
your current directory is wherever the datafile is located

For the table mydrupaldb.cache_form, here is what you must do:

Step 01) Run this query : SHOW VARIABLES LIKE 'datadir'; In most instances, this will be /var/lib/mysql. For the sake of this example, let's assume it is /var/lib/mysql.
Step 02) cd /var/lib/mysql/mydrupaldb
Step 03) service mysql stop
Step 04) myisamchk -r -q cache_form.MYI --sort_buffer_size=2G
Step 05) service mysql start

Give it a Try !!!

CAVEAT : The error message probably means you were not standing in the proper directory where cache_form.MYI is located at the time you first ran myisamchk.


How do I get paragraph fields text data without the  tags? I am trying to pass my paragraph field data from Drupal to a component that I have created in Twig. My component echos out data like so:

{{ my_var }}

In my template file, I am passing data to the component like so:

{% include '@components/my-component-name.twig' with {
   my_var: content.field_my_var_name.0
   ...
} %}

However, when this loads in my browser, what I am getting is:

The contents of my var.

How can I load the contents of my_var into my
 tag without getting another tag injected?

Does your field contain other
 tags you want to preserve? Or just this one in the beginning and end? If you don't need to preserve other
 tags, you could simply use Twig's |striptags filter.

{{ my_var|striptags('
') }}

Or as @Hudri suggested in the comments under your question you may change the field type to something other than formatted text. Or maybe try changing the text format to plain.


How can I show only first level terms on a dropdown taxonomy exposed filter? I have a 2 level taxonomy tree: Countries and cities. I also have a view of content, all of which are marked by first level terms (countries) of that vocabulary.

My taxonomy tree is like that:

Country 1

City 1
City 2
City 3

Country 2

City 4
City 5

In an exposed filter over the view, I want to show only the first level terms (countries) as options. Is it possible?

This question is very similar to How Can I add a Hierarchical taxonomy Select in views filters and when editing content in Drupal 7

I will say that the easiest method I can see is to add an exposed field by the name of "Content: Has taxonomy terms (with depth)" this way you can select the vocabulary(unfortunately only one) and also select the depth.


Display Ubercart sell price in Apache Solr search results I manage an ubercart store that is indexed by Apache Solr. The search indexes the sell price and it's one of the facets. However, the price is nowhere in search-result.tpl.php. It's also not available in the search results preprocess hook in template.php. Is there somewhere else I can inject it into the search results without performing a separate database query for each search result.

You can index it using solr's dynamic fields (see your schema.xml in the solr conf directory) and a custom module hook, namely hook_apachesolr_update_index().

Then you can, at search time, add the field you have indexed into the fields being fetched. For this you have three hooks or 'hooks' to choose from: hook_apachesolr_prepare_query(), hook_apachesolr_modify_query() and CALLER_finalize_query().

For further information on the hooks, see the README.txt in the apachesolr module directory.

Then in your search-result.tpl.php you'll have available the custom indexed field as $result['fields']['your_field_name'].


Custom wrapper field I have a normal field submit:

$form['submit'] = [
  '#type' => 'submit',
  '#value' => 'Submit,
];

But I wish he had a complex wrapper without using #prefix and #suffix. This wrapper also has to pass variables.
What is the easiest way to do it? Creating a tpl.

What you are looking for are "theme wrappers" ... this allows you to create a theme function (or tpl) to use to wrap a form element (or any element in a render array).

There is a good write-up here: https://guusvandewal.nl/drupal-blog/theme-wrappers-drupal-forms

Its for drupal 7 but not much has changed with theme wrappers in Drupal 8


How can I prevent composer from detaching a module's head? How can I prevent composer from leaving a module's git status as a "detached head" when updating

Whenever I use composer to install or update one of my modules or themes, it downloads and overwrites the module's files into the expected directory but leaves the git status in a 'detached head' state and so subsequent development work is not staged to the expected commit until I reset the head ... which only takes a moment but ... I would prefer not to have to remember to do this each time.

Could it be the way I tag the commit of latest dev work? I git push the commit; git tag it; and git push --tags in the belief that git will not push tags and the commit simultaneously.

As an example:

A theme's complete composer.json on GitHub.

{
  "name": "iainhouston/pellucid_monoset",
  "description": "Drupal 8 Theme for pellucid_build",
  "type": "drupal-theme",
  "license": "GPL-2.0+",
  "keywords": ["pellucid", "php"],
  "homepage": "https://iainhouston.com",
  "minimum-stability": "dev",
  "authors": [
    {
      "name": "Iain Houston",
      "email": "iainhouston@mac.com"
    }
  ],
  "require": { }
}

The theme's entries extracted from the project's composer.json

"repositories": [{
    "type": "composer",
    "url": "https://packages.drupal.org/8"
    },
    ...
    {
    "type": "git",
    "url": "https://github.com/iainhouston/pellucid_monoset.git"
    },
    ...

mradcliffe is correct:

  composer checks out the git commit hash rather than a branch if I recall correctly.

This is fairly easy to deal with though. For example, if your main branch is 8.x-1.x, then you do some work on detached head, you can commit the work on the detached head, which will give you a hash. You then check out the 8.x-1.x branch, and merge the hash. Since the detached head has the 8.x-1.x branch upstream, it can be merged back into that branch after you make your changes.

Example:

$ git status
HEAD detached at aa284c1
$ git add file.php
$ git commit -m "Committed file.php"
[detached HEAD ef37212] Comitted file.php
$ git checkout 8.x-1.x
$ git merge ef37212

If you realize early enough, you can actually just run git add on all your changed filed, then check out  the 8.x-1.x branch. Then you can continue to work there, or make a commit on that branch. Or you can even create a new branch from 8.x-1.x and continue your work in that branch.


Can't print fields in a view template I'm overriding drupal /blog path with a views. Created a new view page display and set path to blog. Created views-view-unformatted--blog-page.tpl and trying to output view fields this way:

<?php
print $fields['title']->content;
print $fields['body']->content;
?>

But all what i get is nothing, tried to output <?php print 'Hello, world!'; ?> == it outputs Hello,world. But i can't print Views fields...

PS in another view display - printing fields this way works perfectly. Blank fields affects only blog page view display

The template you have overwritten looks like this (in Drupal 6):

<?php if (!empty($title)): ?>

<?php print $title; ?>

<?php endif; ?>
<?php foreach ($rows as $id => $row): ?>
  <div class="<?php print $classes[$id]; ?>">
    <?php print $row; ?>

<?php endforeach; ?>

As you can see, it's purely used to print out the rows in the view; you should instead use one of the other templates available, if you want to alter the fields. Take a look at the theming information button in the UI that will give you a complete list with previews.


Create an expiration date field that auto expires We are currently migrating a Drupal 6 site to Drupal 8. We have a view that shows a table of files uploaded through the file depot. One of the columns on the table was an Expiration Date. In Drupal 6 we had a module called Auto Expire to set a date for a node to expire which we used to create a field on the view showing the number of days until the link to the file expired.

We created a Node view with multiple fields as the column headings (Date Created, Expiration Date, Staff Member, File Name). For the expiration field, we used Auto Expire to create an Expiration Date field set to 7 days after the creation date. After the 7 days, the node (file depot page) and it's attachments would get deleted.

How do I recreate this functionality (whether programmatically or otherwise) in Drupal 8, since Auto Expire is not updated for Drupal 8?

I am currently looking into the Scheduler module as there is a version for Drupal 8.

You can use Scheduler to unpublish the node (and then optionally use Scheduler's hooks/events to delete the node). However, to get the date set into the Scheduler unpublish_on field, you could use Rules (reacting on 'after creating' event) or use your own custom mymodule_hook_save() to set the date.

We are also in the process of migrating Scheduler's actions and events for Rules, (see https://www.drupal.org/node/2651348) and I think that Rules would then let you delete the node reacting to being unpublished by Scheduler.


Re-write the output of taxonomy_term_page() without hacking core In Drupal 7, taxonomy.pages.inc contains the taxonomy_term_page(), which places a <div class="term-listing-heading"> around the taxonomy heading output.

How can I re-write the output of taxonomy_term_page() in my theme, so I can remove the DIV without hacking core?

I'm quite surprised that there isn't a tpl.php file available for taxonomy_term_page() as this would making theming much easier.

You can do it with preprocess page something like this:

function themename_preprocess_page(&$vars) {
  if  (arg(0) == 'taxonomy' && arg(1) == 'term' && is_numeric(arg(2))) {
    unset($vars['page']['content']['system_main']['term_heading']['#prefix']);
    unset($vars['page']['content']['system_main']['term_heading']['#suffix']);
  }
}

in your theme's template.php

I believe system_main could be called something else, depending on your site setup.


Enabling JavaScript from CKEditor I would like to enable javascript to be added inside CKEditor. The editor filters all my javascript and I would like to make a transtision from an image to a youtube iframe, here is the code that I am using:

But when I click nothing happens, it filters the "onclick" event and adds a paragraph tag:

I am using CKEditor with the module Wysiwyg.

Thanks in advance.

Hope this will help you, For achieving your goal you need to create a plugin of ckeditor, First of all read more about ckeditor plugin, and create a view to get all the video with the display in a page, you can use the views page url for the ckeditor plugin to insert the media on ckeditor, a good tutorial is here.Click Here

this is one of the module which will help you click here & click here


How to switch table prefix in a module in Drupal 6? I have multiple sites setup on a single MySQL database in Drupal 6. The sites each have their own prefix, such as site1_, site2_, etc. I'm wondering how I can switch the current table prefix inside of a module to check the variables on each site. For example, I want to check the preprocess_css variable on every site by looping through each sites settings file and running variable_get('preprocess_css') and get the variable for each site. I can get the table prefix and get the variable using db_query on the variables table, but I know there has to be a way to set the current table prefix inside a module so I can just run variable_get inside a loop with each table prefix. Does anyone know how this can be done?

The prefix is stored as one of the variables in the settings.php file, all of which are made global early on in the page build process.

That in mind, you can do something as easy as:

$GLOBALS['db_prefix'] = 'db1_';
print variable_get('site_name', 'default'); // Site name from first set of tables

$GLOBALS['db_prefix'] = 'db2_';
print variable_get('site_name', 'default'); // Site name from second set of tables

Bear in mind that this change won't persist across page loads so you'll need to do your processing in a single load, or implement some sort of system to track which prefix you should currently be using.


Apply template to a specific page I have a requirement to apply template to a specific page and not to the pages following the same url pattern.
For example I have a page with the path /asia. I also have pages with the paths /asia/india, /asia/china etc. I would like to create a template which applies only for /asia and not for other paths. I created the template file page--asia.tpl.php but it is getting applied for /asia/india and /asia/china as well. Is there a way to specifically map the template to this specific path?

To overwrite Drupal defalut suggestion, You can make your own suggestion for template.

In your case you have defined a menu called asia for that specific template is required, to implement this use this code

 **
 * Implementation of hook_preprocess_HOOK().
 */
function mymodule_preprocess_page(&$variables){
  if(isset($variables['asia']) && arg(1) == '')
    $variables['theme_hook_suggestions'][] = 'page__asiapage';
}

create a tpl file in theme called page--asiapage.tpl.php, it will work.


Restrict access to ECK full page, but allow embedded Following the Lullabot article on how to embed anything in a wysiwyg with Entity Embed and friends  we're using this to embed a custom entity type created with ECK (Entity Construction Kit).

The permissions for ECK require anonymous users have the "View My Entity" permission in order for it to appear in the embedded scenario.  However  ECK also provides a full page URL at /my_entity/{id}, but we want to restrict access and not index the full page, because the content will always be embedded inside other Articles.

I've already implemented the Metatag module for this entity to add the robots noindex meta tag. However the ideal case would be to restrict the ECK full page URL /my_entity/{id} to administrators only. How can this be done, when these entity types are dynamic and don't have a canonical route.

It turns out that though the entities created by ECK are dynamic, they do have route definitions, so we can use this to restrict access, in a hook_preprocess_page placed in a custom module.  Also worth noting that the administrative list display at /admin/content/my_eck_entity is visible to anonymous users when you set the view my_eck_entity entities permission to anonymous users, so we must also look out for this route as well.

use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

/**
 * Prepares variables for page.html.twig.
 */
function mymodule_preprocess_page(&$variables) {
  $route_name = \Drupal::routeMatch()->getRouteName();

  // Restrict access to ECK canonical full page display and the entity
  // administration list screen to content authors. Restricting full page
  // display helps to avoid mistakenly indexing the content in search engines
  // because these entities are only ever going to be seen by anonymous users
  // when embedded into other pages via WYSIWYG embed or rendered entities
  // from entity reference fields on other node types.
  $user = \Drupal::currentUser();
  $restricted_eck_entities = [
    'my_eck_entity', // Replace this with real entity type machine name!
  ];
  foreach ($restricted_eck_entities as $eck_entity) {
    if (
      (
        $route_name === "entity.$eck_entity.canonical"
        || $route_name === "eck.entity.$eck_entity.list"
      )
      && !(
        $user->hasPermission("create $eck_entity entities")
        || $user->hasPermission("edit $eck_entity entities")
      )
    ) {
      throw new AccessDeniedHttpException();
    }
  }
}


Mapping or migrating path alias using using Migrate Source CSV I am importing content from SharePoint into Drupal 8 using Migrate Source
CSV and a large CSV file. I successfully mapped id,title,body,date. But I
cannot map the path alias? In Drupal 7 the Feeds module mapped this easily.
Does anyone know how to do this in Drupal 8?

This is a snippet from my yml file:

process:
  id: id
  nid: nid
  title: title
  alias: path
destination:
  plugin: entity:node

my csv file

"id","nid","title","body","path","date"
"1","1","title1","bodytext","content/12/mypath","2014-08-12"

@Jigar's answer is close but not quite. Here is what I eventually figured out. It should be path/alias and not just path. Also, if you have pathauto module installed it will create the path based on the patterns. So, in order for our path to be imported from csv, the path auto needs to be disabled first. You set path/pathauto's default value to 0 to do that.

source:
...
 constants:
  slash: '/'
....
process:
...
 path/pathauto:
   plugin: default_value
   default_value: 0 # Disable pathauto
 path/alias:
   plugin: concat
   source:
     - constants/slash
     - url


Why are media files used in zero places not deleted? Unused media files (.jpeg .mp4 etc.) are remaining permanently even though unused.

This is shown in the /admin/content/files page in our Drupal 8.6.3 system.

It could be that, at migration from Drupal 7, we weren't careful enough.

Is there any way I can force the deletion of these files using Drupal functionality?

I haven't seen any fully ready a Drupal 8 module to remedy this seemingly common situation.

I've come across this before with webform submission files and the site getting confused about the path.

If you actually try and view 1 of the files in the list does it exist? As you may find it doesn't exist but drupal has kept a record of the file in the database. When drupal tries to do is file tidy up on cron run it's erroring because the file its trying to delete doesn't exist (But its not then smart enough to delete the row out of the database)

The safest solution would be to manually recreate these files in the position /admin/content/files thinks it should exist and then rerun the cron and it should delete your test file and the row in the database


What's the difference between !, %, and @ in replacement tokens? I'm using the Message module on Drupal 7.  For Replacement tokens, the help text says:

  A comma-separated list of replacement tokens, e.g. %title or !url, of
  which the message text makes use of. Each replacement token has to
  start with one of the special characters "@", "%" or "!". This
  character controls the sanitization method used, analogously to the
  t() function.

What's the difference between %, !, and @?  Are there standards about when I should use each symbol?

From the format_string() docs:

@variable: Escaped to HTML using check_plain(). Use this as the default choice for anything displayed on a page on the site.
%variable: Escaped to HTML and formatted using drupal_placeholder(), which makes it display as emphasized text.
!variable: Inserted as is, with no sanitization or formatting. Only use this for text that has already been prepared for HTML display (for example, user-supplied text that has already been run through check_plain() previously, or is expected to contain some limited HTML tags and has already been run through filter_xss() previously).


Possible to run views_embed_view() for a specific role Without having to user_load(SOME_UID_THAT_HAS_MY_INTENED_ROLES); and swap the current $user object and then replace it.

Is it possible to say,

views_embed_view('view_of_articles');

But tell it to respect the permissions of a certain array of roles like,

views_embed_view('view_of_articles', array(SOME_RID));

I know the above wont work since the function isn't defined in such a way, but could this be possible with theme() functions, or something else I'm missing?

In view check the option of "Access" and select roles. Now even if you call the view with views_embed_view() It wont display if the user is not part of the role that have access.


EntityQuery on nodes related by ERR and paragraphs I have content type Publication which relates to content type Project using paragraphs:

Publication [field_mention] -> Mention (paragraphs) [field_project] -> Project

Now I want to show all referenced Projects on Article templates. Views doesn't show all relations because of the complexity of this relationship.

I try to do it using EntityQuery with the following code used in a Custom Block Module in the following way:

$nids = \Drupal::entityQuery('node')
    ->condition('status', 1)
    ->condition('type', 'publication')
    ->condition('field_mention.entity.field_project.target_id', \Drupal::routeMatch()->getRawParameter('node'))
    ->execute();

The result is empty (after a long loading so) and logs don't show any error.

Is field_mention.entity.field_project.target_id the right way to do it or do I miss something?

Newer versions of Drupal (tested with v8.6.2) can also resolve Paragraphs (Entity Reference Revisions) if you explicitly name the target entity type using dot notation:

$nids = \Drupal::entityQuery('node')
    ->condition('status', 1)
    ->condition('type', 'publication')
    ->condition('field_mention.entity:paragraph.field_project.target_id', \Drupal::routeMatch()->getRawParameter('node'))
    ->execute();

Note the .entity:paragraph. instead of .entity. in the referenced field condition


Connect Views and a second database Lets say I have two (mysql) databases drupal and book_data.

The book_data database has a table called books with three columns: isbn, title, pages.

My user entity has a field called field_isbn where every user may enter multiple isbn numbers of books he read.

The next step would be to tell views about the books data structure some how.

In the best case views would allow me to add a relationship between the field_isbn and book_data.books.isbn field so I am able to:

sum up the pages to see how many book pages a user has read
sort/filter for books.title
expose theses filters

Is this possible at all?

I havent done this but I have seen code to make Views in D7 work with remote database tables. If you can get Views to see those tables and fields -- a bit more work should be able to allow you to filter/search through this stuff from Views:

Fields with Multiple Entries in Views w/ External Data Source

It looks like you just have to give drupal a database key for your remote database connection defined in settings.php per field description. The rest looks like a typical implementation of hook_views_data().


How do I create content importing data from an Excel file? I am using Drupal 6 and created a custom content type. I have an excel sheet that has more than 2 lacs entry. It is not easy to enter manually.

Is there is any way to this, either programmatically or from the UI?

You need the Feeds module.

Export your excel sheet as CSV with column headings quoting every cell.
Download and install the Feeds module (and optionally Feeds Tamper).
Create a new Feeds importer to consume the CSV.
http://example.com/admin/structure/feeds/create
Set Fetcher (change) to file upload, Parser (change) to CSV parser and Processor to Node processor.
Map (exactly) your column headings in Node processor mapping.

I've used this with great success in Drupal 7 and once in Drupal 6. PS: Upgrade to D7.


Print node tags in html header I am trying to print the articles tags in the meta area of the html. I am able to print them, however, they contain all the markup, where as I just need the plain text, comma separated list, much like it prints when using the meta module.
Here is what I am using.

function mytheme_preprocess_html(&$variables) {
if ($node = menu_get_object()) {
  if ($node && isset($node->nid)) {
  $node = node_load($node->nid);
   node_build_content($node);
   $variables['field_tags'] = render($node->content['field_tags']);
   }
 }
}

The reason your getting html in your output is because your using render(), which is just a wrapper for drupal_render. Per that function's documentation, it "Renders HTML given a structured array tree."

If you want just something like:
Cats, Dogs, Otters

it would probably be better to just pull out those values, ether by looping through the field_tags array and pulling out the value into an array and then imploding your array, or simply looping through and creating a string. So instead of render(), use something like:

$tags = array();
foreach($node->field_tags['und'] as $tag){
  $tags[] = $tag['value'];
}
$variables['field_tags'] = implode(',', $tags);