Sunday, November 26, 2017

Buffered logger in Drupal 8

Let's imagine you want to send log records from your Drupal 8 site to your email box, 3rd party service or to some other destination in order to know about warnings, errors etc. Most probably you don't want to send an email each time when some action happens as you don't want to decrease page performance. So, in this case, you should write a "buffered logger" which will keep all log entries in a buffer and send them only when it's overflown or on shutdown function. So let's write it.

Sunday, November 5, 2017

Install the latest version of a composer programmatically

If you need to install the latest version of a composer you can use next bash snippet:
EXPECTED_SIGNATURE=$(wget -q -O - && \
php -r "copy('', 'composer-setup.php');" && \
php -r "if (hash_file('SHA384', 'composer-setup.php') === '${EXPECTED_SIGNATURE}') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" && \
php composer-setup.php && \
php -r "unlink('composer-setup.php');" && \
mv composer.phar /usr/local/bin/composer
Using EXPECTED_SIGNATURE variable with the latest available signature value you don't have to hardcode a specific one for comparison on 3rd line.

Saturday, July 29, 2017

Changed Fields API

This is a simple API module for Drupal 7 and Drupal 8 which allows developers to react on changed fields in a node when it was updated. For example, you want to modify node object depends on its field values. Or you just want to know what fields were changed. Or finally, you need to check the difference between old and new field values and do some other thing depending on this difference.

Saturday, July 15, 2017

Drupal Camp Kyiv 2017

On 10-11 of June in Kyiv there was an annual all-Ukrainian event - Drupal Camp Kyiv 2017. This is a place where experienced back-end, front-end developers, DevOps and managers share their knowledge. Traditionally Drupal Camp took place in two days: a conference day which includes 5 streams of presentations and code sprint where passionate developers can work together for improving Drupal and developing community. A few interesting statistics about this year’s event: 403 attendees, 5 streams of lectures, 42 speaker, 10+ international speakers, 70+ code sprint participants and 100+ patches made during code sprint.

Sunday, June 18, 2017

Drupal tester: docker image for testing Drupal projects

Recently I set out to make a simple instrument for running simpletest tests without having LAMP stack installed on your local environment. I needed this for two reasons:
  1. for running tests locally
  2. for running tests on CI server
I've decided to use Docker and create monolith container with Drupal and all the LAMP stuff inside and here what I've got: docker-tester.

Sunday, March 26, 2017

Panels: custom cache plugin

Last time we've created a style plugin. Now we will learn how to cache panel panes with custom cache plugins.

Saturday, February 25, 2017

Panels: custom style plugin

Panels style plugins are made for wrapping panel panes and panel regions into extra markup. 99% of your needs are covered by a "Panels Extra Styles" module. Please look at that module if you need extra styles for panels. But if you need some specific style you can easily implement it.

Wednesday, February 15, 2017

Ctools: custom relationships plugin

Relationships plugins are "bridge" between existing context (that is already set up in a panel) and a context which you want to get from existing one. Let's say your panel contains "Node" context and you want to get a node author (user from node:uid property). To do that you can just set up "Node author" relationship in a panel (under a "contexts" tab) and that's all. That's why relationships plugins are so important - they provide easy way for getting context from existing contexts. Please have a look at this post before continue reading - there is described how to create module integrated with ctools API which allows us to define own plugins.

Sunday, February 12, 2017

Ctools: custom argument plugin

This time we will consider an argument plugin. Arguments are pretty similar to contexts. Actually arguments are context objects loaded from url. By default ctools provides a full set of needed arguments such as "Node: ID", "User: ID", "User: name" etc. But what if you've created a custom context? You might need to create a custom argument for your context (if you want to use your context as an argument of course). I advise you to read previous articles from "Ctools custom plugin" series such as "Ctools: custom access plugin" and "Ctools: custom context plugin". It's also required to read "Ctools: custom content type plugin" before reading this post because there I've described how to create a module integrated with ctools API which can contain ctools plugins.

Ctools: custom context plugin

In previous post we created an access ctools plugin which can be used as a selection or visibility rule in panels. It's time to learn how to create another important custom plugin - a context. It provides additional information for a panel page. For example if you've put a node context to the page you will be able to use node properties as substitutions for a page title. Moreover you will be able to put node fields as panes to a page. By default ctools module provides useful contexts (node, user, taxonomy_term, entity etc) but you can define your own. Please, read first post of "Ctools custom plugins" series before continue reading this. There we've created a module integrated with ctools.

Sunday, February 5, 2017

Ctools: custom access plugin

Last time we've learned how to create custom ctools content type plugin. In that post we've already created a module example_module where we defined the plugin. This time we will learn how to create custom ctools access plugin. This type of ctools plugins can be used as a selection rule for a panel variant or as a visibility rule for a panel pane. Please, read previous post before continue reading this. There is described how to create a module and integrate it with ctools.

Saturday, February 4, 2017

Ctools: custom content type plugin

Ctools content types are an alternative to standard Drupal blocks. They are more comfortable and powerfull than blocks. Ctools content type plugins also known as panel panes. In this post you will learn how to create a configurable ctools content pane plugin.

Sunday, January 29, 2017

Drush commands for every day usage

Drush stands for "Drupal shell" which means a powerful tool for managing Drupal installation from command line interface. Drush provides a lot of useful commands for dealing with a cache, modules, cron, database etc. But some of contrib modules also provide some extra drush commands for specific functionality (like features module comes with commands for managing features). Here's a bunch of a useful drush commands which I use every day.

Tuesday, January 24, 2017

Form API #states: dependent fields

Drupal provides a powerfull API for building different kind of forms. One of the most cool thing in this API, I think, it's a #states feature. It allows developers to create form elements that can change their state depending on some conditions. For instance you can create a text input which will be visible only if checkbox is checked. Or even make multiple conditions for an element.

Saturday, January 21, 2017

Caching: static cache and database cache

You have to cache results of heavy functions, sql queries and markup if it's possible because it reduces load on a system in general. If you have a block which renders a lot of items shiped from a database - cache it. If you have a function that performs heavy calculations and this function is called many times during a script execution - cache a result of this function.

Sunday, January 15, 2017

Menu callback both for ajax and GET requests

I've already written about how to use native Drupal ajax mechanism on front-end side in this post. There I've described how to send requests immediately or by clicking (or by any other event) on any DOM element. It works when javascript is enabled in user's browser. But how to make your menu callback work both with ajax and GET (when js is disabled) requests?

Friday, January 13, 2017

Detect entity type

Default entities (node, user, term etc) in Drupal 7 are instances of a stdClass class. It means you can't determine entity type directly. Let's say you have an object and you want to ensure that it's a node and only then do something node specific. Entity API doesn't provide such possibility out of the box.

Tuesday, January 10, 2017

Add a custom view mode to an entity

Drupal 7 offers a mechanism to render entities which called view mode. For example you can set up how your entity will look as a full page or as a teaser. By default Drupal provides only two modes for node entity (default and teaser) and one default mode for taxonomy term and user entities. But you can easily add your custom view mode.

Sunday, January 8, 2017

Disable ajax throbber

Throbber is an element with a message that shows us that something is running in background. Drupal renders this element each time when ajax request is running (for example when you submit form via ajax). Sometimes we need to disable throbber at all or at least remove/change message. That's how you can do this.

Native Drupal ajax requests

If you are using jQuery.ajax() or for background requests you should have a look at native Drupal ajax implementation. Drupal provides a js object Drupal.ajax that performs all needed actions for you (like processing ajax commands that came from back-end side). All that you need to do is to create instance of this object and configure it.

Create custom ajax command

Drupal 7 offers a lot of default ajax commands which are the part of Drupal Ajax Framework. Furthermore, ctools module extends a set of ajax commands and provides own commands. But what if you need some specific command?

Saturday, January 7, 2017

Submit node form via AJAX

If you want to submit node form (or any form) via ajax request you need to follow next steps:
  1. Alter needed form: add container for validation messages and ajax callback for submit action.
  2. Implement ajax callback that returns ajax commands.

Drush and hook_init: how to don't break drush commands

If you have redirect functionality implemented with drupal_goto() function on hook_init() probably you aren't able to run drush commands because they crashe with a message:
Drush command terminated abnormally due to an unrecoverable error.  [error]

Debugging sql select queries

When you build sql select queries using Drupal database API often you need to debug them. I mean to copy sql string, paste into sql editor, run it and see a result. If you cast query object to string you simply get a sql query with placeholders instead of their values. To get a string with replaced placeholders by values you can use this function: