Gbyte blog: Creating Drush 9 commands and porting legacy commands

Upgrading to Drush 9

Drush should be installed and updated through composer. There is no stable Drush 9 version yet, so the development version must be used. Updating to the development version of Drush 9 is a simple as typing:

$ composer require drush/drush:dev-master

Porting your Drush commands to Drush 9

Porting the commands is a semi-automatic process: There is a command that will generate the required files and class structure for you. To start the wizard, just type:

$ drush generate drush-command-file -l dev

Drush will ask you for the module's machine name and for the optional path to the legacy Drush command file (the one that has your commands, ending with .drush.inc). You will have to provide the absolute path.

drush.services.yml

This is the file your Drush command definition goes into. Do not use your module's regular services.yml as you might have done in Drush 8 or else you will confuse the legacy Drush which will lead to a PHP error like this:

Fatal error: Class 'Drush\Commands\DrushCommands' not found in MyModuleCommands.

Use the dedicated drush.services.yml file in your module's root directory instead.

The file should look like this:

Gbyte blog: precore.net - a platform for artists and design students

Since its relaunch in 2015, the Drupal 7 powered precore.net has been gaining popularity among artists and design students to become their go-to platform. Until today, design students have uploaded over 700 portfolios providing guidance to enrolling candidates. These portfolios are linked to over 500 art faculties of hundreds of universities.

Before enrolling in a course, a candidate can research their local university and study other students' portfolios or enroll in their local design course to prepare for the entry tests - all of it on precore.net.

On top of that, students provide and collect support on the precore.net forum which boasts over 20000 users who have written nearly 250000 posts. This may be the biggest and most beautiful forum built on top of Drupal core.Image removed.

The most powerful feature however may be the ability for guests to create most of the site's content without having to go through any type of registration process. Visitors can go ahead and correct their school's information just by clicking 'edit'. Likewise, anyone can write a blog post - no account or personal information needed. We think this technology has massively contributed to the quantity and quality of content on precore.net.

Gbyte blog: Prevent deletion of taxonomy term if associated with a node

Why check if term is associated to a node prior to deletion?

In cases where taxonomy terms are used only for categorizing content on a Drupal powered web page, there should be no harm in deleting them. However sometimes taxonomy is used to store terms critical to the content they are referenced from and in this case steps should be taken to prevent an accidental deletion.

I have encountered such a case on a project I am working on which is soon to become a web platform for university students. When creating a faculty node, its name is being defined by choosing a term from the 'faculties' vocabulary. Deleting a term assigned to such a faculty node would lead to... well undesired effects.

Approach

When looking for the right hook you will find that there is no hook_taxonomy_pre_delete and using the existing hook_taxonomy_term_delete would be too late (the term would be deleted by then). (By the way, this problem persists across other entity types, like nodes - hoping to see some added hooks in D8.)

I will describe an easy way of preventing the deletion of a used taxonomy term, but be warned, this will only prevent the deletion of a term in the UI, it will not react to programmatically deleted terms.

Here is how this is going to look like:

Image removed.

Some code:

Gbyte blog: Why forking Drupal into Backdrop is a bad thing

Please note the date of the article - it may not be current nor does it necessarily reflect the author's current opinion on the matter. See this comment.

The ability to fork is a wonderful thing.

In the open source community, the ability to fork software projects is a wonderful thing, as it allows taking a software snapshot in a completely different direction from what was intended by its current maintainers.

Projects get forked for reasons that can be categorized in political (changing ownership rights, controversial decisions made by the project maintainers, etc.), technology related (where maintainers disagree about the direction of development and implementation) and personal.

Forking is a bad thing.

Wait... did you not just say forking was wonderful?
The ability to fork is wonderful, as it gives great power to the community. But forking itself is bad for the project, as it results in two projects with weaker development and support, a weakened potential to grow and a divided and confused user base. It leads not only to separate code bases, but also to a divided developer and user community and should be considered last resort.
In the best case scenario, forking is choosing the lesser evil.

No matter how much effort is put into collaboration between the fork and the original project, in the end it always ends in lack of compatibility and refusal to provide support to confused users in the different camp. This is why the Backdrop creators' reassuring statements about cross contribution should be taken with a grain of salt.

Gbyte blog: Simple Views display switch

If you need a simple Views display switch to toggle e.g between a list and a grid display of a view, there are a couple of plug & play options already.

Display Suite and Quick Tabs are modules which provide this functionality but they seem to be quite an overkill for a simple display switch. View modes on the other hand seems to be exactly what is needed, however there is no stable version and the development one did not work for me.

How it needs to work

Our use case dictates that while switching a display, the view needs to retain the exposed filter values and page number. The page will be reloaded, no AJAX magic here.

Image removed.

So let's create our own views display switch. In order to do that you will obviously be needing a view with at least two page displays showing content in different ways. You will also have to put some code into your custom module. If in doubt, refer to the countless other tutorials.

Set up your view

In the view named [view] set the path of [display_1] to e.g [page/grid], the path to [display_2] to e.g [page/list].

Create callback function

Create a simple callback function which will provide the switch in ready-to-be-displayed HTML.

Gbyte blog: How to use the Drupal 8 & 9 honeypot module efficiently

The Honeypot module is a great captcha alternative, as it keeps spam bots from submitting content while also saving your site visitors from having to type in mundane character combinations.
Configured properly it will prevent the majority of bots from submitting forms on your site including registration forms, contact forms, comment forms, content forms... any drupal forms.
It works differently from Captcha: it lures the bot into filling out a form field invisible to regular users. By doing so, the system recognizes the bot for what it is and denies the submission.

While being very user friendly, this reversed bot detection system comes at the cost of some bot submissions getting through anyway. This is why I would advise against using this module on large sites, where it is difficult to track every piece of submitted content. It should work well for smaller and medium sites however, it has been working well in many of my projects including this very site.

Honeypot configuration

Correct configuration of the module is extremely important, as wrong settings might make the module inefficient or worse, prevent real users from submitting forms. After configuring the module, make sure to double check it works by submitting a protected form as an anonymous user.

Once installed and enabled, go to admin/config/content/honeypot to configure the module.

First of all careful with the "protect all forms" option, as caching will be disabled on every page that includes a form. This can be problematic in cases where e.g. a login block is embedded in the sidebar. In addition to ticking what forms to protect, there are two important settings to keep in mind.

Gbyte blog: When custom t() strings are missing from the translate interface

The Drupal 7 translation system including the internationalization package is a heavy beast and while it mostly gets the job done, it is all but intuitive in use.

For high volume translations it is recommended to use the translation template extractor and translate the strings externally. For small corrections however, it is often much more convenient to use the translation interface (admin/config/regional/translate/translate).

Now that you've created that shiny module/template and made it translatable by passing all strings through the t() function, you may be wondering why your newly created string is not showing up in the translate interface.

To save you some trouble, here is a short list of things to check:

1. Include the project version number within the module/theme .info file.
Without the project version information, the translate interface will not register new translatable strings in your module/theme. Make sure to add version = 7.x-1.0 into the module/template .info file.

2. Run the string through the function in a non-standard language mode.
In order for the translation system to add your translatable string, the t() function must run at least once in a non-standard language. To achieve that, you will need to switch the language of the site to one you are going to translate into and then visit the page that displays the string.

3. Mind the case sensitive search filter.
Be accurate when using the translate interface filter - it does not forgive.

Gbyte blog: What to keep in mind when creating Drupal 8 projects - for developers


Please note the article's publishing date. Some of the information presented below may not be current anymore.

With only a few critical issues left in the Drupal 8 queue and D8 being surprisingly usable, many developers already use it in small projects to play with the technology and to challenge themselves.
I have to admit, I am no exception - the embracement of many PHP technologies and (finally!) the jump to the OOP paradigm makes me want to stop writing right now and code some more.

Which projects qualify for Drupal 8 today?

I would wait a few months before creating bigger D8 projects for my clients. The community has to play some catching up first and port modules, themes and write documentation. On top of that, apart from all the OOP technologies we love, there have been some new drupalisms introduced and not documented yet - this combined with the lack of contributed module solutions makes D8 development much more time consuming for paid projects in comparison to D7.

Small projects however are very doable.

First however, it may be necessary to upgrade the server, as D8 introduces relatively high PHP and SQL requirements. See the official requirements page.

Gbyte blog: Image indexation and other new features of Simple XML sitemap 2.10

This is a technical description of the 2.x branch of the module. For the newer 3.x branch see this article; for 4.x, see this article.

New features of Simple XML sitemap

Version 2.10 of Simple XML sitemap is mainly a feature release with only a few minor bugs fixed. The new features are

  • the implementation of the changefreq parameter
  • the ability to set an interval at which to regenerate the sitemap
  • the ability to customize XML output
  • the ability to add arbitrary links to the sitemap
  • image indexation

See the 8.x-2.10 release page for details.
A new version has been released, please make sure to visit the project page.

Image indexationImage removed.

Simple XML sitemap is now able to create Google image sitemaps through indexing all images attached to entities. This includes images uploaded through the image field as well as inline images uploaded through the WYSIWYG. The inclusion of images can be set at the entity type and bundle level but can be overridden on a per-entity basis giving you all the flexibility.