Newsfeeds

Spinning Code: Drupal 8 Batch Services

Planet Drupal - 20 January 2019 - 1:04pm

For this month’s South Carolina Drupal User Group I gave a talk about creating Batch Services in Drupal 8. As a quick side note we are trying to include video conference access to all our meetings so please feel free to join us even if you cannot come in person.

Since Drupal 8 was first released I have been frustrated by the fact that Drupal 8 batch jobs were basically untouched from previous versions. There is nothing strictly wrong with that approach, but it has never felt right to me particularly when doing things in a batch job that I might also want to do in another context – that really should be a service and I should write those core jobs first. After several frustrating experiences trying to find a solution I like, I finally created a module that provides an abstract class that can be used to create a service that handles this problem just more elegantly. The project also includes an example module to provide a sample service.

Some of the text in the slides got cut off by the Zoom video window, so I uploaded them to SlideShare as well:


Quick Batch Overview

If you are new to Drupal batches there are lots of articles around that go into details of traditional implementations, so this will be a super quick overview.

To define a batch you generate an array in a particular format – typically as part of a form submit process – and pass that array to batch_set(). The array defines some basic messages, a list of operations, a function to call when the batch is finished, and optionally a few other details. The minimal array would be something like:

<?php // Setup final batch array. $batch = [ 'title' => 'Page title', 'init_message' => 'Openning message', 'operations' => [], 'finished' => '\some\class\namespace\and\name::finishedBatch', ];

The interesting part should be in that operations array, which is a list of tasks to be run, but getting all your functions setup and the batch array generated can often be its own project.

Each operation is a function that implements callback_batch_operation(), and the data to feed that function. The callbacks are just functions that have a final parameter that is an array reference typically called $context. The function can either perform all the needed work on the provided parameters, or perform part of that work and update the $context['sandbox']['finished'] value to be a number between 0 and 1. Once finished reaches 1 (or isn’t set at the end of the function) batch declares that task complete and moves on to the next one in the queue. Once all tasks are complete it calls the function provided as the finished value of the array that defined the batch.

The finish function implements callback_batch_finish() which means it accepts three parameters: $success, $results, and $operations: $success is true when all tasks completed without error; $results is an array of data you can feed into the $context array during processing; $operations is your operations list again.

Those functions are all expected to be static methods on classes or, more commonly, a function defined in a procedural code block imported from a separate file (which can be provided in the batch array).

My replacement batch service

It’s those blocks of procedural code and classes of nothing but static methods that bug me so much. Admittedly the batch system is convenient and works well enough to handle major tasks for lots of modules. But in Drupal 8 we have a whole suite of services and plugins that are designed to be run in specific contexts that batch does not provide by default. While we can access the Drupal service container and get the objects we need the batch code always feels clunky and out of place within a well structured module or project. What’s more I have often created batches that benefit from having the key tasks be functions of a service not just specific to the batch process.

So after several attempts to force batches and services to play nice together I finally created this module to force a marriage. Even though there are places which required a bit of compromise, but I think I have most of that contained in the abstract class so I don’t have to worry about it on a regular basis. That makes my final code with complex logic and processing far cleaner and easier to maintain.

The Batch Service Interface module provides an interface an an abstract class that implements parts of it: abstract class AbstractBatchService implements BatchServiceInterface. The developer extending that class only needs to define a service that handles generating a list of operations that call local methods of the service and the finish batch function (also as a local method). Nearly everything else is handled by the parent class.

The implementation I provided in the example submodule ends up four simple methods. Even in more complex jobs all the real work could be contained in a method that is isolated from the oddities of batch processing.

<?php namespace Drupal\batch_example; use Drupal\node\Entity\Node; use Drupal\batch_service_interface\AbstractBatchService; /** * Class ExampleBatchService logs the name of nodes with id provided on form. */ class ExampleBatchService extends AbstractBatchService { /** * Must be set in child classes to be the service name so the service can * bootstrap itself. * * @var string */ protected static $serviceName = 'batch_example.example_batch'; /** * Data from the form as needed. */ public function generateBatchJob($data) { $ops = []; for ($i = 0; $i < $data['message_count']; $i++ ) { $ops[] = [ 'logMessage' => ['MessageIndex' => $i + 1], ]; } return $this->prepBatchArray($this->t('Logging Messages'), $this->t('Starting Batch Processing'), $ops); } public function logMessage($data, &amp;$context) { $this->logger->info($this->getRandomMessage()); if (!isset($context['results']['message_count'])) { $context['results']['message_count'] = 0; } $context['results']['message_count']++; } public function doFinishBatch($success, $results, $operations) { drupal_set_message($this->t('Logged %count quotes', ['%count' => $results['message_count']])); } public function getRandomMessage() { $messages = [ // list of messages to select from ]; return $messages[array_rand($messages)]; } }

There is the oddity that you have to tell the service its own name so it can bootstrap itself. If there is a way around that I’d love to know it. But really one have one line of code that’s a bit strange, everything else is now fairly clear call and response.

One of the nice upsides to this solution is you could write tests for the service that look and feel just like any other services tests. The methods could all be called once, and you are not trying to run tests against a procedural code block or a class that is nothing but static methods.

I would love to hear ideas about ways I could make this solution stronger. So please drop me a comment or send me a patch.

Related core efforts

There is an effort to try to do similar things in core, but they look like they have some distance left to travel. Obviously once that work is complete it is likely to be better than what I have created, but in the meantime my service allows for a new level of abstraction without waiting for core’s updates to be complete.

Categories: Drupal

Kaltura Video Block

New Drupal Modules - 20 January 2019 - 9:05am

This module provides a code to embed kaltura video as a block into drupal site.

Categories: Drupal

Video Game Deep Cuts: NASA Slime-d Me With A BadCupid - by Simon Carless

Gamasutra.com Blogs - 20 January 2019 - 7:27am
This week's highlights include a look at NASA's new commissions in the video game space, the crunch-free development of Slime Rancher, and a very offkilter procedurally generated dating game, among other things.
Categories: Game Theory & Design

Business.ru online checks

New Drupal Modules - 20 January 2019 - 5:27am

Решение для ФЗ-54.
Интеграция с онлайн чеками business.ru (подробное описание позже)

Categories: Drupal

Collect To Entities

New Drupal Modules - 20 January 2019 - 1:40am

This module processes the e-mails collected by Inmail Collect. An incoming part of a customer service can be created with this module. It is important to note that this module only generates the content, does not perform any permission management with the generated content. Recommended and related modules:

Nodeaccess
https://www.drupal.org/project/nodeaccess

Categories: Drupal

OSTraining: How to Create a Voting System in Drupal 8

Planet Drupal - 19 January 2019 - 10:40pm

One of OSTraining’s customers asked how to implement content voting on their site. 

In Drupal 7, the popular choice was the Fivestar module, but that's still not ready for Drupal 8.

In this tutorial, I'll show you how to use the Votingapi Widgets module in Drupal 8. This module makes use of a “Rating” field, which you can customize and insert into your content.

Categories: Drupal

OSTraining: How to Create CSS and Javascript Animations in Drupal 8

Planet Drupal - 19 January 2019 - 10:14pm

There are multiple JavaScript and CSS libraries on the internet. They allow you to animate parts of your site and make them look more attractive.

The Animations module makes it easy to include animations on your Drupal site. 

There's a full list of the animations on the module page, but they include such wonderfully named animations as swing, tada, wobble, jello, bounceIn, bounceOut, fadeIn, rollOut, zoomIn, slideInRight and more.

In this tutorial, I'll show how to install and use the required libraries and the Animations module..

Categories: Drupal

OSTraining: How to Create a Contact Form in Drupal 8

Planet Drupal - 19 January 2019 - 10:06pm

One of OSTraining’s members asked how to create a following web form with the Webform module:

  • The site has four regions to be contacted: NE, SE, NW, and SW.
  • Each region will have their own contact person/team.
  • The user must be able to select one or more of the regions to contact at the same time, using checkboxes.
  • All the submittions must be BCC-ed to the main administrator.
  • If needed, the site owner should be able to add one or more email recipients for each region.

In this tutorial, you will learn how to meet these user requirements using the Webform module.

Categories: Drupal

OSTraining: Videos to Get you Started with Drupal Development

Planet Drupal - 19 January 2019 - 9:54pm
How do I get started with Drupal development?

That's a common question we get from people who join OSTraining for the first time. They want to know about the skills they will need, and what kind of classes they should take.

In this guide, I'll give you an overview to help you get started with Drupal development.

Categories: Drupal

Migrate Staging Table

New Drupal Modules - 19 January 2019 - 6:30am
Categories: Drupal

Commerce Paypal Donate

New Drupal Modules - 18 January 2019 - 8:11pm
Categories: Drupal

Ben's SEO Blog: 6 Tips to Rock Drupal 8 SEO

Planet Drupal - 18 January 2019 - 12:55pm

This article was originally written on 2017-04-12 but has been updated with current information and SEO best practices.

Drupal is phenomenal for SEO. When you use Drupal 8 for your content management system, you have a powerful tool to rock search engine optimization. I’ve worked in Drupal for 12 years and I’ve experienced firsthand how quickly search engines respond to a well-optimized Drupal website. I’ve seen customers triple their traffic in weeks after upgrading from another platform. I’ve seen competitive advantages from site-wide optimizations like RDF or AMP that put my clients on the cutting edge of SEO because they use Drupal. The benefits are a faster website, higher rankings and more traffic.

One of the main reasons Drupal is the content management system of... Read the full article: 6 Tips to Rock Drupal 8 SEO

Categories: Drupal

Microsoft says its game streaming service has an advantage thanks to Xbox

Social/Online Games - Gamasutra - 18 January 2019 - 12:44pm

Microsoft says the experience it's gained through its Xbox dealings gives it a potential leg up on the competition.  ...

Categories: Game Theory & Design

Simple entity translations

New Drupal Modules - 18 January 2019 - 12:40pm
Why do you need this module?

This module aims to make content translation easier. It adds two additional forms for content translation.
One form is to translate multiple entities at once. Second is to translate one entity to several languages at once.
Note: these forms do NOT display untranslatable fields!
You can select what content type, vocabulary (content entity bundle) should have such forms.

Categories: Drupal

Remove HTTP headers

New Drupal Modules - 18 January 2019 - 8:10am
Overview

The Remove HTTP headers module removes configured HTTP headers from the response. Also removes <meta name="Generator" content="Drupal 8 (https://www.drupal.org)"> from the <head> tag if the X-Generator HTTP header is configured to be removed. By default the X-Generator and X-Drupal-Dynamic-Cache HTTP headers are configured to be removed.

Categories: Drupal

The Rise of The Influencer  -  And Why Epic&#039;s New Store Approach Is Huge - by Meredith Hall

Gamasutra.com Blogs - 18 January 2019 - 7:20am
Ten years ago in 2009, the word influencer didn’t bear much weight. Now, it's part of the core approach for the new Epic Games Store - but why?
Categories: Game Theory & Design

Acquia Developer Center Blog: Building Usable Conversations: How to Approach Conversational Interfaces

Planet Drupal - 18 January 2019 - 6:49am

To kick off 2019 properly, the Experience Express is taking a break from Drupal and web development to consider an oft-forgotten component of new digital experiences in the conversational space. Though many organizations, some of Acquia's customers included, have leapt headlong into building conversational interfaces, sometimes it can be difficult in such a newfangled paradigm to consider all possible angles where things can go awry.

Tags: acquia drupal planet
Categories: Drupal

WeKnow: Drupal South 2019 / Round Two

Planet Drupal - 18 January 2019 - 4:16am
Drupal South 2019 / Round Two Australian Drupal community and market are growing stronger. Participated in Drupal South Event for a second time, where I learned more about GovCMS and presented about Gatsby to create a React Application to accelerate integrations. enzo Fri, 01/18/2019 - 12:16
Categories: Drupal

AmoebaCRM

New Drupal Modules - 18 January 2019 - 4:01am
Categories: Drupal

Pages

Subscribe to As If Productions aggregator