Planet Drupal

Subscribe to Planet Drupal feed - aggregated feeds in category Planet Drupal
Updated: 33 min 50 sec ago

PreviousNext: Using Mink for web testing

Tue, 15/07/2014 - 01:00

PreviousNext have been using Behat to test Drupal 7 sites for some time now. More recently, there has been a big push to introduce Behat tests in Drupal 8. So what is it all about?

In this post, I'll be taking a look at the Mink layer behind Behat and using it for web scraping and functional testing and what this means for the future of Drupal testing.

Categories: Elsewhere

Károly Négyesi: Drupal 8 progress from my / MongoDB perspective: update #27

Tue, 15/07/2014 - 00:53

There hasn't been an update for some time now; things have quieted down a bit, I am mostly just writing drivers now (and coach people on migrate). MongoDB module caught up with the latest config changes and so the module works again. Migrate bugfixing moves along steadily with more and more people actually trying it and fixing bugs, hurray! Blocks now get placed more sensibly, there's steady progress on D6->D8 CCK Single On/Off Checkbox, Checkboxes/Radio buttons, and Select formatters, also node authors in more interesting cases are broken (In Drupal 6, the node.uid and the node_revision.uid can be different). The first step for migration groups is ready. This is the stepping stone for Drupal 7 migrations because quite a few migration will need to be in both the Drupal 6 and the Drupal 7 group. It is also quite important for contrib -- now contrib will be able to just add in a migration YAML that this migration belongs to the Drupal 6 group and it'll run along with core, as easy as that.

Our favorite meta issue convert SQL queries to entitity queries issue is almost finished, opens the door for multilingual / performance enhancements and of course MongoDB :)

I have discussed with Crell how to define a standard mechanism for backend-aware service overrides. As usual, this is good for core because it allows MySQL and PostgreSQL specific drivers but also at the same time it will help MongoDB as well: currently the MongoDB module handles the service overrides but it's an all-or-nothing thing. With this issue, you'll be able to mix various storage backends as you want in a standard fashion.

Finally, even if it's not directly MongoDB related, the issue to switch on twig autoescape is almost done too -- this will make Drupal 8 more secure, even custom modules and custom themes will be easier to write in a secure fashion. Hopefully this will make Drupal 8 an even more appealing offer.

Categories: Elsewhere

Drupal Association News: Drupal Association Board Meeting Summary

Tue, 15/07/2014 - 00:22

We held our July Drupal Association Board Meeting last Wednesday. Halfway through the year, we took the opportunity to review our metrics for the year thus far, discuss some possible changes to our governance model, and tackle a couple of housekeeping issues in executive session. If you somehow managed to miss us during the live session, never fear! We've got a recording, the meeting materials, and the minutes available for your perusal, as well as this summary:


DrupalCon Austin is now behind us, but it's not forgotten! We're thrilled to have helped host an event that was so successful in so many ways. We were able to beat our Portland attendance numbers, though we did fail to meet our stretch goal of 4,000 attendees. At this point, we are sifting through all the registration, financials, and evaluation data to pull together a summary report (with comparisons to Portland) for the August board meeting.

Next up is DrupalCon Amsterdam. Registration for Amsterdam is strong and we're particularly excited that we had a record number of session submission - over 500! The sessions are now set, and we have a great line up, covering some of the most relevant topics for our community. There will be fun as well, of course. What's more fun than a bicycle? Apparently nothing, because many of our attendees are purchasing the bike package as part of their registration! And of course, there's Tour de Drupal

DrupalCon Latin America is the first DrupalCon scheduled for 2015. The site is scheduled to be up in mid-August for session submissions. We are also working on determining how we will handle languge and translation at DrupalCon Latin America. Working with the local team, we are discussing options for content translation so that we can serve both English and Spanish speakers.

We were able to create a lot of momentum for at DrupalCon Austin. Staff and Working group members conducted several user research interviews for the User Research Project led by Whitney Hess. And, in the weeks following DrupalCon, our staff were able to deploy over 30 patches to that came out of the sprints in Austin. 

In addition, we also recently deployed a CDN service for The CDN allows us to reduce strain on our infrastructure, increase our security, and most importantly should increase performance for users, especially those outside of the United States. We want to thank Narayan Newton (nnewton) and the rest of the Infrastructure Working Group for their direction and help.

Finally, there is a new way for you to keep on top of change notifications for We've standardized the reporting and, in addition to posting them online at, you can now subscribe to an email list to receive notifications right in your inbox.

Board Governance

At the June board retreat in Austin, each of the board committees met to discuss current issues. The Governance Committee met with the aim of exploring ideas that would increase the diversity of candidates for our elected candidates, possible term limits for board members, and how to improve committee performance on the board. Based on that conversation, the committee presented several ideas for the board to discuss. No decisions were made at this time, but the Governence Committee did receive good feedback to incorporate into future proposals. 

Next Meeting

Want more board news? Get it live! Join us at one of our upcoming board meetings

Flickr photo: Kristen Pol

Categories: Elsewhere

Deeson Online: Deeson Online and DrupalCon Amsterdam: From rockstar speakers to world-class sessions

Mon, 14/07/2014 - 21:12
Deeson Online and DrupalCon Amsterdam: From rockstar speakers to world-class sessionsBy Lizzie Hodgson | 14th July 2014Look alive! DrupalCon Amsterdam is going to be here in no time, and Deeson Online are once again a proud Silver Sponsor of what is shaping up to be a rather spectacular event.

Possibily the most significant date in the European Drupal community diary, DrupalCon Amsterdam will not only offer all the usual mix of community summit, sessions, BOFs and sprints, it also has some very impressive keynotes, including co-editor of Boing Boing, Cory Doctorow.

Photo credit: Jonathan Worth CC Attribution-Share Alike 2.0 Generic license

A regular contributor to The Guardian, the New York Times, Publishers Weekly and Wired, Doctorow is formerly the Director of European Affairs for the Electronic Frontier Foundation, as well as a renowned advocate of freedom in technology law, policy, standards and treaties. Nice.

Deeson Online are getting involved too!

We'll share our BOFs in the next few weeks, but Deeson Online MD, Tim Deeson, is going to be running a session with Vesa Palmu from Wunderkraut, Paul Johnson from CTI Digital and Jeff Walpole of Phase2 – all chaired by Robert Douglass from Commerce Guys.

About the session

Entitled 'Life in the fast lane - achieving sustainable growth' the panel will explain how they built their world-class Drupal businesses.

From growing pains to scaling to meet demand, the audience can quiz each panellist on how they've broken through various barriers to get to where they are as a company.

Key topics will include:
  • How do you differentiate your business in the market?
  • Describe a defining moment which changed your business
  • To service larger clients, what specialisms have you needed to deliver in-house?
  • How does your business plan to sustain growth ie VC, Acquisition, JV?
  • What is the most challenging aspect of delivering larger projects?
  • How do you mitigate risk?
  • What is the biggest challenge your business foresees?
  • How should large Drupal shops contribute to the sustainability of the project?
So if you want to learn from leaders of four of the world's most accomplished Drupal businesses, this session is for you!
Categories: Elsewhere

Lullabot: Module Monday: Honeypot

Mon, 14/07/2014 - 20:00

Fighting spam is an ongoing cat and mouse game as site owners come up with protections against spam, and spammers come up with increasingly impressive ways to bypass those protections. Solutions like Mollom have been popular in recent years, however Mollom is tied to an external service and only works while that service is running smoothly. Additionally, it costs money if your site has a lot of traffic. CAPTCHA challenges are also a popular solution, but they have accessibility problems -- and automated tools are getting increasingly successful at bypassing them.

Categories: Elsewhere

Acquia: The Open Source Value Proposition

Mon, 14/07/2014 - 16:36

Every so often, advocates and vendors of proprietary/closed source software attempt a FUD (Fear, Uncertainty & Doubt) campaign of comment and link-baiting in order to reframe the conversation around Open Source. The arguments brought up in these discussions are predictable and generally straw man arguments that hold little water, so I wanted to take time to break these down and show the real value proposition of Open Source platforms, web content management systems generally, and Drupal specifically.

Categories: Elsewhere

Stanford Web Services Blog: Module of the Day: Path Redirect Import

Mon, 14/07/2014 - 15:02

Today we're going take a look at the Path Redirect Import module, which lets you import redirects in bulk into your Drupal site.

All of the modules described in this post are available on Stanford Sites.

Categories: Elsewhere Function scope & Drupal cache

Mon, 14/07/2014 - 13:48
Function scope & Drupal cache

When developing with caching in mind it's important to consider functionality scope. For example, writing code which is per visitor specific in PHP with caching support ahhh =O. While rewriting that same functionality in JavaScript offers us a quick and cache friendly solution. Consider the following examples.

/** * Implements hook_preprocess_TEMPLATE(). */ function THEME_preprocess_page(&$variables) { $detect = mobile_switch_mobile_detect(); if ($detect['ismobiledevice'] && !$detect['istablet']) { $variables['logo'] = url('sites/all/themes/THEME/images/logo_rev.png', array('absolute' => TRUE)); } } /** * Custom header block content. */ function _header_search_content_block() { $detect = mobile_switch_mobile_detect(); $form = drupal_get_form('search_form'); // Format search form. $form['basic']['keys']['#attributes']['placeholder'] = t('Search'); $form['basic']['keys']['#title_display'] = 'invisible'; $form['basic']['keys']['#size'] = 20; if ($detect['ismobiledevice'] || $detect['istablet']) { $form['basic']['keys']['#size'] = 15; } $items = array( render($form), l(t('another item'), 'link') ); return theme('item_list', array('items' => $items)); }

Clearly this code can be easily rewritten in JavaScript. However with caching enabled we'll need a method to pass our device detection variables. The only function which is exempt from Drupal cache is boot(). Calling drupal_add_js() directly from hook_boot() fails; the following example is using Mobile Switch and illustrates a work around.

/** * This is an example of how to manipulate site elements with page * caching enabled. We pass our detection variables to js settings * which we can then act on. */ function MODULE_boot() { $detect = mobile_switch_mobile_detect(); // Whatami. $_SESSION['detect'] = array( 'ismobile' => $detect['ismobiledevice'], 'istablet' => $detect['istablet'] ); } /** * Implements hook_init(). */ function MODULE_init() { drupal_add_js(array('detect' => $_SESSION['detect']), 'setting'); } /** * @file * MODULE.theme.js */ (function($) { Drupal.behaviors.MODULE = { attach: function(context, settings) { // Swap logo for mobile. if (settings.detect.ismobile && !settings.detect.istablet) { $('.site-branding__logo img').attr('src', Drupal.settings.basePath + 'sites/all/themes/THEME/images/logo_rev.png'); } // Search box size. if (settings.detect.ismobile || settings.detect.istablet) { $('.l-region--header .search-form input.form-text').attr('size', 15); } } }; }(jQuery));

These flags can of course be used for more fruitful purposes =)... Note, this sort of consideration is most likely second nature to most Xd.

Categories: Elsewhere

CTI Digital: Installing Drush using Composer on Mac OS X 10.9 Mavericks

Mon, 14/07/2014 - 12:46
Following on from our previous guide “Creating and using an public/private SSH key-pair in Mac OS X 10.9 Mavericks” in which we walked you through the process of setting up Git on Max OS X 10.9 Mavericks, we’re now going to look at installing Drush using Composer. If you’re never heard of Drush before, the description provided on the  Drush GitHub repository offers a succinct and accurate explanation of what Drush is and the tools it makes available to you: Drush is a command line shell and Unix scripting interface for Drupal. If you are unfamiliar with shell scripting, reviewing the documentation for your shell (e.g. man bash) or reading an online tutorial (e.g. search for "bash tutorial") will help you get the most out of Drush. Drush core ships with lots of useful commands for interacting with code like modules/themes/profiles. Similarly, it runs update.php, executes sql queries and DB migrations, and misc utilities like run cron or clear cache. Ultimately our goal in these series of guides is to give anyone both experienced and inexperienced alike the knowledge and skills required to configure their system so that an installation of Drupal can be run from it with a suite of tools available for them to use from the get-go. Let’s begin. Installing Composer Rather than installing Drush manually, we’re going to let a tool called Composer do all the hard work for us. Composer is a tool for handing dependency management the full description for which can be found on the Composer site. In a nutshell though, the following sums up Composer well: Composer is a tool for dependency management in PHP. It allows you to declare the dependent libraries your project needs and it will install them in your project for you. Let’s install Composer. Open a new instance of the Terminal by either navigating to the Applications folder within the finder followed by the Utilities sub-folder, or alternatively by pressing “Cmd+Space” and typing “Terminal” followed by the “Enter” key. Once open, type the following command to ensure you’re in your home directory: cd ~/ To download composer, type the following command into the Terminal and hit enter: curl -sS| php At this point you could type “~/composer.phar --help” into the command line and you’ll most likely get a list Composer help documentation, but we want to be able to access Composer simply by typing the command “composer”, so let’s move the *.phar file into our “/user/local/bin” directory. Note: On a fresh installation of OS X 10.9, the “/usr” directory will very likely be empty. If this is the case, to enable us to successfully move Composer to “/usr/local/bin/composer” you’ll need to type the following two commands “sudo mkdir /usr/local” and “sudo mkdir /user/local/bin”. After typing the first command, you may be prompted for your system password. Simply enter it to continue. Now we’re all set to move Composer. To do this, type the following command into the Terminal: mv composer.phar /usr/local/bin/composer Note: If you get an error trying to move the file, prefix the command above with “sudo” and try again. We should now be able to type “composer” into the terminal and get something other than an error returned. Try this out by typing “composer” and hitting enter. Adding the Composer “bin” directory to our path Once Drush is installed, we will be able to type “~/.composer/vendor/bin/drush” followed by the Drush command of our choice, but who wants to do that every time?  To be enable the ability to type “drush” followed by our command we need to add Composer’s bin directory to our path. In your home directory “~/“ type the command “nano ~/.bash_profile” and add the following line to the file that opens up: export PATH="$HOME/.composer/vendor/bin:$PATH" Quit Nano, by pressing “Ctrl+X” and when asked if you wish to save the document type “Y” and hit “Enter”. Finally we need to re-source our “.bash_profile” file by typing “source ~/.bash_profile” into the Terminal (alternatively you can quit and re-open the Terminal). Installing Drush At this point, installing Drush is a piece of cake. Simply type the following into the Terminal and hit “Enter” composer global require drush/drush:dev-master Drush should now be installed. To ensure it is, type “drush” into the command line and you should see a series of Drush help documentation. If you had any problems following this guide feel free to get in touch with me on Twitter at @craigperks
Categories: Elsewhere

Wunderkraut blog: Configuration Entities in Drupal 8

Mon, 14/07/2014 - 11:10

With the overhaul of many API's in Drupal 8, one of the new kids on the block is the configuration system with its integration with the entity API. This means that we can now define configuration entities (that work much like the regular content entities) for the purpose of managing more complex configuration. For example, a View is a configuration entity and so is a field or an image style.

In this article we will look at how to define a configuration entity type that will serve a simple purpose, describe dummy flower configuration entities. We will do so in a module called flower and will use the alpha13 release of Drupal 8 to do it.

Before we get started, let's define a practical goal for this tutorial. As I said, we will have a flower config entity type with a couple of properties: name, number of petals, color and season. And by the end, we will have a fully fledged UI to create and manage them. The final code you can also find in this repository.

So let's begin.

The configuration entity interface

The first thing we need to do is define an interface our Flower entity type class can implement and that extends the default ConfigEntityInterface. So inside of our module's src/ folder, create a file called FlowerInterface.php with the following interface:

/** * @file * Contains \Drupal\flower\FlowerInterface. */   namespace Drupal\flower;   use Drupal\Core\Config\Entity\ConfigEntityInterface;   /** * Provides an interface defining a flower entity type. */ interface FlowerInterface extends ConfigEntityInterface {   }

As you can see, we are just extending the default configuration entity interface without adding any methods to it (which is possible).

The configuration entity class

Next, we will focus on the crux of defining our own configuration entity class. Go ahead and create a folder inside the src/ directory called Entity, and within it, a file called FlowerEntity.php:

/** * @file * Contains \Drupal\flower\Entity\FlowerEntity. */   namespace Drupal\flower\Entity;   use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\flower\FlowerInterface;   /** * Defines a Flower configuration entity class. * * @ConfigEntityType( * id = "flower", * label = @Translation("Flower"), * fieldable = FALSE, * controllers = { * "list_builder" = "Drupal\flower\FlowerListBuilder", * "form" = { * "add" = "Drupal\flower\Form\FlowerForm", * "edit" = "Drupal\flower\Form\FlowerForm", * "delete" = "Drupal\flower\Form\FlowerDeleteForm" * } * }, * config_prefix = "flower", * admin_permission = "administer site configuration", * entity_keys = { * "id" = "id", * "label" = "name" * }, * links = { * "edit-form" = "flower.edit", * "delete-form" = "flower.delete" * } * ) */ class FlowerEntity extends ConfigEntityBase implements FlowerInterface {   /** * The ID of the flower. * * @var string */ public $id;   /** * The flower name. * * @var string */ public $name;   /** * The flower color. * * @var string */ public $color;   /** * The number of petals. * * @var int */ public $petals;   /** * The season in which this flower can be found. * * @var string */ public $season;   }

What we have here is a simple class defining the entity properties we want (name, id, color, number of petals and season). This class extends the default ConfigEntityBase class and implements our interface. What happens above the class definition is what's interesting though.

Using annotations, we are basically telling Drupal about our Flower entity type.

The @ConfigEntityType tells Drupal that this is a configuration entity type (as opposed to a plugin or something else). Within its definition, we have an array-like structure with the following information (I will only mention the keys that are not super obvious):

  • label - the label of the entity type passed through the translation system.
  • fieldable - the configuration entities are not fieldable, but the content entities are. Since we are using the same entity API, we can specify this.
  • controllers - all the classes needed to manage these entities. The list_builder class will provide an admin overview interface of the entities, whereas the form classes are used to perform the CRUD operations through the UI.
  • config_prefix - a configuration identifier
  • entity keys - mapping of the main entity keys to the entity properties we defined. For instance, when we call the label() method on the entity object, it will return the flower name.
  • links - administration links for editing and deleting entities with values referencing routes. Specifying them here will make Drupal add them automatically to the operations column on the entity overview page (we'll see this in a minute).

For more information about the structure of an entity class annotation, follow this documentation page.

The entity forms

The next thing we need to do is create the forms we referenced in the annotations above: for adding, editing and deleting flower entities. The cool thing is that the form for adding can be reused for editing as well. For delete, we extend a special class that gives us all we need for a confirmation form. But first, the add/edit form (FlowerForm.php) inside of the src/Form/ folder:

/** * @file * Contains \Drupal\flower\Form\FlowerForm. */   namespace Drupal\flower\Form;   use Drupal\Core\Entity\EntityForm; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Url;   /** * Class FlowerForm * * Form class for adding/editing flower config entities. */ class FlowerForm extends EntityForm {   /** * {@inheritdoc} */ public function form(array $form, array &$form_state) {   $form = parent::form($form, $form_state);   $flower = $this->entity;   // Change page title for the edit operation if ($this->operation == 'edit') { $form['#title'] = $this->t('Edit flower: @name', array('@name' => $flower->name)); }   // The flower name. $form['name'] = array( '#type' => 'textfield', '#title' => $this->t('Name'), '#maxlength' => 255, '#default_value' => $flower->name, '#description' => $this->t("Flower name."), '#required' => TRUE, );   // The unique machine name of the flower. $form['id'] = array( '#type' => 'machine_name', '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH, '#default_value' => $flower->id, '#disabled' => !$flower->isNew(), '#machine_name' => array( 'source' => array('name'), 'exists' => 'flower_load' ), );   // The flower color. $form['color'] = array( '#type' => 'textfield', '#title' => $this->t('Color'), '#maxlength' => 255, '#default_value' => $flower->color, '#description' => $this->t("Flower color."), '#required' => TRUE, );   // The number of petals. $form['petals'] = array( '#type' => 'textfield', '#title' => $this->t('Petals'), '#maxlength' => 255, '#default_value' => $flower->petals, '#description' => $this->t("The number of petals."), '#required' => TRUE, );   // The season. $form['season'] = array( '#type' => 'select', '#options' => array( 'Spring' => 'Spring', 'Summer' => 'Summer', 'Automn' => 'Automn', 'Witer' => 'Winter' ), '#title' => $this->t('Season'), '#maxlength' => 255, '#default_value' => $flower->season, '#description' => $this->t("The season in which this flower grows."), '#required' => TRUE, );   return $form; }   /** * {@inheritdoc} */ public function save(array $form, array &$form_state) {   $flower = $this->entity;   $status = $flower->save();   if ($status) { // Setting the success message. drupal_set_message($this->t('Saved the flower: @name.', array( '@name' => $flower->name, ))); } else { drupal_set_message($this->t('The @name flower was not saved.', array( '@name' => $flower->name, ))); } $url = new Url('flower.list'); $form_state['redirect'] = $url->toString();   }   }

In our FlowerForm class we are extending the Drupal EntityForm class and implementing 2 of its methods: form() and save(). In the first one, we define a regular Form API form very similar to what we do in Drupal 7. But there are a few cool new things happening there as well:

  • We extend the parent form and add our elements to that definition.
  • We get the configuration entity object from the entity property of the parent class.
  • We check the operation being performed on the entity and if the user is editing it, we change the title of the page to reflect this
  • Instead of using the procedural t() function, we access $this->t() on the parent class for best practice.
  • We access the config entity public properties and set them as the defaults in the form elements' definition.
  • For the machine_name, we use the flower_load() helper function (that we will need to define in our .module file) in order to automatically check whether an entity with that ID already exists.

In the save() method we perform the simple operation of saving the entity object to the configuration system. Couldn't get simpler than this. And after the save is performed, we redirect to the flower entity overview page. Here we use the Url class to build a url object based on a route (that we will define later).

Next, let's quickly create the delete form.

Inside the same src/Form/ folder, create a FlowerDeleteForm.php file with the following class:

/** * @file * Contains \Drupal\flower\Form\FlowerDeleteForm. */ namespace Drupal\flower\Form;   use Drupal\Core\Entity\EntityConfirmFormBase; use Drupal\Core\Url;   /** * Form that handles the removal of flower entities. */ class FlowerDeleteForm extends EntityConfirmFormBase {   /** * {@inheritdoc} */ public function getQuestion() { return $this->t('Are you sure you want to delete this flower: @name?', array('@name' => $this->entity->name)); } /** * {@inheritdoc} */ public function getCancelRoute() { return new Url('flower.list'); } /** * {@inheritdoc} */ public function getConfirmText() { return $this->t('Delete'); } /** * {@inheritdoc} */ public function submit(array $form, array &$form_state) {   // Delete and set message $this->entity->delete(); drupal_set_message($this->t('The flower @label has been deleted.', array('@label' => $this->entity->name))); $form_state['redirect_route'] = $this->getCancelRoute();   } }

With this form class we are extending the Drupal EntityConfirmFormBase that provides us with all we need for a delete confirmation form. By implementing these self-explanatory methods, we take care of the entity delete process. Finally, it's time to define the admin overview page.

The entity list builder

As we declared when defining the config entity class, we now need a class file responsible for building the overview page of our entities. So straight in the src/ folder of our module you can create a FlowerListBuilder.php class file with the following class:

/** * @file * * Contains Drupal\flower\FlowerListBuilder */   namespace Drupal\flower;   use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Entity\EntityInterface;     class FlowerListBuilder extends ConfigEntityListBuilder {   /** * {@inheritdoc} */ public function buildHeader() { $header['label'] = $this->t('Name'); $header['color'] = $this->t('Color'); $header['petals'] = $this->t('Number of petals'); $header['season'] = $this->t('Season'); return $header + parent::buildHeader(); }   /** * {@inheritdoc} */ public function buildRow(EntityInterface $entity) {   // Label $row['label'] = $this->getLabel($entity);   // Color $row['color'] = $entity->color;   // Petals $row['petals'] = $entity->petals;   // Season $row['season'] = $entity->season;   return $row + parent::buildRow($entity); }   /** * {@inheritdoc} */ public function render() {   $build = parent::render();   $build['#empty'] = $this->t('There are no flowers available.'); return $build; }   }

In this class that extends the ConfigEntityListBuilder, we implement three methods. The buildHeader() method is responsible for creating the table header of our overview page whereas buildRow() will create the rows based on the number of entities and their values. Lastly, we are overriding the render() method so that we can specify a custom message to display in case there are no entities to show (personal preference). And that's basically it with the list builder class.


There are a few more things we need to take care of in order to round up our configuration entity type. The first one has just became kind of mandatory so I'll start with that: the configuration schema. So let's quickly create the folder structure inside our module (config/schema/) and inside a file called flower.schema.yml we can have the following:

# Schema for the configuration files of the Flower module. flower.flower.*: type: mapping label: 'Flower' mapping: id: type: string label: 'Flower identifier' uuid: type: string label: 'UUID' name: type: label label: 'Name' color: type: string label: 'Color' translatable: true petals: type: integer label: 'Number of petals' season: type: string label: 'Season' translatable: true

On the first line (after the comment) we start defining the schema for the (flower module).(flower configuration entity type).(all flower configuration entities). And it follows to map all the entity properties and specify what data type they are. Although the uuid property was not defined by us, Drupal adds it by default and we can specify it here.

As far as I could tell, the label-typed properties become translatable automatically whereas for all the rest we want translatable we can specify translatable: true. Translation is one of the biggest reasons for which we use these schemas for configuration entities.

And now that the schema is taken care of, it's time for some finishing touches. First, let's create our routes so that we can access everything in the browser. Inside of a file called flower.routing.yml in the module root folder, add the following:

flower.list: path: '/admin/structure/flowers' defaults: _entity_list: 'flower' _title: 'Flowers' requirements: _permission: 'administer site configuration' flower.add: path: '/admin/structure/flowers/add' defaults: _entity_form: 'flower.add' _title: 'Add a new flower' requirements: _permission: 'administer site configuration' flower.edit: path: '/admin/structure/flowers/edit/{flower}' defaults: _entity_form: 'flower.edit' _title: 'Edit flower' requirements: _permission: 'administer site configuration' flower.delete: path: '/admin/structure/flowers/delete/{flower}' defaults: _entity_form: 'flower.delete' _title: 'Delete flower' requirements: _permission: 'administer site configuration'

For more information about the structure of a route file (and what the above keys actually mean), please consult this documentation page. But an important take-away are the paths we defined at admin/structure/flowers.

Second, on the flower overview page, we'd probably like a link to add new flowers to the site. So let's create another YML file in the root of our module called flower.local_actions.yml to define that link:

flower.add: route_name: 'flower.add' title: 'Add flower' appears_on: - flower.list

This is a simple local action link definition called flower.add that uses the flower.add route and appears on the page given by the route flower.list. For more information about defining local actions, consult this documentation page.

Third, we can create a menu link under the Structure admin menu that will take us to the flower overview page. So inside of a file called flower.menu_links.yml in the module root folder, add the following:

flower.list: title: Flowers description: 'Administer the flower entities' parent: system.admin_structure route_name: flower.list

Here we create a link called flower.list found under the system.admin_structure link and that uses the flower.list route name. Simple.

Finally, we need to create the auto loader function that will be used by the machine_name form element to check whether an entity with a given machine name already exists (on the flower add form). So inside the flower.module file, create this function:

/** * Menu argument loader. Returns a flower entity * * @param $id * @return \Drupal\Core\Entity\EntityInterface|static */ function flower_load($id) { return FlowerEntity::load($id); }

And don't forget to use the FlowerEntity class at the top of the file:

use \Drupal\flower\Entity\FlowerEntity;

And that should be about it. Clear the caches, make sure the module is enabled, and start poking at it. Navigate to /admin/structure/flowers and create, edit, delete flower entities. Additionally, you can turn on configuration translation and translate all your entities into multiple languages. Cool, no?


In this tutorial we've looked at how we can create our own simple configuration entity type in Drupal 8. The alpha13 version (latest at the time of writing) has been used for this, so make sure that if you are using a newer one you make the necessary code adaptations if needed.

In Drupal 7 we do not have configuration entities and we are left with creating custom tables that hold data meant as configuration. And obviously, integration with the modest D7 entity API is practically inexistent. This all changes in Drupal 8 with the development of a robust entity API - fully integrated with the multilingual and configuration systems. Because of this, we now have exportable and translatable configuration entities used to manage more complex data that is not content.

And with all these new developments, we are being introduced to a few new concepts that can scare us a bit (services, dependency injection, plugins, OOP and so on). However, once we get used to them a bit, they will become a friend rather than foe and open the door to more sane, performant and modern development within the Drupal framework.

Categories: Elsewhere

Drupal core announcements: Drupal core security release window on Wednesday, July 16

Mon, 14/07/2014 - 04:45
Start:  2014-07-16 (All day) America/New_York Sprint Organizers:  David_Rothstein

The monthly security release window for Drupal 6 and Drupal 7 core will take place on Wednesday, July 16.

This does not mean that a Drupal core security release will necessarily take place on that date for either the Drupal 6 or Drupal 7 branches, only that you should prepare to look out for one (and be ready to update your Drupal sites in the event that the Drupal security team decides to make a release).

There will be no bug fix release on this date; the next window for a Drupal core bug fix release is Wednesday, August 6.

For more information on Drupal core release windows, see the documentation on release timing and security releases, and the discussion that led to this policy being implemented.

Categories: Elsewhere

Miles Carter: Drupal views templating tutorial: Outputting the respective image fields of multiple associated taxonomy term references

Mon, 14/07/2014 - 01:50

Courtesy of - Miles J Carter Photos on the Web Blog
Source URL : Drupal views templating tutorial: Outputting the respective image fields of multiple associated taxonomy term references

Using a custom field template to output taxonomy term references as their respective image fields, rather than as text or a link

The ingredient icons are term reference fields formatted to output as their respective image fields, rather than as a link or text

The example situation is where a view displays a list of nodes or fieldable entities, for our example items on a menu, and each of these has one or more taxonomy term references, in this example the main ingredients. While it’s simple to output the term references as plain text or a link, showing an image or other field attached to the term reference instead of this presents problems.

Using views relationships

The obvious solution is to create a relationship to the taxonomy in the view set up, and add the image field via the relationship. However, this currently presents issues with duplicate rows being output. If an item in the view has more than one term reference, it is displayed once for each term reference. Because of how views works, setting “distinct” and “pure distinct” in the query settings does nothing as they are technically distinct results (each has a different term reference).

The views_distinct module should offer a solution to this kind of problem, but currently it does not work in a way that can aggregate the required fields while filtering duplicates in this situation.

Creating the custom field template

In our example view, no relationship is used and the relevant term reference field is included in the field list

If you have never made a views template before, click the link “Information” in the Other section of the view:


This displays a list of possible templates to use in customising your view for each field in the view. The template names shown are ordered from least specific to most specific – the filename of the template determines which situtations it is used. The bolded template is the one currently being used. To make a new custom template, create a file in the theme’s templates directory with the name. Click the link next to it to get the default code which should go into the template. In this case we wish to control output in all situations the field appears, so the first custom template option (highlighted) is that used.


From the helpful comment at the top of the file, it can be seen that the contents of the view item can be found in the $row object. By debugging this object the location of the ingredients term references and their respective image fields can be found.

In this case the term reference field data is at:


and the image field at:


Where INDEX is the array index for multiple items.

The field_view_field() function is useful here to display the image field without needing to worry about URLs and allows control of formatting, e.g. image style presets. We also need to use an isset() condition to prevent warnings being thrown where rows don’t have any term references.

Putting this all together gives the example code:

if(isset($row->field_field_ingredients)) {
        $term = $row->field_field_ingredients;

        foreach($term as $ingredient){
                print render(field_view_field('taxonomy_term', $ingredient['raw']['taxonomy_term'], 'field_image',));

This outputs the image, but at it’s original size and with an ugly label that says “Image:”. To fix this, we need to use the optional fourth parameter of the field_view_field() function to control display and formatting of the field. The line inside the foreach() loop becomes:

print render(field_view_field('taxonomy_term', $ingredient['raw']['taxonomy_term'], 'field_image',
array('label'=>'hidden', 'settings' => array('image_style' => 'thumbnail'))));

This hides the label and sets the image style preset for the output to ‘thumbnail’.

Final code:

if(isset($row->field_field_ingredients)) {
        $term = $row->field_field_ingredients;

        foreach($term as $ingredient){
                print render(field_view_field('taxonomy_term', $ingredient['raw']['taxonomy_term'], 'field_image',
                array('label'=>'hidden', 'settings' => array('image_style' => 'thumbnail'))));

Source - Miles J Carter Photos on the Web Blog
Read the Original Article : Drupal views templating tutorial: Outputting the respective image fields of multiple associated taxonomy term references

Categories: Elsewhere

PreviousNext: Writing a custom Drupal Search API processor

Mon, 14/07/2014 - 01:07

When working with the Search API Drupal module, sometimes we need to programmatically add information that is not available for indexing as a field. Lucky we can write our own custom pre-processor to provide this information to the index.

Categories: Elsewhere Headless Drupal - Inline edit

Sun, 13/07/2014 - 23:00

In our last example we showed how to create node using an angular form served from Drupal itself. This time we are taking one big step further and create the node from a completely decoupled web app.
And if that's not enough for the readers excited by the idea of a decoupled Drupal, we've also added inline editing to the example!

Enjoy the live demo

If you know Form API's pains, you should be excited now

Continue reading…

Categories: Elsewhere

Freelock : I've got a theory: The Scientific Method applied to web site performance

Sun, 13/07/2014 - 18:10

What can you do about this page being so slow? That's a question we've been asked by half a dozen customers in the past 6 months, and as it turns out, we can do quite a lot.

One of my long-standing complaints about Drupal is that it's a resource hog. That's an issue we can generally help by throwing lots of hardware and caching systems at the problem -- but that's not the kind of performance issue these clients were having.

PerformanceScalingMonitoringDrupalDrupal PlanetTechnical
Categories: Elsewhere

Mediacurrent: The Power of Giving

Fri, 11/07/2014 - 22:00

Several years ago, a mentor told me to add computer tech services to my web design company’s services because “everyone’s a web designer.” His point: there’s a lot of competition in the web design and development market. With so much competition, why would web development shops like Mediacurrent place so much value in sharing industry knowledge and even custom code for free with the Drupal community? Why is it worthwhile for a for-profit company to share knowledge to a community that includes competitors?

Categories: Elsewhere

Midwestern Mac, LLC: Multi-value spatial search with Solr 4.x and Drupal 7

Fri, 11/07/2014 - 21:59

For some time, Solr 3.x and Drupal 7 have been able to do geospatial search (using the location module, geofield, or other modules that stored latitude and longitude coordinates in Drupal that could be indexed by Apache Solr). Life was good—as long as you only had one location per node!

Sometimes, you may have a node (say a product, or a personality) affiliated with multiple locations. Perhaps you have a hammer that's available in three of your company's stores, or a speaker who is available to speak in two locations. When solr 3.x and Drupal 7 encountered this situation, you would either use a single location value in the index (so the second, third, etc. fields weren't indexed or searched), or if you put multiple values into solr's search index using the LatLonType, solr could throw out unexpected results (sometimes combining the closest latitude and closest longitude to a given point, meaning you get strange search results).

Categories: Elsewhere

Joachim's blog: The ripple effect

Fri, 11/07/2014 - 21:21

Hello! I'm back. I've not made any blog posts in over a year and a half due to the site where my blog was before,, closing down. And while it took me some time to get round to writing a Migrate script to import my posts from the old site's database, it was actually getting round to setting up this new domain that took the longest.

So what have I been doing all this time? Especially as I still don't have a single Drupal 7 site out there to my name? Well, these days I work on a humongous web application which has kept me busy for the last 18 months; it's a large Drupal site (we hit a million of one of its several custom entity types recently), but to the general public it's just a login page. I may talk more about the development challenges in future posts.

Prior to that, I was building what would have been one of the earliest big Drupal Commerce sites to launch... except that very shortly before launch in October 2012, the whole project got canned.

Tags: contributing codedrupal commercedevelopmentmaintaining projects
Categories: Elsewhere

Lullabot: Front-end Rapport #3

Fri, 11/07/2014 - 20:00
Current Trends in Browser Market Share

Topics: Browsers

Arstechnica does a visual deep-dive into browser market shares through multiple charts and graphs — breaking down worldwide browser trends and adoption rates.

Categories: Elsewhere

Aten Design Group: Design4Drupal 2014

Fri, 11/07/2014 - 18:33

Design4Drupal 2014 is almost here, and Aten couldn't be more excited. This year, along with being the Design Partner for the event, members of Aten's Design & UX team will be presenting four different sessions.

This year's Design4Drupal (August 1-3) has been structured to give each day a specific focus. Friday kicks things off with a business summit, Saturday is chock full of sessions and Sunday wraps things up with sprints and trainings. Make sure you catch as many of Aten's sessions on Saturday as you can:

Saturday, August 2, 10:15am Enhancing Design with Adaptive Content

Aten’s Joel Steidl, Lead Architect, and Christine Coughlan, Information Architect, will share practical tips for breaking down and organizing content for projects of any size. They’ll share case studies to reinforce the theory and practice behind adaptive content and best practices for implementing it in Drupal and other platforms.

Layout Design Patterns

John Ferris, Aten's Lead Front-end Developer, presents reusable solutions to common layout problems. He'll begin with foundation CSS layout concepts and then build up to specific techniques for implementing complex layouts in Drupal.

Saturday, August 2, 2:15pm Anti-Handoff: A better design & front-end relationship

Front-end Developers delivering on what's promised by Designers can make or break a project. Erin Holloway, Aten's Senior Designer, will walk through approaching this problem with clear communication, the right tools and mutual respect. If you're struggling with collaboration between your team members, this session can help.

Saturday, August 2, 3:30pm Giving and Getting Great Feedback

Great feedback can be the lifeblood of a successful project. However, setting aside personal preference and giving objective feedback can be challenging. Responding to that feedback can be even harder. Aten’s Designer, Roxy Koranda, will give you the tools to both give and get great feedback.

With just 3 weeks until the event, there isn't a ton of time left to register. If you use Drupal and want to learn more about how best to approach Design, UX and Front-end Development, Design4Drupal is the place to be. We hope to see you there!

Categories: Elsewhere