Subscribe to feed Planet Drupal - aggregated feeds in category Planet Drupal
Bijgewerkt: 3 uur 56 min geleden

Drupal Watchdog: The Tao of the Wayfinder

di, 2015/08/11 - 9:29pm

Everyone working on software has a baseline competency with communication, yet it’s not unusual to see the time required to communicate effectively viewed as a distraction from the real task at hand. People seeking to deliver valuable software in a more timely and reliable fashion tend to turn to concrete changes – a new ticket system or software tool, more developers, performance bonuses – rather than delve into developing communication skills, despite the many concrete ways improved communication can increase a project’s momentum.

Set and Communicate Goals for Response Time

You’ve probably experienced some form of the information black hole. Maybe you put in a request to have an account created but have no idea if it will be minutes or months until the request is fulfilled. It’s important, but not urgent, and you don’t want to be “that person” who demands immediate attention. If only you knew how long it should take, you could set aside the stress of not knowing. Then, if a response didn’t arrive when it should have, you’d know it was time to double-check.

Both individuals and teams can:

  • Set honest response times;
  • Communicate them clearly and visibly;
  • Monitor how they’re living up to those goals;
  • Adjust processes or goals accordingly.

People are free to focus on other things when they know how long they have to wait.

Setting such expectations also frees you from more “Is it ready yet?” e-mails. Sending an auto-reply or a cut-and-paste acknowledgement like this should do the trick:

“If your request hasn’t been answered in three working days, something has gone amiss. Poke us with a stick by e-mailing”

It can be as formal or as playful as suits your needs.


Palantir: D8FTW: Storing data in Drupal 8

di, 2015/08/11 - 9:10pm

Newsflash: Storing and retrieving data is rather the point of a Content Management System like Drupal. Of course, not all content is created equal. Some needs a robust structure and curatorial controls built around it, while other data isn't really content at all but administrator-defined configuration. The way those need to work can vary widely.

In Drupal 7, developers had three not all that great ways of storing data: Entities (usually nodes), the Variables table, and "here's an SQL connection, enjoy!" That doesn't cut it for modern sites, unfortunately. What's more, everything was stored in a single SQL database which is part of what made configuration staging so difficult in Drupal 7; we had to build complex systems to extract the configuration out of arbitrary SQL tables, serialize it, and put it back in.

Not surprisingly, Drupal 8 has largely fixed that problem by tackling the different types of data that may need to be stored, each with their own dedicated APIs. Of course, moving from one big blob of data (aka, arbitrary SQL) to structured APIs requires changing the way you think about arbitrary data. So let's review the different ways to store stuff in Drupal 8, and where each of them is useful.


The simplest option is the Drupal State API. The State API is a simple key/value pool for values that are, by design, specific to a single Drupal install. Good examples here include the timestamp of the last cron run, generated optimization lookup tables (which should not get cleared as often as the cache does), the currently active theme, and so on. These are all values that are not user-provided configuration, and would make no sense to deploy from staging to production or vice versa.

State can store values of any type, as they will be serialized and unserialized automatically. However, not all object types can be serialized. In particular, any object that has a dependency on a service should never be serialized. Only serialize value objects.

Note that every read of a state value is a new hit against the underlying database. If you're loading multiple values out of state for some reason, use the getMultiple() method.

The state API is a single namespace, so be sure to namespace your state entry key names with your module name, like "mymodule.last_person_hugged".


The State API is itself just an abstraction layer on top of the Key/Value API. The Key/Value API allows the storing of any arbitrary serializable value, with the keys namespaced to a "collection". The "state" is simply one collection.

It's also possible to use your own collection, directly accessing the Key/Value API. However, if you're going to do that it's helpful to define your own class that composes the Key/Value factory service, much the same way that the State API does. At the moment there aren't many tools to quickly replicate that functionality, but the process is straightforward and the State class itself is readily copy-pasteable. Most of the non-trivial code in it is simply to cache loaded values so that the Key/Value store is not hit multiple times per request for the same value.


Content in Drupal 8 means the Entity API. Drupal Entities are much more rigidly structured than in an ORM like Doctrine. There are three layers to the Entity API, conceptually:

  1. Entity Types define different business logic for different objects. What that logic is varies on the Entity Type. Generally a new Entity Type involves writing a new PHP class. Examples includes Nodes, Users, Taxonomy Terms, Comments, and Custom Blocks.
  2. Entity Bundles are different configurations of the same Entity Type, with a different Field configuration. Creating one involves setting up configuration, which in (nearly) all cases involves an administrator pushing buttons. "page nodes", "article nodes", and "event nodes" are examples of different bundles of the "node" Entity Type.
  3. Fields are the smallest basic unit of Drupal content. A field is a single rich-value. Rather than "string" or "int" it is a value like "email address", "formatted text", or "telephone number". It can also be a reference to another entity. All entity objects can be viewed as a collection of Fields, each of which may be single- or multi-value. (As far as the code is concerned Fields are always multi-value, but may be configured to only bother storing one value.)

The key aspect of Content is that it is generally user-generated and of potentially infinite cardinality. (That is, there's no limit on how many entity records a user can create.) Unlike in previous Drupal versions, however, the Entity API is robust enough that it is reasonable to use for nearly all user-provided data rather than just a select few types.

If you want users to be able to enter data into the system, and there's no hard-coded low limit to how many entries they can make, Entities are your tool of choice. Building a custom entity is also much more viable than in past versions, so don't be afraid to define your own Entity Types. There's no need to just piggy-back on nodes anymore.

Content Entities are also translatable into different languages. The capability is baked into all Field types, making multi-lingual content a breeze.


The most important new data system in Drupal 8, though, is the Configuration system. The Configuration system replaces the variables table, the features module, half of the ctools module suite, and the myriad custom tables that various modules defined in previous versions with a single, coherent, robust way to store, manage, and deploy administrator-provided configuration.

That last part is key. The Configuration system is your go-to tool if:
1) Users on the production site should not be changing these values. If they should be changing values on production, you probably meant for it to be Content.
2) If you have a staging site, you will typically be editing on the staging site and then deploying to production en masse.
3) Affects the business rules of the module or site.

For the Drupal 7 users, pretty much anything for which you ever thought "this should really be in a Feature module" now belongs in Configuration.

The configuration system is modeled as a namespaced key-value store (although it does not use the Key/Value system internally, as the implementations are quite different). The keys are dot-delimited strings, and the values are specifically "Configuration objects". Config objects have get() and set() methods to manage properties on the object, among other features we won't go into here.

Most importantly, config objects can be safely serialized to YAML and unserialized from YAML. That's what differentiates the Configuration system from the other data storage systems: It's canonical form is not in SQL, but YAML that can be loaded into the system or exported from it. Modules can provide default configuration files in YAML, which will get imported into the site when they're installed. A site can also export some or all of its configuration files to a known directory on disk. That could be hundreds of files, but that's fine. Once in that directory the files can be easily checked into Git, checked out on another server, and imported from files back into config objects in Drupal. Configuration deployment: Solved!

You will also run across something called "Configuration Entities". This seemingly mixed concept is a way of providing CRUD behavior using the basic Entity API but backed by the Configuration API. Configuration Entities do not have Fields, but otherwise use essentially the same API. Configuration Entities are useful for cases where a user or administrator may be making multiple instances of a given configuration object. They're also the storage mechanism underlying Plugins.

Configuration objects are also translatable, which allows sites to make string value configuration available in the language of their users.


Tempstore is a bit of an odd duck of Drupal 8's data storage world. It's provided not by core but but the user module, and there's actually not one but two different tempstores: one private, one shared.

A tempstore is for data that needs to be persisted between requests without being saved back to the canonical storage (such as an entity or configuration object). If that sounds like PHP's native session handling, it should; the use case is very similar. The main difference is the shared tempstore is, as the name implies, shared between users, whereas sessions are, by design, not.

The quintessential (and original) example of that behavior is Views. A View is stored as a configuration entity. You don't want the View to be incrementally updated every time a single field is changed, though; you want to make a series of changes and then save the changes all at once. Instead, a temporary copy of the View config entity is saved to the shared tempstore every time a setting is changed. That allows changes to survive a browser restart, or a lunch break, without affecting the live copy of the View. It can even be picked up by another user if the first user gets delayed or goes on vacation and forgets to hit save. When the View is saved then the temporary copy is written back to the configuration system and the temporary version cleared.

The private tempstore works the same way, but its values are not shared between users. That makes it more appropriate for wizard-type interfaces or multi-step forms.

Both tempstores are backed by the Key/Value API internally. The Key/Value API offers a variant called "expirable", where values will get cleared out eventually, say if a View is left mid-edit for several days, which tempstore uses. In practice, unless you're building complex multi-step UIs you won't run into tempstore very often.


And finally, we have the cache system. Drupal 8's cache system is actually far more robust than its predecessors, and is heavily leveraged by the rendering system. That's a topic for another time, though. For now, we're just looking at cases where you'll use it directly.

The general rule for caching something is "is it more expensive to compute this value than to look up an old version from the database?" Database calls are not cheap. (Even if not using SQL, you're still making some kind of I/O call which is the most expensive thing you can do in a program). Don't cache something in the cache system until and unless you know it's going to be helpful to do so. Often, that is other I/O intensive calls, like a web service call or a complex set of queries.

Another important rule for caching is that it should be for performance only. If the cache is wiped clean of all data, your code should still run. It may run slower, the site may run too slowly to be usable, but no irreplaceable data has been lost. Never, ever store data in the cache that you cannot recreate on-demand if needed. Similarly, don't store generated and regeneratable data elsewhere. That belongs in the cache.

What to choose?

With so many options, how do you know where to put your data? While the lines are not always crystal clear, the following pointers should cover most cases.

Is it purely a performance optimization, and the data can be regenerated if needed? If yes, Cache.

Should it be configured on staging and pushed to production? If yes, use the Configuration system. If there will be an arbitrary number of them, use Config Entities.

Was it in the variables table before, but not something to push from staging to production? If so, it likely belongs in State.

Is it user-generated content on the live site? Most likely it should be a Content Entity.


Shitiz Gag's Blog: [GSoC 2015: Hawk Authentication] Week 12: Unit testing and finishing the modules

di, 2015/08/11 - 8:03pm

GSoC is wrapping up in another two weeks, that means it’s time to start wrapping up the module and make it in a shippable state. For that, I have started working on unit tests as well as documentation.

Unit Tests

Unit tests help maintain a project in long term as they can help automatically detect if a change is made by someone in future doesn’t break some other part of the module, for example a change in the header library is to add some features that could result in breaking of an obscure client function that has been there since version 0.1. If the function has unit test coverage, it would get caught before the module gets released to the general public and would prevent some hassle.

My goal is to cover as many test cases as possible, accounting for general and exceptional cases. So far I have done basic Hawk Auth tests and nonce validation tests, I’ll be working on unit testing permissions, security and validation. I had to spend some time in order to figure out how Drupal does unit testing as that is something I’m not really familiar with and I haven’t done a lot of unit testing before so this was a good opportunity for me to pick up and implement some test cases to become more familiar with it.

A wall I ran into was when I was trying to use existing routes implemented by system module’s test submodule router_test in order to test whether Hawk Authentication was working. After a couple hours of tinkering it occurred to be that the route I was using was specifically mentioning basic_auth. After spending a few hours on this and realising that I was trying to get around something which was intentionally the way it is. I implemented my own custom module just for testing. The module provides a few basic routes in order to emulate controllers while the unit tests run. For example, a route simply shows the current logged in user’s username, this is to ensure Drupal is correctly identifying users via Hawk. As I implement more tests, I’ll implement more controllers to help them.


Since my blog has been accepted into Drupal Planet last week, I’ve started working on writing a few posts to recap the GSoC journey of mine as well as provide introductions to Hawk, Hawk Auth module and the project itself. Hopefully these articles will help people understand the protocol and the project better. I’m trying to get a few posts out this week and the next week.

For now that is all, I’ll continue with unit testing and documentation until the next week.

Thank you!


Michael J. Ross: Drupal Taxonomy Tips and Tools

di, 2015/08/11 - 5:02pm
Website Adaptability, One Tag at a Time


A shorter version of this article was published in the print magazine Drupal Watchdog, Volume 5 Issue 1, Spring/Summer 2015, on pages 32-33, by Tag1 Publishing. The magazine was distributed at Drupalcon Los Angeles, 2015-05-11. The article was also published on their website.

When comparing the most commonly-used content management frameworks, web developers typically cite Drupal's robust support for taxonomies as one of its leading strengths. This should come as no surprise to anyone with even minimal experience in using taxonomy vocabularies and their terms in designing and building new websites, largely because they provide a proven way to categorize and make findable the content of any website, with relatively little effort.

Specifically, every piece of content can be tagged with zero or more terms defined within an unlimited number of vocabularies, and these tags can be used in myriad ways for grouping and sorting that content. In the case of a taxonomy term reference used by a view of one or more content types, the sort order and filtering can be specified by the developer using the Views interface or within a custom module, or that functionality can be exposed to the end-user, giving her even greater control over what data is displayed.

The judicious use of taxonomies can be a powerful component of any content strategy that is intended to grow and change in the future as a website's owners and users demand new ways to organize the site's content so as to minimize the time and steps required to find specific content. This is true not just for on-page site visitors, but also for people consuming that content in RSS aggregators for whom only some of the content is of interest — for example, everything published in a particular category or during a certain month.

In this examination of some best practices, techniques, and useful contrib modules associated with taxonomies, it is assumed that the reader has a basic understanding of vocabularies and terms.

Select Field Versus Taxonomy

When adding to a content type a new field that will contain a value from a predefined list of possibilities, you have the option of utilizing a field of type "List (text)" (or one of the two numeric variants of "List"), and setting the Allowed values list on the field settings page. Or, you can employ a taxonomy term reference, which, as the name implies, refers to a term in the taxonomy vocabulary specified when creating the field. There are no absolute rules as to which of the two methods are best, but here are some sensible guidelines:

  • Perhaps you want the client to be able to add, change, or remove the allowed values of the field in question, without risking the dangers of permitting the client — and having to explain how — to edit that field settings in the content type. Then taxonomy is definitely the right choice. Even if you will likely never alter the list — for example, the names of Canadian provinces — then a select list should work fine as the field type.
  • If tag modification is not an issue, then consider whether or not the new field is needed for the content type to make sense, for example, a state or province name in a postal address. In such cases, a list field may be called for. Conversely, if the field simply adds additional information independent of the content's identity, then a term reference would be optimal, as it is more loosely coupled from the other fields in the content type. For instance, an article filed under a "Technology" category is still an article if you were to remove the category association, so taxonomy would be a good fit.
  • If database performance is an issue, then a list field would make more sense than a taxonomy term reference, because the latter involves additional table joins.
  • Finally, if the field needs to support hierarchies or focused RSS feeds, then you should use a taxonomy field. (A summary of the possible types of hierarchies follows.)
Less Taxing Taxonomies

While the Taxonomy module built into Drupal 7 core makes it possible to build an unlimited number of useful vocabularies, that building process can be quite tedious. Do you have hundreds of country names to enter, and dread the clicking and pasting? Fortunately, there are several contrib modules that can be tremendously helpful in reducing the time and effort required.

As its name suggests, Taxonomy Manager provides far more control than the core module for working with vocabularies, including the addition and deletion of multiple terms in a single step. For instance, to begin populating a newly-created vocabulary with the names of various colors (instead of countries, for brevity's sake here), the single operation would require no more effort than pasting the list of names into a text area, one per line.

Figure 1. Taxonomy Manager adding terms

The terms are then displayed as a list.

Figure 2. Taxonomy Manager terms added

Moreover, the terms can be manipulated by selecting one or more of them and using the UI buttons for moving or deleting them, or performing other actions. Although a move operation requires multiple clicks instead of a single drag-and-drop, multiple selected terms can be moved as a group.

Figure 3. Taxonomy Manager moving terms

Yet even greater power is available when working with hierarchical taxonomies. For such vocabularies, the module displays its terms in a tree format.

Figure 4. Taxonomy Manager terms hierarchy

Taxonomy Manager can export terms as a CSV file, but not import them. For that, consider the aptly-named Taxonomy CSV Import/Export module, which allows an administrator to import or export taxonomy terms in a CSV file or as text pasted from the system clipboard. It also supports internationalization and the Drush utility. You are guided through the import process through six steps. For either import source, hierarchy is indicated using commas, such as:

term 1 ,term 1.1 ,term 1.2 ,,term 1.2.1 ,,term 1.2.2 term 2 ,term 2.1 ,,term 2.1.1 ,,term 2.1.2 ,term 2.2 term 3

The module does a good job of explaining what steps it has performed, including automatically creating the import vocabulary if no existing vocabulary was specified prior to import.

Figure 5. Taxonomy CSV message

The final result is, as intended, hierarchical.

Figure 6. Taxonomy CSV imported vocabulary

You may benefit from a few lessons learned from my own experience: This module will take any earlier instances in the file of each repeated child term, and move it to the bottom of its list of child terms, when it encounters a later instance. To minimize confusion long after you have set up a website's vocabularies, if you allow the import process to name the new vocabulary, you should later change the machine-readable name to match your vocabulary name. This module handles several vocabulary structures: flat (no parent), tree (single parent), and polyhierarchy (multiple parents). Avoid that last one if you ever wish to be able to reorder terms, and if you wish to retain your sanity.

These are just two of the many taxonomy-related modules that have been contributed by the community as a supplement to the core functionality. Yet they can be effective components in your toolset, as you learn first-hand how the extensive use of taxonomies for organizing, displaying, and managing data can make a website extremely adaptable to future needs. It also can serve as a key component of a durable information architecture for any website.

Copyright © 2015 Michael J. Ross. All rights reserved.

Categorieën: Featured Case Studies:

di, 2015/08/11 - 4:42pm
Completed Drupal site or project URL:

About Acronis

The rise of virtualization, the explosion of data creation and the opportunities in Cloud services offer are bringing new challenges to maintaining effective backup and disaster recovery programs for critical data.

Acronis helps users securely migrate, protect and recover critical data wherever it resides in their physical, virtual or cloud environments. With the Unified Platform and new generation technology, its innovative solutions are designed to ease the management burden and reduce total cost of ownership while improving recovery time objectives.

  • Over 5,000,000 individual customers and over 500,000 business customers in a broad range of industries have chosen Acronis to protect their business continuity.
  • Strong Acronis partners ecosystem reaches customers in more than 145 countries worldwide.
  • Acronis offer 24/7 assistance to their customers worldwide through their award-winning customer support centres.

Acronis products have won many different awards and are well-known as secure, solid and stable disk backup solutions worldwide. And now ADCI Solutions are proud to announce that we have built a website to popularize and sell these outstanding applications.

Key modules/theme/distribution used: Display SuiteFeaturesContextWorkbenchWorkbench ModerationViewsWysiwygTranslation Management ToolNodeblockMeta tags quickLanguage HierarchyCorresponding node referencesCoderOrganizations involved: ADCI Solutions

ERPAL: Creating custom commerce products and line item types

di, 2015/08/11 - 3:30pm

Flexibility and integration are the most important factors when developing E-commerce, CRM or other kind of business applications with Drupal.
As our main goal with ERPAL Platform is to provide a flexible Drupal distribution for building every kind of business application with Drupal, for the last few months we've focused on commerce components. Drupal Commerce is one of ERPAL Platform’s core components providing product, price and order features. The challenge was to pre-configure the integration of such components as CRM contacts, quotes, orders, invoices and the business logic to connect them. At the same time, ERPAL Platform needs to be as flexible as possible. In this blog post we want to present a detailed example about how to create custom product types with related custom line item types and show how to connect those types and their fields with one another.
Let’s imagine a t-shirt online store where we want to set up a product type that lets the user choose between different colors and sizes of the shirts offered in the shop. We’ll go through the configuration process to show you the feature using an example of ERPAL Platform with a single line of code.

1) Creating a new product type

It takes only a few steps to create a new commerce product type.

  1. Navigate to: Store » Products » Product types » Add product type
    • /admin/commerce/products/types/add
  2. Insert a name for your product type, e.g. "T-Shirt"
  3. Click the "Save and add fields" button at the very end of the form
  4. Add two new text fields named "Color" and "Size"
    • It would be beneficial to adjust the field names to field_shirt_color and field_shirt_size, to prevent inconveniences in the future
    • You could just as well use taxonomy terms or other field types instead of text fields, but we'll take the easy route for now
  5. And save it!


2) Create a new line item type

In this step we create a new line item type that’s related to the product type we created in the previous step. The line item type helps us to display a product during the order process, in the cart or in a quote, order or invoice.

  1. Go to: Store » Configuration » Line item types » Add a product line item type
    • /admin/commerce/config/line-items/add-product-line-item-type
  2. Insert a name for your new line item type; we'll again use "T-Shirt", as the line item should match our new product type
  3. Add the existing fields field_shirt_color and field_shirt_size (in our case the same fields as for the product type)
  4. Save that line item type!


3) Connect the product type with line item type

Now, as we create our new product type and line item type, we need to connect both entity types and map their fields.

  1. Navigate to Store » Configuration » Order settings » Manage fields and edit the "line items" widget type
    • /admin/commerce/config/order/fields/commerce_line_items/widget-type
  2. The widget type should be set to "Dynamic line item widget"
  3. Adjust the "Settings for T-Shirts line item type" (a fieldset within the dynamic line item widget fieldset)
    1. Select the correct "Product type", in our case "T-Shirt"
    2. Set commerce_unit_price to commerce_price
    3. Set field_shirt_color to field_shirt_color
    4. And finally field_shirt_size to field_shirt_size
  4. Hit "Continue" and "Save"

As mentioned above, you can use your line item types in your quotes and invoices. You’ll find their configuration at: Store » Configuration » Order types » Invoice / Quote. /admin/commerce/config/order-types

4) Create a product and test it

Now you can check whether the setup works. If you add a new product to a cart, a quote, an order or an invoice, the line item that’s used to show the selected product will change dynamically with the selected product, showing the correct fields. As you mapped the fields of the line item type to the related product type, you can select the product attributes after the product has been added. You can test the settings as follows:

  1. Go to "Products" in the ERPAL menu and hit the local action (the button on top) "Add a product"
    • /product/add/t-shirt
    • Alternatively, go to Store » Products » Add a product » Create T-Shirt
    • /admin/commerce/products/add/t-shirt or via
    • /order/add
  2. As you can see, our two new fields are added to the form dynamically. Now insert all data. Remember the SKU value!
  3. When creating an order, insert the SKU into the product autocomplete field and select the recently created product
    • Now you should see that the fields have adjusted to the corresponding line item type and the values of the product's fields are copied.



    Adding a custom product type is not much more complicated than adding a new content type to a Drupal site. It’s important to create not just the product type but also a line item type and connect them. All in all, just three small steps without a single line of code. The module that provides these features is already included and pre-configured in ERPAL Platform. It’s also available as separate modules on in case you want to use it in an existing project: it’s the dynamic widget for commerce line item field module.

    For more how-tos and best practises related to ERPAL Platform, please read our docs.


    Commerce Guys: The Apple Store discovers the Power of Content

    di, 2015/08/11 - 3:19pm
    At Commerce Guys we know the value of content-driven commerce. It’s the reason our founders built Drupal Commerce, to enable the seamless blending of content management and robust commerce within a single software platform. We are thrilled to see more and more people talking about this continued transformation in the eCommerce market.

    On Friday, Apple Inc., one of the largest companies in the world, announced what they see as a major shift in their eCommerce operations via a post on their website titled "A new way to learn and shop on": Content and Commerce are two sides to the same coin. Without Content, no one knows what you're selling. Without Commerce, how does your website help your business grow? A powerful platform that allows for seamless blending of the two can make a business grow by strengthening its ability to attract new customers and effortlessly convert browsers into buyers.

    Most eCommerce platforms do a great job at transactional eCommerce, but in today's ever changing online landscape, a business needs more than just a checkout experience to attract and engage prospects and turn them into customers. A flexible framework like Drupal Commerce allows companies to build a web experience with a single software that controls both sides of the coin. Content that engages and attracts customers and feature rich eCommerce which improves conversion rates.

    As Apple stated “Now you can shop everywhere across and purchase products right where you learn about them.” Now that Apple has seen the value of blending rich product information with eCommerce, something that Commerce Guys already embraced, perhaps you should consider making similar improvements to your eCommerce strategy by taking a look at Drupal Commerce.

    Drupalize.Me: Configure Search API Solr to Use Stopwords When Indexing Content

    di, 2015/08/11 - 3:02pm

    Most written text has a lot of functional words, like "a", "the", or "is" which are important to the person reading the content as they help it flow in a cohesive manner, but aren't necessary as important to someone searching the content of your site. In this tutorial we'll look at ways to ignore those words in our search index.


    Deeson: Executing Drupal Behat tests on Vagrant from within PHPStorm

    di, 2015/08/11 - 10:00am

    If you've made it past the title, congratulations! There are lots of concepts discussed in this article, I'll mention Vagrant and Behat very briefly, but won't go into details as I'll provide better places to find information on getting started with those tools. This article is mainly for people who use Vagrant for Drupal development, have at least some idea as to how to make a Behat test run on their Vagrant box and want to run those tests from within the PHPStorm IDE.


    Vagrant is a tool for creating consistent and portable development environments. The intention is to give all your developers the tools they need to do their job in a single package such as a database and web server. There is work involved in initially setting it up, but once you have a workable receipe you can pass that round to all your developers so they have the consistent development environment. All the tools run from within a Virtual Box, a complete operating system which can be made to be much more like the production environment.

    Some helpful people have already done most of the hard work for you so you can start with what they have already done. Popular choices are VLAD and VDD. At Deeson, we tooled the base VDD recipe and added to it to build our own environment which uses a 64 bit version of Ubuntu Trusty64 as well as solr, nginx and a load of other tools. You can find Deeson's VDD recipe at

    Drupal Behat Tests with Drupalextension

    Behat is a PHP tool for creating and running functional tests and, potentially, engaging in something called behaviour driven development (BDD). A functional test describes some function of the finished website. This differs from unit tests, in that a unit test should test some small piece of the code in isolation, whereas a functional test will test a complete path through the system potentially touching many parts of the codebase.

    If you are using the Deeson version of VDD linked above then you already have a globally installed copy of Behat. If you are using your own Vagrant box then you will need to add Behat and the Drupal extension to it. The instructions for installing Behat and the Drupalextension can be found at

    System configuration

    I am assuming you have followed the instruction on the Drupalextension site linked above to get a Behat test running on the command line on your Vagrant box. For the rest of the article, I will also assume the following variables, you should subsitute these with you own values where appropriate:

    • Project root on the Vagrant box is at /var/www/vhosts/
    • Drupal docroot is within the project root on the Vagrant box at /var/www/vhosts/
    • Behat tests are on the Vagrant box at /var/www/vhosts/ with the behat.yml configuration file at /var/www/vhosts/
    • The project root is also on your local computer at ~/Sites/ such that the drupal docroot is therefore at ~/Sites/ (Windows users, your milage may vary)
    • Your VagrantFile is located on your local computer at ~/Applications/vdd. This is the directory you checked out VDD or the Deeson equivalent if thats what you are using for Vagrant. The VagrantFile is a file in that directory which describes how your Vagrant is configured.
    PHPStorm Vagrant Configuration

    With the scene set we finally arrive at how to configure your PHPStorm. Within PHPStorm, we want all the tests to execute when we press the play button. Because the tests are running on the remote Vagrant box we need to setup a remote PHP interpreter within PHPStorm and tell PHPStorm this is accessible via Vagrant.

    1. PHPStorm -> Preferences
    2. Tools -> Vagrant

    In the configuration for Vagrant you should set the path to your VagrantFile. This file describes your Vagrant configuration and would be in the folder you checked out VDD or the Deeson equivalent into. My settings are shown below.

    PHPStorm PHP Interpreter Configuration

    Next you need to tell PHPStorm that PHP is running on the Vagrant instance and can be used to run code with.

    1. PHPStorm -> Preferences
    2. Languages and Frameworks -> PHP
    3. On the Interpreter line click the triple dots button to open the Interpreters configuration screen. 
    4. Click the plus (top left) to add a new interpreter
    5. Give it a name (e.g. Vagrant PHP)
    6. Choose Vagrant
    7. Specify the locationt to your VagrantFile (again)
    8. Specify the location of PHP on the Vagrant box (e.g. /usr/bin/php). Note that clicking the Reload button here may make PHPStorm work it out for you.

    VDD users may get an error about unmatched paths when configuring the Interpreter. You are using a dynamically mounting VagrantFile, and PHPStorm is unable to work out how you project directory maps from your local computer to the Vagrant box. You will need to specify the mappings on a per project basis in your VagrantFile as follows.

    Under Vagrant.configure("2") do |config| add the following lines, remebering to replace the local path to the correct path for your system. You'll note that this code will never get run when the VagrantFile is properly used as it is inside an impossible block of code. However, it provides the information PHPStorm needs to work out the mappings from local computer to Vagrant box paths for the project.

    if 1 > 2 config.vm.synced_folder "/Users/johnennew/Sites/", "/var/www/vhosts/" end Configuring Behat for PHPStorm
    1. PHPStorm -> Preferences
    2. Languages & Frameworks -> PHP -> Behat
    3. Click the plus (top left)
    4. Choose the Vagrant PHP Intepreter
    5. Specify where behat executable is located within the Vagrant box. If you followed the instructions for drupalextension to install Behat globally then this will be /usr/local/bin/behat
    6. Press the reload button (two circular arrows) to have PHPStorm verify the path to Behat is correct
    7. Tick Default configuration file
    8. Find your behat.yml file in your project locally (for me this is ~/Sites/
    Configuring PHPStorm Run Configuration

    We are now ready to configure the run mode in PHPStorm so that the green play button becomes available and pressing it executes the tests

    1. Run -> Edit configurations ...
    2. Click the plus (top left) then Behat
    3. Name: Behat tests
    4. Test scope: Defined in configuration file

    Press the green play button in PHPStorm and in theory your tests will now be executed on the Vagrant box and the results sent to PHPStorm.

    If you would like to just test part of the suite of tests you can do so by tagging the tests and then creating a new Run configuration which specifies which tags to run. Lets say you have tagged some of your scenarios as @justthis

    1. Run -> Edit configurations...
    2. Press the plus symbol (top left) to add a new configuration and choose Behat
    3. Name: Just this
    4. Test scope: Defined in the configuration file
    5. Test runner options: --tags="justthis"
    6. Click OK

    Now you have a dropdown choice next to the play button in PHPStorm to choose either Behat tests or Just this. Choose Just this and press play and only the scenarios tagged @justthis will be run.

    Happy testing!


    PreviousNext: Over the Waterfall: The future is Agile

    di, 2015/08/11 - 9:44am

    I recently attained the Certified Scrum Professional (CSP) certification and found the process a good opportunity to reflect on what led me to Scrum. It was also a chance to take pause and consider our  industry approach to project management.


    Wunderkraut blog: Stylus with Gulp: a fantastically fast front-end workflow.

    di, 2015/08/11 - 9:09am

    Modern CSS preprocessors are hardly a surprise to anybody these days, SASS and LESS have polarized the developer ecosystem and workflow tools like Grunt and Gulp have become welcome additions to both camps. Not so welcome additions to this new reality are compile times that in complex projects can stretch into seconds, sometimes in the double digits, and multiple dependency trees. How does a compile time of milliseconds with exactly one dependency sound? Intrigued? Then keep reading!

    In this post we'll be taking a look at one solution to the aforementioned problem: slow compile times and multiple dependencies.

    First, lets take a look at the most obious solution to speeding things up: eliminating layers in our workflow stack. Say, we use Grunt (who doesn't!) or even better, Gulp (awesome!). What dependency is required to run those awesome things? Node.js, of course. Now, wouldn't it be great if our preprocessor also ran on Node, and maybe its extensions and packages too? Never fear, Stylus is here!

    Stylus is the underdog and player number three in what at first glance appears to be a two-horse race.

    While Stylus does not have as large a collection of extensions as the other two, the ones that are available are top-notch and cover all the bases. There's the nib library for all things CSS3, Rupture for media query handling, and an absolutely fantastic Jeet for a grid system amongs others.

    Stylus won't strongarm you into any kind of a specific syntax style. You can use standard CSS syntax on one extreme, or white-space delimited syntax on the other and everything in between. With great power, of course, comes great responsibility, so unless you enforce a certain discipline, there is potential for some not-so-pretty code.

    Next thing, Grunt or Gulp? If neither of those words evoke a strong sense of tribal belonging, then go with Gulp, otherwise... look into Gulp and see if you can live with it.  We'll be setting up a killer workflow based on Gulp right here.

    So lets get right down to business: lets set up a real-world Drupal theme development environment that you'll be able to use right away.

    tl;dr scroll down to the bottom and download a package that contains everything described here, otherwise:

    1. Remember that single dependency? What does it mean exactly? It means that there is only one file to maintain for versioning all our packages and tools: node's package.json, here is mine: { "name": "project_name", "version": "0.0.0", "dependencies": { "stylus": "^0.52.0", "stylus-type-utils": "0.0.3" }, "devDependencies": { "bower": "^1.4.1", "browser-sync": "^2.8.1", "gulp": "^3.9.0", "gulp-autoprefixer": "^2.3.1", "gulp-concat": "^2.6.0", "gulp-jshint": "^1.11.2", "gulp-rename": "^1.2.2", "gulp-sourcemaps": "^1.5.2", "gulp-strip-debug": "^1.0.2", "gulp-stylus": "^2.0.4", "gulp-uglify": "^1.2.0", "jeet": "^6.1.2", "jshint-stylish": "^2.0.1", "nib": "^1.1.0", "rupture": "^0.6.1", "yargs": "^3.18.0" }, "scripts": { "postinstall": "find node_modules/ -name '*.info' -type f -delete" } } Place this in your theme's root (name it package.json).
    2. Configure Gulp: gulpfile.js, here is mine: 'use strict'; var gulp = require('gulp'); var prefix = require('gulp-autoprefixer'); var uglify = require('gulp-uglify'); var jshint = require('gulp-jshint'); var concat = require('gulp-concat'); var stylish = require('jshint-stylish'); var rename = require('gulp-rename'); var stripDebug = require('gulp-strip-debug'); var browserSync = require('browser-sync').create(); var stylus = require('gulp-stylus'); var sourcemaps = require('gulp-sourcemaps'); var reload = browserSync.reload; var args = require('yargs').argv; var nib = require('nib'); var serverUrl = args.proxy; if (!serverUrl) { serverUrl = ''; } // Confingure our directories var paths = { js: 'js/**/*.js', jsDest: 'aggregated-js', css: 'css', styles: 'styles', ds: 'ds_layouts', panels: 'panel_layouts', img: 'img', }; ////////////////////////////// // Begin Script Tasks ////////////////////////////// gulp.task('lint', function () { return gulp.src([ paths.js ]) .pipe(jshint()) .pipe(jshint.reporter(stylish)) }); gulp.task('scripts', function() { return gulp.src(paths.js) // Concatenate everything within the JavaScript folder. .pipe(concat('scripts.js')) .pipe(gulp.dest(paths.jsDest)) .pipe(rename('scripts.min.js')) // Strip all debugger code out. .pipe(stripDebug()) // Minify the JavaScript. .pipe(uglify()) .pipe(gulp.dest(paths.jsDest)); }); ////////////////////////////// // Stylus Tasks ////////////////////////////// gulp.task('styles', function () { gulp.src(paths.styles + '/*.styl') .pipe(sourcemaps.init()) .pipe(stylus({ paths: ['node_modules', 'styles/globals'], import: ['jeet/stylus/jeet', 'stylus-type-utils', 'nib', 'rupture/rupture', 'variables', 'mixins'], use: [nib()], 'include css': true })) .pipe(sourcemaps.write('.')) .pipe(gulp.dest(paths.css)) .pipe(; }); gulp.task('ds', function () { gulp.src(paths.ds + '/**/*.styl') .pipe(sourcemaps.init()) .pipe(stylus({ paths: ['node_modules', 'styles/globals'], import: ['jeet/stylus/jeet', 'stylus-type-utils', 'nib', 'rupture/rupture', 'variables', 'mixins'], use: [nib()] })) .pipe(sourcemaps.write('.')) .pipe(gulp.dest(paths.ds)) .pipe(; }); gulp.task('panels', function () { gulp.src(paths.panels + '/**/*.styl') .pipe(sourcemaps.init()) .pipe(stylus({ paths: ['node_modules', 'styles/globals'], import: ['jeet/stylus/jeet', 'stylus-type-utils', 'nib', 'rupture/rupture', 'variables', 'mixins'], use: [nib()] })) .pipe(sourcemaps.write('.')) .pipe(gulp.dest(paths.panels)) .pipe(; }); ////////////////////////////// // Autoprefixer Tasks ////////////////////////////// gulp.task('prefix', function () { gulp.src(paths.css + '/*.css') .pipe(prefix(["last 8 version", "> 1%", "ie 8"])) .pipe(gulp.dest(paths.css)); }); ////////////////////////////// // Watch ////////////////////////////// gulp.task('watch', function () {, ['lint', 'scripts']); + '/**/*.styl', ['styles']); + '/**/*.styl', ['ds']); + '/**/*.styl', ['panels']); + '/globals/**/*.styl', ['styles', 'ds', 'panels']); }); ////////////////////////////// // BrowserSync Task ////////////////////////////// gulp.task('browserSync', function () { browserSync.init({ proxy: serverUrl }); }); ////////////////////////////// // Server Tasks ////////////////////////////// gulp.task('default', ['scripts', 'watch', 'prefix']); gulp.task('serve', ['scripts', 'watch', 'prefix', 'browserSync']) Place it in your theme's root, name it gulpfile.js

    3. Now, the gulpfile.js above expects things to be in certain places, let's not disappoint it!
      Create a file structure like this: (if you download the package at the bottom of the page, you'll have it all set)

      theme_name |\ | ds_layouts |\ | panel_layouts |\ | aggregated_js |\ | js |\ | css |\ | img |\ | styles | |\ | | globals | |\ | | modules | \ | includes | style.styl \

      You'll notice that in this case I'm using a couple of assumptions.

      1. You'll be using Display Suite (because you should!)
      2. You'll be using Panels (because why not)
      While Display Suite, once enabled, will look for a folder named ds_layouts in your theme, Panels needs to be informed of our panel_layouts directory. To do so, add this line somewhere near the bottom of your file:  plugins[panels][layouts] = panel_layouts

      The rest of the directory structure is as follows:
      1. aggregated_js
        Gulp will lint, concatenate and uglify whatever scripts it finds in the js folder (or its subfolders) into a neat little file called scripts.min.js and place that here.
      2. js
        See point 1.
      3. css
        Destination directory for compiled .styl files and sourcemaps. The Gulp workflow will autoprefix the compiled files to be compatible with browser versions as specified in the gulp file (at the moment, 8 versions back from current, see prefix task definition in the gulpfile.js)
      4. img
        We'll keep theme image files here.
      5. styles
        Sources for stylus.

        Files with the extension .styl found immediately inside the styles directory will result in their respective compiled equivalents in CSS form in the css directory, anything in the globals subdirectory will be included during compile time with any .styl file (even the files in ds_layouts and panels_layouts! Do you see where this is going?) so naturally it's a good spot to put our variable definitions, mixins, extendables and such things. Modules subdirectory contains partials to be included in the main file(s) (in our case, style.styl), they won't be included automatically, so style.styl file must contain the following at its beginning (and ideally, that would be all it contains):

        @import 'includes/*.css' @import 'modules/**/*.styl' Includes subdirectory will have any pre-compiled css files (such as html5reset.css) which will be rolled as the first thing into compiled css. You can organize the structure in the modules subdirectory whichever way you please, incuding creating your own subdirectories for ease of use or reading, they will all be automatically incuded at compile time.
    4. Now that we've done the preparatory work, how do we actually make this whole thing work?
      1. From the theme root directory run: npm install (assuming you have Node.js already installed on your system)
      2. From the theme root, run: gulp
        Gulp will now listen for changes to your js or styl files and promptly compile them into css and minimized js for you! Congratulations!
      3. Additionally, you could take advantage of the awesome BrowserSync and run: gulp serve
        This will do the same as point number 2 above, but will also run a BrowserSync server which will reload the browsers (and other devices connected to the site) upon detecting a change to your CSS or JS files and will sync events on page (including scrolling and hovering!). By default, it will proxy a default site found at "" and re-broadcast it, if you will, at localhost:3000. You can change the default proxy by modifyling relevant line of gulpfile.js (search for, it is there only once), or you can specify your own proxy like this: gulp serve
      4. What about those ds_layouts and panel_layouts directories, what do those have to do with stylus you ask? They are there to make your life easier when working with ds and panels templates. Both of those have an option to include css file with the template, and if you were to place a stylus file with the appropriate filename in the template subdirectory, Gulp will compile that file using the global includes (so your mixins, variables, your grid and breakpoint will all be available to you!), and place it in the same place as source for you to include in the template! This will make the styles defined there availabe to both front, and back ends. You'll be able to view the layout of your page in its near compelted form when working with page manager, for example.

    If you've managed to follow along and everthing worked, wonderful! I've used node version 0.12.7 with latest available versions of all node packages to write this setup. If something does not work, download and extract the package below. It is a barebones Drupal theme ready to be set as a subtheme of an existing theme or act as standalone. It is also possible that Gulp wants to be installed globally, in that case, simply run npm install -g gulp from the theme root.


    InternetDevels: Using PDF on Your Drupal Website

    di, 2015/08/11 - 8:55am

    Drupal web development is at its peak so you can get a cutting-edge website by hiring a great Drupal team. However, if you want to try and build a Drupal website by yourself, we hope some tips from our guest blogger Jack Dawson, founder of Big Drop Inc., will be useful to you. So let us give him the floor.

    Read more

    DrupalCon News: Session Spotlight: Dries is requesting your feedback

    di, 2015/08/11 - 7:00am

    After four years in the making, Drupal 8 is right around the corner and Dries’ Retrospective at DrupalCon Barcelona will be dedicated to looking back at what we did and how we did it. With countless new features and improvements, getting Drupal 8 ready for release has been a huge community effort, and in his session, Dries would like to highlight feedback about the process in his Core Conversations talk.


    Tech Rendezvous: GSoC2015 Week eleven and testing PDF

    di, 2015/08/11 - 2:00am

    Chen Hui Jing: Drupal 101: Getting started with Drupal 7 theming

    di, 2015/08/11 - 2:00am

    With Drupal 8 just around the corner, it may seem odd that I would write a post about Drupal 7 theming, but I figured it would take some time for Drupal 8 to really become mainstream. Also, when I do write that Drupal 8 theming post (coming soon), we can do some one to one comparisons on the things that have changed. Trust me, there are a lot of differences between the two.

    A theme is like the skin for your website. Drupal 7 theming may seem complicated at first. Peeking into a theme folder reveals a bunch of folders littered with PHP files, stylesheets and who knows what else. The easiest way to wrap your head around things is...


    Steve Purkiss: What is Drupal?

    di, 2015/08/11 - 1:08am
    Tuesday, 11th August 2015What is Drupal?

    Drupal is people. Drupal is figuring out people. Drupal is figuring out how to make things better. Drupal is about feeding yourself and your family. Drupal is about feeding other people's families. Drupal is about going to places you'd never considered going to. Drupal is about laying in the lake and watching the stars at night. Drupal is about making money for your business. Drupal is about making things easier. Drupal is about accessiblity for all. Drupal is about opportunity for all. Drupal will tell you what you need to know. Drupal is there for you to tell and show. Drupal is the push and the struggle. Drupal is the hook. Drupal is about taking those moments to really get your teeth into something you're passionate about and feel like you're maybe making a difference. Drupal is about escapism. Drupal is firing up the laptop and tethering before you get on the plane so you can git clone the latest dev release to take a look through the code until you're sleepy just to show off a bit more Drupal to fellow passengers who may take a glance but also learn something at the time. Drupal is about sharing your costs. Drupal is there to learn how to share. Drupal is there to provide a path to follow. Drupal is about sharing your thoughts and visions. Drupal is finding out where the line is when you didn't even know there was a line. Drupal is finding out the magic of everyone. Drupal is about survival. Drupal is tolerance. Drupal is about sustainability. Drupal is opportunity for all. Drupal is forcing you to face up to your conditions. Drupal is understanding. Drupal is a battle, an upheal struggle. Drupal is simple. Drupal is about sharing. Drupal is about caring. Drupal is hugging. Drupal is your voice. Drupal is special. You are special. 

    Drupal is your True Pal.


    tags: Drupal PlanetPlanet DrupalWhat is Drupaldrupal

    Red Crackle: Creating the simplest headless Drupal 7 site

    ma, 2015/08/10 - 10:25pm
    In What is headless Drupal post, you learned what exactly is headless Drupal. In this post, you will create the simplest headless Drupal application possible in less than 15 minutes. By the end of this post, you will have a simple HTML page. On loading this page, JS will send a request to Drupal. Drupal will generate a random number and send it back to the JS. JS will render it on the HTML page.

    Four Kitchens: REST Easy Part 2: Sub Property Boogaloo

    ma, 2015/08/10 - 10:10pm

    This week we’ll continue where we left off after doing the ground work of creating a basic endpoint with the RESTful Drupal module. We skipped one crucial part: the body field. This week’s installment will cover our missing field, which requires extra care when used within a RESTful endpoint.


    Promet Source: Feature Branch Workflow the Promet Way

    ma, 2015/08/10 - 9:50pm

    When you’re wrangling a slightly larger team of devs as we do here at Promet, the importance of strict naming conventions becomes apparent pretty quickly. Take the commonly referenced Git workflow from Victor Driessen, for example.

    Categorieën: Happy birthday to me and Devel form debug module to you all

    ma, 2015/08/10 - 8:06pm
    I’m turning 32 today. People love birthdays, to me it’s just another line number in a messed stack trace output (philosophy mode enabled).   Two years ago I released a drupal module called Get form id (deprecated from now on) that does one small task - it tells you any form's id ...

    Read now