Nov 02 2018
Nov 02

We are in the process of transforming the way we host our applications to a docker based workflow. One of the challenges we face is the file storage. At the heart of our business are open source technologies and tools, therefore  we have looked into in using Minio (more or less the same as Amazon S3 for file storage) instead of local filesystem (or Amazon S3).

We are going to use the Drupal module Flysystem S3 - that works both with Amazon S3 and Minio (compatible with the Amazon S3).

Flysystem is a filesystem abstraction library for PHP which allows you to easily swap out a local filesystem for a remote one - or from one remote to another.

For a new site it is pretty straight forward, for a legacy site you need to migrate your files from one storage to another - that I am going to look into in the next blog post.

Minio container

First we need Minio up and running. For that i am using docker, here is an example docker-compose.yml:

services:
  minio:
    image: minio/minio:edge
    container_name: minio
    hostname: minio
    ports:
      - "8001:9000"
    volumes:
      - "./data:/data"
    environment:
      - "MINIO_ACCESS_KEY=AFGEG578KL"
      - "MINIO_SECRET_KEY=klertyuiopgrtasjukli"
      - "MINIO_REGION=us-east-1"
    command: server /data


Settings

When you have installed the Flysystem S3 module (and the dependency - the module Flysystem), we need to add the settings for Minio to our settings.php file (there is no settings for this in Drupal. Yet.):

$schemes = [
    's3' => [
        'driver' => 's3',
        'config' => [
            'key'    => 'AFGEG578KL', 
            'secret' => 'klertyuiopgrtasjukli',
            'region' => 'us-east-1',
            'bucket' => 'my-site',
            'endpoint' => "http://minio.mysite.com:9000",
            'protocol' => "http",
            'cname_is_bucket' => false,
            "cname" => "minio.mysite.com:8001",
            'use_path_style_endpoint' => TRUE,
            'public' => true,
            'prefix' => 'publicfiles',
        ],
        'cache' => TRUE, 
        'serve_js' => TRUE,
        'serve_css' => TRUE,
    ],
];
$settings['flysystem'] = $schemes;

Endpoint is for communicating with Minio, cname is the base URL that files is going to get on the site. Serve_js and serve_css is for Minio to store aggregated CSS and JS.

Create a field

You now need to define which fields are going to use the S3 storage, for this, I create a new image reference field, and use “Flysystem: s3” as the Upload destination.

Surf over to Minio - our example is on http://minio.mysite.com:9000 - add the defined bucket, my-site, and make sure that drupal can write to it (edit policy in Mino and make sure it has read and write on the prefix - or for wildcard prefix - *)

And you are done

And that is it - now we are using Minio for storing the images. Try to upload a file on the field you created - and you should see the file in Minio. Also on the site - you should of course see the image - but now with the URL used in the settings for CNAME, in our case, minio.mysite.com:8001.

We have put some time and effort into the Flysystem S3 module together with other contributors, and we hope you will test it out and report any feedback. Have fun!

Mar 28 2018
Mar 28

One week ago, we received a warning that a critical security update for Drupal, which affected drupal 7 and 8 (and even 6, which is not supported anymore) was going to be released today. And we braced ourselves for updates.


A couple of years ago, it was a hard work for us to update a site if a security update was released. Nowadays our hosting and our processes are much better and simpler - and thanks to a team effort by our Live-team at Digitalist, we got our most vulnerable sites patched minutes after the security fix was released. 

Digitalist Live Team patched in total around 1700 sites on our own hosting in less than 2 hours!

If you read the FAQ for the security issue - it is really critical to update - if the vulnerability is exploited all non-public data is accessible, and all data can be modified or deleted. Simply put - your site could be immediately hacked and taken over by someone else.

It is good to remember that the vulnerability has not been exploited anywhere that we know of. But after discolsure of a vulnerability, "black hat" hackers will immediately try to exploit Drupal sites. That is why it so important to act quickly and apply security updates once they become public.

Drupal is one of the most secure CMS systems available - and it stays that way due to its robust vulnerability-handling process.

Dec 07 2017
Dec 07

Some module require that you download external Javascript-libraries, and in drupal 8 that should be done in Composer. 

The module Masonry require the JavaScript library with the same name. So we need to include the package in composer.json, like:
 


"repositories":[
    {
        "type":"composer",
        "url":"https://packages.drupal.org/8"
    },
    {
        "type": "package",
        "package": {
            "name": "desandro/masonry",
            "version": "master",
            "type": "drupal-library",
            "dist": {
                "url": "https://unpkg.com/[email protected]/dist/masonry.pkgd.min.js",
                "type": "file"
            }
        }
    },


And in the require part that is:


"require":{
    ...
    "desandro/masonry":"master",
    ...
},

And then we need to add libraries in extra part of we do not have that:


"extra":{
...
"web/libraries/{$name}":[
    "type:drupal-library"
],
...

So to install the library, you just need to run


composer require desandro/masonry

Oct 04 2017
Oct 04

Group photo from Drupalcon Vienna

So last week we went with a big crowd (16 of us) from Digitalist to Drupalcon in Vienna to join the about 2000 other attendees. We went to sessions and BOF:s about caching in Drupal 8, Symfony components in Drupal core, Docker, Config split, Decoupled Drupal, Multi-sites in Drupal 8 and a lot of other things.

Driesnote

[embedded content]

A standard thing at Drupalcon is Dries talking about The state of Drupal - called the Driesnote – that means talking about all the good things we have in Drupal and in the community and what is working, and what we need to work on to make Drupal and the community even better. One great thing to hear is the result of the survey that the Drupal Association sent out to companies working with Drupal – a lot of the companies around the world is going very well – over 48.5% of the Drupal companies has a growing sale – and Drupal deal sizes are also growing for them – for 47% it is getting bigger.

Dries also talked about the workspace-project – that you could work on a part on the site with a bunch of content – and see how it looks – without publishing it – a big step forward for Drupal. Also some talk about adding a JS-framework to get a better UI experience in the admin parts of the site.
 

Contenta

[embedded content]

Decoupling Drupal (also know as headless Drupal) has been something that has been done for years now – and one really nice intiative is Contenta CMS, that try to build a best practice setup for decoupling Drupal – and on their session they presented some of the work they have done – with an easy setup to make frontenders that never has worked with Drupal to get started on which end points to use etc. If you are starting a project with a decoupled Drupal – I recommend you to check Contenta CMS out, with ready examples using JS-frameworks like Angular, React etc.

ELM

[embedded content]

There were a bunch of sessions discussing different uses of frameworks that could be used as an frontend for Drupal – one I find very interesting (being mostly a backender myself) is using ELM, presented on Drupalcon by Amitai Burstein – who the latest four years have build different solutions for decoupled Drupal.

Caching, a guru-guide

[embedded content]

Wim Leers is one of the core contributors that knows most about the caching layer in Drupal – and his session about caching in Drupal 8 was one of the most interesting in Vienna – there a lot of stuff to think about in caching – and his session went thru the most of them.

Moving configuration around

[embedded content]

The Drupal 8 configuration system is a hard nut to crack for some projects – and one of the solutions that are getting more and more attention is config split – used for handling configuration differences betweween different environments (dev → stage → prod). Fabian Bircher did a crowded presentation about his brain child and were also part of a BOF initiatives by the Swedish university Lunds Universitet, talking about the problems and solutions using Drupal 8 for multi sites setups.

Humanized Internet

[embedded content]


External keynote speakers has been a long tradition – and this year we had Monique J. Morrow talking about the Humanized Internet – with a lot of focus on personal security and the Internet – one of the examples she brought up about this was the Swedish data breach inside Transportstyrelsen, and the upcoming GDPR regulation that helps protecting personal data inside EU.

And there a lot of more

Of course there were a lot more – and most of the sessions you could now watch on Drupalcons site, just go to the schedule and pick which session you would like to watch.

Next Drupalcon in Europe will be in 2019 – and I am looking forward to it!
 

Jun 21 2017
Jun 21
In order to run Behat test from PHPStorm we need to setup our IDE in a certain way because our IDE is on the host and the Behat tool is running inside our vagrant VM, so we will need to use a remote interpreter, let's see how we can do it: Configure the PHP remote interpreter: Go to settings/preferences and browse to Language and frameworks > PHP Remote php interpreter At CLI interpreter we may have by default, so we can open the CLI interpreters dialog window from the ... icon. In that dialog we can add a new interpreter clicking in the + icon. In our case we can add a 'From Docker, Vagrant, VM, Remote' and we will get different options to setup the connection to the remote interpreter. Change the name of the remote interpreter and check the box 'Visible only for this project'. We can use Vagrant and… Read More
Apr 04 2017
Apr 04

If you just want your content to be cached before Drupal 8, there were almost no problems, just turn on caching for anonymous users, and you are all set. Muhahhaha! Who am I kidding...

If you want to interact with users with different content depending on the user, role etc. You got problems, if you want to invalidate the cache, you got problems. If you want to show a View of nodes, and turn off caching of that view, but had caching for anonymous users, you got problems. And so on. The most caching issues were solved by clearing all the cache, which could bring down the site if your unlucky.

So the real problem we wanted solve were not caching per see, it was cache invalidation. And like Phil Karlton supposedly said in the early nineties “There are only two hard things in Computer Science: cache invalidation and naming things.”

Some sites solved the caching issue before Drupal 8 with just turning of the cache completely, and scaled up the environments instead, and spent a lot of money in doing so. I have seen some high traffic sites with almost no cache logic in place, because it was to hard to get the cache invalidation to work. Those who worked hard on getting the cache and the cache invalidation to work smarter used modules like expire and purge, and integrated with rules solve complex cache invalidation. But is was almost impossible for any Drupal module to know where any content were used on a site. And that is what we want from smart cache invalidation.

Almost the only case that the default caching worked with no issues before D8, was if your site just were only one node, and some static blocks.. And if you updated that node, the cache of that node will be invalidated (hopefully). A normal sized site has hundreds and thousands of pieces of content, relations to other content, has listing of nodes etc. So it was real hard before D8.

So what we needed for cache in Drupal 8 is for Drupal to be aware on what cache and where it is used an in which context. Cache all things (aka. Fast by default), and make cache invalidation easier (aka Cache tags). And we got it. And let’s dive into what we got in the next blog post.

This is our second part of our ongoing series: Caching in Drupal 8, first part you could find here (with links to blog posts published so far).

Photo by Sera Tü. License

Mar 31 2017
Mar 31

Den här sidan använder cookies. Om du fortsätter använda sidan så accepterar du användandet av cookies. Läs mer om cookies

Jag förstår

In a series of blog posts we will go through how caching works in Drupal 8, to try to demystify the caching layer in Drupal 8 for developers.

In a series of blog posts we will go through how caching works in Drupal 8, to try to demystify the caching layer in Drupal 8 for developers.

Planned blog posts are (this will be linked from here when they are up)

  • Introduction
  • How it worked, and what we wanted to be solved in D8
  • Cache metadata - overview
  • Cache keys
  • Cache context
  • Cache max-age
  • Cache tags
  • Twig cache
  • Core cache services
  • Internal Page Cache
  • Internal Dynamic Page Cache
  • Creating your own cache tags
  • Creating your own cache context
  • Define and use your own cache bins
  • Solutions for working with good caching of Views
  • Disable caching – why, when and how
  • Cache tags together with Varnish
  • Cache bins in Memcache/Redis/whatever
  • Wrapping it up

The plan is to finish this series in a months time, with a couple or more of blog posts per week. Many parts of the series is loosely based on a session I did for DrupalCamp Northern Lights this February. But, here I will have the time to go into more detail, and with more code examples.

We started early to work with Drupal 8, our first project was this site, and after that we started to deliver Drupal 8 sites to our clients. We learned a lot during all the projects, and hopefully I will be able to share to you all the stuff that the learned about the caching layer in an understandable way. So this knowledge is based on trial and error on real projects.

Target audience for this blog series is both backend and frontend developers.

Looking for a job?

We are always looking for talents. In fact, our last 5 employees moved to Stockholm just to work with us. Will you be our sixth?

Vi hjälper dig nå resultat. Kontakta oss Ring direkt på 08-20 90 04.

Updating taxonomy term name in Drupal 8

Here you can read how to use hook update for updating taxonomy terms in Drupal 8.

Varnish Purge 8.x-1.4 is out

As for Purge module 8.x-3.0-beta5, creation of cache tags is removed from the Purge module itself, and should now be handled by purges instead – so from Varnish Purge 8.x-1.4 we now have a sub-module, Varnish Purger Tags, that handles the cache tags. 

Mar 04 2017
Mar 04

Den här sidan använder cookies. Om du fortsätter använda sidan så accepterar du användandet av cookies. Läs mer om cookies

Jag förstår

Next Wednesday you are all welcome to our Drupal Meetup at Wunderkraut, where we will talk about caching in Drupal 8 And drink some beer.

It has been a while, but now it is time again for a Drupal Meetup in Stockholm, and it will be at the Wunderkraut office in Stockholm, signup for it here. There will be beer, mingle, talk about caching in Drupal 8, and more. Bring a friend or two!

Vi hjälper dig nå resultat. Kontakta oss Ring direkt på 08-20 90 04.

Rekommenderad läsning!

Highlights from Drupalcon Vienna

So last week we went with a big crowd (16 of us) from Digitalist to Drupalcon in Vienna to join the about 2000 other attende…

MDN Rekommenderad läsning!

Highlights from Drupalcon Vienna

So last week we went with a big crowd (16 of us) from Digitalist to Drupalcon in Vienna to join the about 2000 other attende…

MDN

Kraften i Drupal

Vi har hittat en bra film som enkelt beskriver styrkan och kraften i Drupal och communityn runt omkring.

Feb 23 2017
Feb 23

Den här sidan använder cookies. Om du fortsätter använda sidan så accepterar du användandet av cookies. Läs mer om cookies

Jag förstår

Here you can read how to use hook update for updating taxonomy terms in Drupal 8.

The hook update is added in the .install file like mymodule_update_800x

function mymodule_update_8001(&$sandbox) {
  $query = \Drupal::entityQuery('taxonomy_term');
  $query->condition('vid', 'county');
  $result = $query->execute();

  foreach($result as $term_id) {
    $term = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($term_id);
    $term_name = $term->getName();
    // Transforming taxonomy term value. Doing my stuff.
    $value = $term_name . " län";
    $term->setName($value);
    $term->save(); // Important!!!!
  }
}

Looking for a job?

We are always looking for talents. In fact, our last 5 employees moved to Stockholm just to work with us. Will you be our sixth?

Vi hjälper dig nå resultat. Kontakta oss Ring direkt på 08-20 90 04.

Rekommenderad läsning!

Stockholms Stadsmission väljer Drupal

Vi har fått förtroendet att hjälpa till med övergripande koncept, design och kontinuerlig utveckling av Stockholms Stadsmiss…

MDN

Cache in Drupal 8: Introduction

In a series of blog posts we will go through how caching works in Drupal 8, to try to demystify the caching layer in Drupal …

MDN

Vad är Drupal?

Drupal är ett Open Source-ramverk för webb och har idag världen största samt mest aktiva community med mer än 1 miljon användare.

Nov 17 2016
Nov 17

Den här sidan använder cookies. Om du fortsätter använda sidan så accepterar du användandet av cookies. Läs mer om cookies

Jag förstår

Out of the box Drupal 8 has the header of a page request set to X-Frame-Options: SAMEORIGIN, that means that many modern web browsers does not allow the site to be framed from another domain, mostly for security reasons. This is good in many cases, but some web browsers has problem with this, and X-Frame-Options is deprecated in favor of using Content-Security-Policy.

So why do you need a header like that? It is mainly for protecting a site for what is called Clickjacking

Also, for some cases you want you site to be framed into another, and doing that out of the box with Drupal 8 is not possible in most modern web browsers if you don't alter the sites header in apache, nginx, varnish or in some other way. We are now going to look into doing in “some other way”, in this case with Drupal. I prefer using Drupal to control site headers because of the sites header is a part of the application. 

This solution is based on this post on drupal.org.

Create a structure like this:

mycustom 
  ├── mycustom.info.yml 
  ├── mycustom.services.yml 
  └── src 
    └── EventSubscriber 
      └── MyCustomEventSubscriber.php 

And here is the code

mycustom.info.yml



name: My custom
type: module
description: Replacing X-frame-Options with Content-Security-Policy
core: 8.x
package: custom

mycustom.services.yml


services:
  shp_xframe_remove_event_subscriber:
    class: Drupal\mycustom\EventSubscriber\MyCustomEventSubscriber
    tags:
      - {name: event_subscriber}

src/EventSubscriber/MyCustomEventSubscriber.php


<?php
namespace Drupal\mycustom\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

/**
 * Subscriber for changing header.
 */
class MyCustomEventSubscriber implements EventSubscriberInterface {

  /**
   * Remove X-Frame-Options, adding Content-Security-Policy.
   */
  public function setHeaderContentSecurityPolicy(FilterResponseEvent $event) {
    $response = $event--->getResponse();
    $response->headers->remove('X-Frame-Options');
    // Set the header, use FALSE to not replace it if it's set already.
    $response->headers->set('Content-Security-Policy', "frame-ancestors 'self' mysite.com *.mysite.com", FALSE);
  }

  /**
   * {@inheritdoc}
   */
  static public function getSubscribedEvents() {
    // Response: set header content for security policy.
    $events[KernelEvents::RESPONSE][] = ['setHeaderContentSecurityPolicy', -10];
    return $events;
  }

}

That is it.

Looking for a job?

We are always looking for talents. In fact, our last 5 employees moved to Stockholm just to work with us. Will you be our sixth?

Vi hjälper dig nå resultat. Kontakta oss Ring direkt på 08-20 90 04.

Oct 05 2016
Oct 05
In our developer workflow we install the site continuously during development, as a health check of the code base. One of the problems we have in this workflow is when we declare a service that belongs to a module that is not activated yet during the install, like Memcache module. In our developer workflow we install the site continuously during development, as a health check of the code base. One of the problems we have in this workflow is when we declare a service that belongs to a module that is not activated yet during the install, like Memcache module. This is what a site needs normally in settings.php,  $settings['memcache']['servers'] = ['localhost:11211' => 'default']; $settings['memcache']['bins'] = ['default' => 'default']; $settings['memcache']['key_prefix'] = 'foo_bar'; $settings['cache']['default'] = 'cache.backend.memcache'; This works perfect to add on a runnings site when the module is activated… Read More
Sep 12 2016
Sep 12
As for Purge module 8.x-3.0-beta5, creation of cache tags is removed from the Purge module itself, and should now be handled by purges instead – so from Varnish Purge 8.x-1.4 we now have a sub-module, Varnish Purger Tags, that handles the cache tags.  As for Purge module 8.x-3.0-beta5, creation of cache tags is removed from the Purge module itself, and should now be handled by purges instead – so from Varnish Purge 8.x-1.4 we now have a sub-module, Varnish Purger Tags, that handles the cache tags.  To use Varnish Purge with cache tags, from version 8.x-1.4, you need to activate the new sub-module. And also you need to reconfigure the Purger – because we renamed the Header for the cache tags to Cache-Tags, because we see no point calling it something else, so you also need to update your VCL file, if you using the older settings – Purge-Cache-Tags – for… Read More
Sep 08 2016
Sep 08
This is how you use the hook_user_logout to implement a redirect in Drupal 8. For implementing a redirect in Drupal 8, we can do it using the hook_user_logout() /** * Implements hook_user_logout(). */ function mymoduler_user_logout() { // we redirect to an external site $response = new RedirectResponse("https://www.google.se"); $response->send(); return $response; } Remember to include the library: use \Symfony\Component\HttpFoundation\RedirectResponse;
Jul 21 2016
Jul 21
The dependency injection is the best way for using services in Drupal 8 and it should be used whenever possible. In Drupal 7 we were using the function valid_email_address for validating emails in Forms, like: function test_custom_form_validation($form, &$form_state) { $mail = $form_state['values']['email']; if (!valid_email_address($mail)) { form_set_error('email', t('Please Enter a valid email address.')); } } We should not used this method for validating emails in Drupal 8 because it is deprecated. Instead, it is recommended to use dependency injection. The dependency injection is the best way for using services in Drupal 8 and it should be used whenever possible. The best practice is to call the require service as argument in the constructor. It is not recommended to call out the global service container what it is a common error when… Read More
Jul 09 2016
Jul 09
In this blog post I am going to go through a step by step setup for using the Varnish purge module together with Purge and Drupal 8. Please read this about updates done since the blog post were written. In this blog post I am going to go through a step by step setup for using the Varnish purge module together with Purge and Drupal 8. We have started to work on the Varnish purge module and we are using it some of our projects. The Varnish purge module is a fork of the Generic HTTP Purger with some minor changes. To use Purge and Varnish Purge you need to have a working setup with Varnish already, for an example VCL, see the end of the blog post. First install Purge and Varnish purge modules. For Purge to work normally you also have to install… Read More
Jun 13 2016
Jun 13
With the release of ES6 (ECMAScript 2015) they added the new Proxy feature. It lets you create a middleware when doing changes to a object. With the release of ES6 (ECMAScript 2015) they added the new Proxy feature. It lets you create a middleware when doing changes to a object. We will use this to build a simple cache helper for the client side. We will use sessionStorage to store the data so we don't have to care about invalidation. // The name of the sessionStorage item. const sessionKey = 'cachedData'; // Get stored items const sessionItems = sessionStorage.getItem(sessionKey); // Parse the stringified items if it exists else create a empty object let cachedItems = sessionItems ? JSON.parse(sessionItems) : {}; const handler = { // This trap (function) will be run each time we are setting the property values set (target, key, value) { // Add the new… Read More
Mar 03 2016
Mar 03
I will go through how to build a menu and menu items that is translatable in code. Let's say for example we want to rebuild our main menu each time a user saves a node.  deleteLinksInMenu($menu_name); // Here we are creating the first level and pointing // it to /first_level $first_level = MenuLinkContent::create([ 'title' => 'First Level', 'link' => ['uri' => 'internal:/first_level'], 'menu_name' => $menu_name, 'expanded' => TRUE, ]); // Save the first level $first_level->save(); // Create a array from fake nids for this example's sake. // In a real life scenario you will want to use… Read More

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web