Dries Buytaert: Working together to promote Drupal

Planet Drupal - 27. Juni 2018 - 0:28

The Drupal community has done an amazing job organizing thousands of developers around the world. We've built collaboration tools and engineering processes to streamline how our community of developers work together to collectively build Drupal.

This collaboration has led to amazing results. Today, more than 1 in 40 of the top one million websites use Drupal. It's inspiring to see how many organizations depend on Drupal to deliver their missions. What is equally incredible is that historically, we haven't collaborated around the marketing of Drupal. Different organizations have marketed Drupal in their own way.

In my DrupalCon Nashville keynote, I shared that it's time to make a serious and focused effort to amplify Drupal success stories in the marketplace. Imagine what could happen if we enabled hundreds of marketers to collaborate on the promotion of Drupal, much like we have enabled thousands of developers to collaborate on the development of Drupal.

Accelerating Drupal adoption with business decision makers

To focus Drupal's marketing efforts, we launched the Promote Drupal Initiative. The goal of the Promote Drupal Initiative is to do what we do best: to work together to collectively grow Drupal. In this case, we want to collaborate to raise awareness with business and non-technical decision makers. We need to hone Drupal's strategic messaging, amplify success stories and public relation resources in the marketplace, provide agencies and community groups with sales and marketing tools, and improve the Drupal.org evaluator experience.

To make Promote Drupal sustainable, Rebecca Pilcher, Director of MarComm at the Drupal Association, will be leading the initiative. Rebecca will oversee volunteers with marketing and business skills that can help move these efforts forward.

Promote Drupal Fund: 75% to goal

At DrupalCon Nashville, we set a goal of fundraising $100,000 to support the Promote Drupal Initiative. These funds will help to secure staffing to backfill Rebecca's previous work (someone has to market DrupalCon!), produce critical marketing resources, and sponsor marketing sprints. The faster we reach this goal, the faster we can get to work.

I'm excited to announce that we have already reached 75% of our goal, thanks to many generous organizations and individuals around the world. I wanted to extend a big thank you to the following companies for contributing $1,000 or more to the Promote Drupal Initiative:

If you can, please help us reach our total goal of $100,000! By raising a final $25,000, we can build a program that will introduce Drupal to an emerging audience of business decision makers. Together, we can make a big impact on Drupal.

Joachim's blog: Making builder code look like output code

Planet Drupal - 26. Juni 2018 - 23:30

One of the big challenges with updating Drupal Code Builder for Drupal 8 has been the sheer variety of code to be output. On earlier versions of Drupal, it was just about hooks, and all that needed to be done was to take the API documentation code and replace 'hook_' with the module name. There were info files too, and Drupal 7 added the placing of hooks into different .inc files, but compared to this, Drupal 8 has things like plugin annotations, fluent method calls for content entity baseFieldDefinitions(), FormAPI arrays, not to mention PHP class methods, and more.

But one of the things I enjoy about working on DCB is that I am free to experiment with different ideas, much more so than with work on core or even contrib. It is its own system, without any need to work with what a framework supplies, and it has no need to be extensible. So I can try a new way of doing things as often as I want, and clean up when I've had time to figure out which way works best.

For example, up until recently, the code for a field definition in baseFieldDefinitions() was getting generated in three different ways.

First, the old-fashioned way of doing it line by line, then concatenating the array with a "\n" to make the final code. This is the way most of the old code in DCB was done, but with things that need handling of terminal commas or semicolons, and nesting indents and so on, it was starting to get really clunky.

So then I tried writing something loosely inspired by Drupal's RenderAPI. Because that's a nice big hammer that seems to fit a lot of nails: make a big array of data, chuck your stuff into it, then hand it over to something that makes the output. Except, not so good. Writing the code to make the right sort of array was fiddly. The array of data needed to combine actual data and metadata (such as the class of an annotation), which added levels to the nesting.

Then I hit on an idea: baseFieldDefinitions() fields are a fluent interface, like this:

$fields['changed'] = BaseFieldDefinition::create('changed') ->setLabel(t('Changed')) ->setDescription(t('The time that the node was last edited.')) ->setRevisionable(TRUE) ->setTranslatable(TRUE);

What if the code that builds this could be the same, to the point where you could just copy-paste code from, say, the node entity class, and make a few tweaks? Creating the code in DCB would be much simpler, and having the DCB code look like the output code would make debugging easier too.

Using a class with the magic __call() method lets us have just that: a renderer object that treats a method call as some information about code to render. Here's what the builder code for the base field definition code looks like now:

$changed_field_calls = new FluentMethodCall; $changed_field_calls ->setLabel(FluentMethodCall::t('Changed')) ->setDescription(FluentMethodCall::t('The time that the entity was last edited.')); if ($use_revisionable) { $changed_field_calls->setRevisionable(TRUE); } if ($use_translatable) { $changed_field_calls->setTranslatable(TRUE); } $method_body = array_merge($method_body, $changed_field_calls->getCodeLines());

It's not yet perfect, as the first line isn't done by this, and the handling of the t() calls could do with some polish; probably by creating a separate class called something like FunctionCall, such that FunctionCall::somefunction() returns the code for a call to somefunction().

But the efficiency and elegance of this approach has led me to devise a new principle for DCB: builder code should look as much as possible like that code that it outputs.

So applying this approach to outputting annotations, the code now looks like this:

$annotation = ClassAnnotation::ContentEntityType([ 'id' => 'cat', 'label' => ClassAnnotation::Translation("Cat"), 'label_count' => ClassAnnotation::PluralTranslation([ 'singular' => "@count content item", 'plural' => "@count content items", ]), ]); $annotation_lines = $annotation->render();

Magic methods used there as well, this time for static calls. The similarity to the output code isn't as good, as annotations aren't PHP code, but it's still close enough that you can copy the code you want to output, make a few simple changes, and you have the builder code.

This work has embodied another principle that I've come to follow: complexity and ugliness should be pushed down, hidden, and encapsulated. Here, the ClassAnnotation and FluentMethodCall have to do fiddly stuff like quoting string values, recurse into nested arrays. They have to handle special cases, like the last line of a fluent call has a semicolon and the last line of an annotation has no comma. All of that is hidden from the code that uses them. That can get on with doing the interesting bits.

Skriptsprache: Perl 5.28 ist entscheidend sicherer

heise online Newsticker - 26. Juni 2018 - 18:30
In diesem Jahr bringt erst der Juni alles Neue in die Perlwelt, denn drei ernste Sicherheitslücken wollten zuvor zuverlässig geschlossen sein.

Apple-Tastaturaustausch: Welche Geräte betroffen sind und wie es funktioniert

heise online Newsticker - 26. Juni 2018 - 18:30
Apple hat erstmals Probleme mit den Butterfly-Keyboards aktueller Notebooks eingeräumt – und will sie kostenlos beheben. Noch sind Fragen offen.

YouTube-Premium für Apple-Nutzer 33 Prozent teurer

heise online Newsticker - 26. Juni 2018 - 18:00
Wer den neuen Google-Dienst auf iPhone und iPad abonniert, zahlt deutlich drauf. Der Konzern will offenbar Apples Provision kompensieren.

MIT-Forscher wollen konkurrierende Blockchains miteinander kommunizieren lassen

heise online Newsticker - 26. Juni 2018 - 17:30
Immer neue Blockchains entstehen, doch sie bilden noch kein gemeinsames Netz. Erste Anbieter versuchen, diese Lücke bei der Interoperabilität zu schließen.

GitLab 11.0: Auto-DevOps-Feature für alle Nutzer

heise online Newsticker - 26. Juni 2018 - 17:00
Das als Beta in GitLab 10.0 eingeführte Auto DevOps ist jetzt für alle GitLab-Nutzer verfügbar. Es soll Arbeitsabläufe automatisieren und einfacher gestalten.

RTL will Netflix und Amazon Prime Video angreifen

heise online Newsticker - 26. Juni 2018 - 17:00
Bert Habets, Chef der RTL-Group, glaubt, mit eigenem Video-on-Demand gegen die Platzhirschen Netflix und Amazon Prime Video mithalten zu können.

Top500 der Supercomputer: Amerika first, aber wohl nur kurz

heise online Newsticker - 26. Juni 2018 - 16:30
Der US-amerikanische Summit-Rechner liegt nun auf Platz 1 in der neuen 51. Top500-Liste der Supercomputer.

Elektro-Rennwagen: Volkswagen bricht den Rekord am Pikes Peak

heise online Newsticker - 26. Juni 2018 - 16:00
Der Elektro-Rennwagen von VW hat am Pikes Peak nicht nur die konventionelle Konkurrenz hinter sich gelassen, sondern auch eine neue Bestzeit aufgestellt.

20 Jahre Gigabit-Ethernet

heise online Newsticker - 26. Juni 2018 - 16:00
Wer heute LAN kauft, kauft Gigabit-Ethernet, das am 25. Juni 1998 standardisiert wurde – für Glasfasern.

Lecker Strom: Mikroorganismen als Elektronenatmer und Elektronenfresser

heise online Newsticker - 26. Juni 2018 - 15:30
Einige Mikroorganismen ernähren sich von Strom oder verwandeln Rohstoffe in Elektrizität. Das wollen sich Forscher zunutze machen.

NeTV2 und DIY-Mikroskope – neue Crowdfunding-Projekte für Maker

heise online Newsticker - 26. Juni 2018 - 15:30
Ein neues FPGA-Board, Mikroskope für Citizen Science oder Elektronik für Escape Rooms – auf den Crowdfundingseiten gibt es immer Projekte zu entdecken.

Fünf externe Festplatten im Test: Backups per USB 3.0

heise online Newsticker - 26. Juni 2018 - 15:30
TechStage hat fünf externe Festplatten mit USB-3.0-Anschluss getestet. Die 3,5-Zoll-Systeme bringen bis zu 10 TByte Speicher und eigenen sich gut für Backups.

Mediacurrent: PDFs in Drupal (DrupalCon Session Review)

Planet Drupal - 26. Juni 2018 - 15:10

There were a lot of amazing sessions at DrupalCon Nashville 2018, but one of the few sessions that sparked my interest was “PDFs in Drupal” presented by Dan Hansen. In this session, Dan goes through the importance of PDFs, gave a short introduction to some of the more popular PDF rendering libraries, and gave a demo on some tips and tricks that I found very useful for my future projects.

Most, if not all of us, have opened a PDF recently. PDFs are popular because they are universal as a document format and can easily be sent to others without having to worry about whether their machine can open them. Despite this, Dan notes that it feels like PDFs are behind in support, and it would be nice to have better PDF handling in Drupal core - similar to images in media libraries.

PDF Rendering Libraries

This session introduced a handful of popular PDF rendering libraries:

  • Print-to-PDF
  • jsPDF
  • FPDF
  • mPDF
  • TCPDF
  • FPDI
  • DOMPDF
  • Wkhtmltopdf
  • PDFtk
PDFs in Drupal

In Drupal 7, the most popular module for generating PDFs is the Print module - but does not support Drupal 8. Fortunately, there are options available for Drupal 8:

  • Printable - based on the Print module to allow generation of PDFs. It relies on the PDF API, which is currently not stable.
  • Entity Print (recommended) - allows for printing any Drupal entity or View (D8 only) to PDF. This module provides flexibility with PDF rendering libraries and is more lightweight compared to the Print module and has a stable release for both D7 and D8.
  • FillPDF - allows for filling PDF with values. This module can be used with the PDFtk library or a paid third-party service, and can help in reducing overhead of rendering PDFs.
     
Tips and Tricks

I found Dan’s demos to be the most interesting - as he showed some code examples of various (and seemingly common tasks) related to PDFs. The following examples from Dan’s session shows how simple and straightforward it is to work with PDFs:

Making a PDF from HTML

A custom controller can simply return the following output:

$dompdf = new Dompdf();
// Pass the HTML markup.
$dompdf->loadHtml($markup);
// Render the HTML as PDF.
$dompdf->render();
// Stream the generated PDF back to user via browser.
$dompdf->stream();

Combining 2 PDFs

Using the PDFtk library:

$pdf = new Pdf([ 
  'A' => '/path/file1.pdf', // A is alias for file1.pdf 
  'B' => ['/path/file2.pdf','pass**word'], // B is alias for file2.pdf ]);
$pdf->send();

Notice that you can specify a password for the PDF file (if there is one). You can also extract specific pages from the PDF files as well:

$pdf->cat(1, 5, 'A') // pages 1-5 from A 
  ->cat(3, null, 'B') // page 3 from B 
  ->cat(7, 'end', 'B', null, 'east') // pages 7-end from B, rotated East 
  ->cat('end', 3,'A','even') // even pages 3-end in reverse order from A ->cat([2,3,7], 'C') // pages 2,3 and 7 from C    
  ->saveAs('/path/new.pdf');

More of these examples can be found at https://packagist.org/packages/mikehaertl/php-pdftk.

Fill in a PDF Template

Using the FillPDF module:

$pdf = new Pdf([‘PATH_TO_PDF’]);
$pdf->fillForm([
  ‘name_of_text_field’ => ‘Some value’
])
->needAppearances()
->send(‘filled.pdf’);

I really enjoyed and learned a lot of useful tips from Dan’s session, and I encourage anyone who is looking to work with PDFs in Drupal to check out the session.

Related Content:
Accessibility: Let's Talk PDFs | Blog
Top Drupal 8 Modules | Blog
Mediacurrent Top Drupal 8 Modules: Drupalcon 2018 Edition | Blog

Web Wash: Display Blocks within Content pages using Block Field in Drupal 8

Planet Drupal - 26. Juni 2018 - 15:00

The Block field module lets you insert a Drupal block as a field on your content.

A Drupal theme is divided into regions and you can place blocks or your own custom blocks into these regions. You accomplish this task by dragging and ordering blocks in the "Block Layout" screen. That means you can append blocks before or after the main content of your content type. This "Block Layout" screen will soon be cluttered if you have multiple content types and/or multiple single nodes, each one with a different custom block.

However, there’s a way to insert a block (or many blocks) directly into your content as a field. Thus, you don’t have to place the block in the "Block Layout" screen, instead, you insert the block as a field on the node.

In this tutorial, we’re going to cover the usage of the Block field module. Let’s start!

Wohnungsnot: München will Airbnb und Co. in die Pflicht nehmen

heise online Newsticker - 26. Juni 2018 - 14:30
Wohnraum in München ist knapp. Viele Eigentümer vermieten ihre Wohnungen an Städteurlauber. Die Stadt München will Airbnb und Co. jetzt in die Pflicht nehmen.

NASA-Orbiter fotografiert blaue Düne auf dem Mars

heise online Newsticker - 26. Juni 2018 - 14:00
Der Mars Reconnaissance Orbiter hat in einem Mars-Krater eine große Düne mit ungewohnter Färbung entdeckt: Sie ist blau.

Transparente Algorithmen: Barley will Regelung auf EU-Ebene

heise online Newsticker - 26. Juni 2018 - 14:00
Die Bundesjustizministerin will Verbraucher darüber aufklären, warum ein Algorithmus im Internet sie in eine bestimmte Kategorie einsortiert.

ComputerMinds.co.uk: Including form values in an email

Planet Drupal - 26. Juni 2018 - 13:46

Let's say you've built a custom form for your Drupal 8 site. It contains various elements for input (name, email address, a message, that kind of thing), and you want to send the submitted values in an email to someone (perhaps a site admin). That's a pretty common thing to need to do.

This could be done with Drupal's core contact forms, webforms, or similar -- but there are cases when a bespoke form is needed, for example, to allow some special business logic to be applied to its input or the form presentation. The drawback of a custom form is that you won't get nice submission emails for free, but they can be done quite easily, with the token module (you'll need that installed).

In your form's submission handler, send an email using the mail manager service (I'll assume you can already inject that into your form, read the documentation if you need help with that):

<?php $params = [ 'values' => $form_state->getValues(), ]; // The 'plugin.manager.mail' service is the one to use for $mailManager. $mailManager->mail('mymodule', 'myform_submit', 'admin@example.com, 'en', $params);

Then create a hook_mail() in your .module file, with a matching key ('myform_submit' in my example):

<?php /** * Implements hook_mail(). */ function mymodule_mail($key, &$message, $params) { switch ($key) { case 'myform_submit': $token_service = \Drupal::token(); $token_data = [ 'array' => $params['values'], ]; // In this example, put the submitted value from a 'first_name' element // into the subject. $subject = 'Submission from [array:value:first_name]'; $message['subject'] = $token_service->replace($subject, $token_data, ['clear' => TRUE]); // Each submitted value can be included in the email body as a token. My // form had 'first_name', 'last_name', 'color' and 'birthdate' elements. $body = <<>>; $message['body'] = [ $token_service->replace($body, $token_data, ['clear' => TRUE]), ]; break; } }

Spot the [array:value:thing] tokens! Using these 'array' tokens makes it really easy to include the whatever input gets submitted by visitors to this custom form on your Drupal site. Note that there's no sanitization done - although if your email is just plain text, that's probably not a problem.

There are more array tokens you can use too, such as ones to return a comma-separated list of all items in an array, a count of items, or just the first/last item. See the original issue for examples. These tokens are available in Token's Drupal 7 version too!