Third & GroveThird & Grove
Feb 26, 2016 - James Watts

Installing Content Automatically in Drupal 8

Frequently when building Drupal applications there is a need for content to be created in order to properly theme and test new functionality. Both backend and frontend development work can be aided greatly by having a consistent and reproducible set of realistic content in the system. The ideal approach would use the actual site content as it will be presented in production, but frequently that data isn’t yet available or complete when the site is under development.

Drupal 8 has powerful install and update functionality built into it’s module system, which can be useful in a variety of ways to load test (or production) site content as part of the site install. These methods would typically be placed inside module_install() hooks (in the .install file), but could also be used as part of hook_update_N hooks if you’re working with a module that has already been published and installed.

Content Nodes

Most Drupal 8 sites will be largely based around displaying content nodes, so these are the first type of object we’ll create in our installer:

use Drupal\node\Entity\Node;
 
function my_module_install() {
  $node = Node::create([
    'type' => 'page',
    'uid' => 1,
    'revision' => 0,
    'status' => TRUE,
    'promote' => 0,
    'created' => time(),
    'langcode' => 'en',
    'title' => 'My Page Title',
  ]);
 
  $node->set('body', [
    'value' => '<h1>Welcome to My Page!</h1>',
    'format' => 'basic_html'
  ]);
 
  $node->save();
 
  $source = '/node/' . $node->get('nid')->value;
  \Drupal::service('path.alias_storage')->save($source, '/my-page', 'en');
}

 

In this example we create a Basic page content Node object and add some content to it's title and body fields. After saving the node, we then add a friendly URL alias for it to replace the default ugly URL. After adding this to your module and installing it, you should now be able to navigate to http://your-site-url.com/my-page and see the result.

Sample Text

When creating sample nodes, it's often necessary to have a realistic amount of text content to ensure the final page design and theme flow properly. Most developers turn to the old standby of Lorem Ipsum text, so Drupal has included a utility allowing you to generate such text programatically without cluttering up your code with long string blocks:

use Drupal\Component\Utility\Random;
 
function my_module_install() {
  $random = new Drupal\Component\Utility\Random();
 
  ...
 
  $node->set('body', $random->paragraphs(6));
}

 

Here we construct a new instance of the Drupal Random utility class, then we can use it when creating content nodes to generate the body for us. This example generates six paragraphs of random Lorem Ipsum, but the Random class has a few other tricks as well, including words, sentences and even images.

Sample Images

Speaking of images, while the Random utiltity can produce randomized placeholder images, most designs will be easier to test with images that are close in style, size and aspect ratio to the final intended content. Luckily, we can easily load some sample images for our content nodes and link them to image type fields:

$destination = 'public://my_module-images-2016';
file_prepare_directory($destination, FILE_CREATE_DIRECTORY);
 
$img_source = sprintf('%s/private/assets/testimg.jpg', \Drupal::root());
$img = null;
 
if (is_readable($img_source)) {
  $data = file_get_contents($img_source);
 
  $img = file_save_data(
    $data,
    $destination . '/testimg.jpg'
    FILE_EXISTS_REPLACE
  );
}
 
...
 
if ($img) {
  $node->get('field_main_image')->appendItem($img);
}

 

This example shows loading a test content image from the private directory in the Drupal root folder (although it can be loaded from anywhere), saving it into the Drupal public files (in the my_module-images-2016 directory), and associating it with a test content node in the field_main_image custom field. You can use the same image to populate multiple nodes, or load individual images for each.

Navigation Menu Items

The last common type of test content we'll look at is navigation menu items. These are created much like regular content nodes, just with a different object type:

use Drupal\menu_link_content\Entity\MenuLinkContent;
 
function my_module_install() {
  $link = MenuLinkContent::create([
    'title'      => 'My Page',
    'link'       => ['uri' => 'internal:/my-page'],
    'menu_name'  => 'main',
    'weight'     => 10,
  ]);
  $link->save();
}

 

Here we create a new navigation item in the main menu, pointing at the URL for our sample page (though this could also be a full external url). If you need to create a deeper nested heirarchy, you can also set the parent of a menu item with another item:

  $link = MenuLinkContent::create([
    'parent' => $link_parent->getPluginId(),
    ...
  ]);

 

Conclusion

Creating test content using the Drupal 8 installers is easy, and will save you and QA tons of time and stress as you build and test your new site.