Planet Drupal

Subscribe to Planet Drupal feed
Drupal.org - aggregated feeds in category Planet Drupal
Updated: 14 hours 29 min ago

KnackForge: How to update Drupal 8 core?

23 March 2018 - 10:01pm
How to update Drupal 8 core?

Let's see how to update your Drupal site between 8.x.x minor and patch versions. For example, from 8.1.2 to 8.1.3, or from 8.3.5 to 8.4.0. I hope this will help you.

  • If you are upgrading to Drupal version x.y.z

           x -> is known as the major version number

           y -> is known as the minor version number

           z -> is known as the patch version number.

Sat, 03/24/2018 - 10:31
Categories: Drupal

Chapter Three: How to Prevent Duplicate Terms During a Drupal 8 Migration

0 sec ago

In this post I will show a custom process plugin that I created to migrate taxonomy terms. The plugin handles the creation of new terms and prevents duplicates.

Below is a portion of the migration template. In the example, I am migrating new terms into keywords vocabulary via field_keywords field.

field_keywords: - plugin: existing_term # Destination (Drupal) vocabulary name vocabulary: keywords # Source query should return term name source: term_name - plugin: skip_on_empty method: row

This is the source code for the process plugin.

Categories: Drupal

DrupalEasy: DrupalEasy Podcast 196 - Ryan's Ace(?) in the Hole - Paragraphs Module

18 August 2017 - 12:25pm

Direct .mp3 file download.

Ryan Price and Mike Anello discuss the pros and cons of the Paragraphs module, including using it for layout and/or information architecture. Ryan takes the discussion in unexpected directions by bringing up Pattern Lab as a prototyping tool and his mysterious "Ace in the Hole" (which Mike feels is more like a Jack of spades). In addition, there's some discussion about a new-ish feature in the Migrate Plus module that is sure to make migration developers happy.

Interview News DrupalEasy News Sponsors Upcoming Events Follow us on Twitter Subscribe

Subscribe to our podcast on iTunes, Google Play or Miro. Listen to our podcast on Stitcher.

If you'd like to leave us a voicemail, call 321-396-2340. Please keep in mind that we might play your voicemail during one of our future podcasts. Feel free to call in with suggestions, rants, questions, or corrections. If you'd rather just send us an email, please use our contact page.

Categories: Drupal

Mediacurrent: TypeScript and Drupal.behaviors

18 August 2017 - 8:05am

Back in June some of our crew attended Dinosaur JS conference in Denver, CO.

There were talks ranging from V8’s JS optimization (even had some assembly language slides in there) to demonstrating the creation of an homage to an abstract artist with JavaScript code.

This all got me thinking about TypeScript, Closure compiler, etc... and JS performance and development in general. But I have to admit, I was struggling to see how these technologies could benefit us in Drupal since most of our JS is done in Drupal.behaviors.
 

Categories: Drupal

Anubavam LLC: Building web services with Drupal 7

18 August 2017 - 5:52am
Building web services with Drupal 7

A web service is a software system designed to support interoperable machine-to-machine interaction over a network. Web services is a well-defined way for two computers to communicate with each other over the internet. 

Drupal web services is always a good option for you

In Drupal, web service is being used to communicate with other web applications or mobile applications. Content can be shared and easily integrated with other applications as well. 

Why use web services in Drupal?

Web services are useful because they present us with an architecture where a resource on a site (an image, textual content, such as a node ID or block ID, a video or audio file) is given a unique identifier. 

Use cases 

For example, in Drupal, every node has an ID. Every file you upload to a Drupal site also has a unique path to it.

This is extremely useful since all applications share this common semantic standard. We name things similarly on all of our web applications. 

Drupal services and real world examples

Here are some examples, perhaps we have to build a product site and they are developing a app for that product site in mobile, then we can pass data from web to mobile app using the web service.  For example if the HR Department wants to integrate its job postings and applications with another web application such as job portals, web services can make this happen.

Advantages of Drupal web development services you can’t ignore

This leads to another advantage of using web services with Drupal and why we would choose to use Drupal in the first place. Instead of having to upload our photos twice—once to our Drupal site and then repeating the procedure to our some other applications, services allows us to upload the images to our Drupal site once and then automatically send that data over to other application which wants without having to upload one (or even a batch of images) again. It saves us time and speeds up the entire process of generating web-based content.

Building web services for Drupal 7

Drupal can use web services following any of the protocols mentioned earlier, including XML-RPC, REST, and SOAP. Drupal can consume web services by requesting data from other web applications using RSS and XML-formatted requests. As a Drupal developer, you can write your own service code in Drupal using PHP. You can also use the Services module as well as other service-specific contributed modules to create these web service requests.

Service module supports multiple interfaces like REST, XMLRPC, JSON, JSON-RPC, SOAP, AMF and more.

Make use of Drupal Services module for:

  • Integration with core Drupal functionality like files, nodes, taxonomy, users, files and more.
  • Response format API allows you to define response Formats for CONTENT-TYPE ie. application/json or application/xml. (also calls such as ENDPOINT/node/1.json work)

Additionally, all the communication between services, in our example between a client and a server, happens over HTTP (the standard web protocol). This is a uniform protocol that is used for transport and communication of the service. All transports take place uniformly using GET, POST, PUT, and DELETE requests, for example.

The HTTP requests are stand alone and occurs at one given moment and is isolated from all other activated requests. If HTTP requests works and gets a response, it succeeds. If HTTP requests doesn’t get response from the server or application it's communicating with, it fails. The requests can be repeated an infinite number of times.
 

admin Fri, 08/18/2017 - 08:52 Drupal Drupal Development Drupal developer Drupal Application Development
Categories: Drupal

Chapter Three: How to Fix HTML Content Issues During Migration in Drupal 8

17 August 2017 - 5:20pm

In this post I will show you a technique to fix HTML issues, import images or perform content operations during migrations.

We have to fix source content before most content migrations. This can be challenging if there are many entries in the source database. The powerful Drupal 8 Migration API provides elegant ways to solve this type of problem.

To solve HTML issues, I always create my own process plugin. Here is an example how you would call your own process plugin to fix HTML issues in the body field:

Categories: Drupal

Chiranjeeb Mahanta | Blog: GSoC’17 Coding period | Week #11 | Uc wishlist

17 August 2017 - 12:01pm
GSoC’17 Coding period | Week #11 | Uc wishlist chiranjeeb2410 Thu, 08/17/2017 - 15:01
Categories: Drupal

Acquia Lightning Blog: Using the Content API

17 August 2017 - 10:41am
Using the Content API Adam Balsam Thu, 08/17/2017 - 13:41

Lightning 2.1.7 includes a new top-level component: Content API. Its purpose is to provide a very basic server-side framework for building decoupled apps using Lightning as a backend. It has no strong opinions about how the "front-end" of such an application is implemented -- out of the box, it merely provides tools to deliver Drupal entities according to the JSON API specification.

Generally speaking, you can interact with API anonymously in the same way that an anonymous user can interact with a standard Drupal site. So you can do things like get a single piece of content, or a list of content without authenticating. For other actions -- the kind that would normally require you to be logged in to Drupal -- you will need to provide an OAuth access token in the header of your request. Tokens are related to a Drupal user and an OAuth client, which is associated with any number of Drupal user roles. You can obtain a token by making a specific HTTP request for it.

Let's go through some common, generic, use cases. I'll use cURL in my example so that you can easily test them out for yourself.

Getting a list of content

The API endpoints generally follow the following pattern: "/jsonapi/{entity-type}/{bundle}". So if we wanted to get a list of Basic Page content, we could send a GET request to "/jsonapi/node/page":

curl --request GET \ --url https://example.com/jsonapi/node/page

Which would return something like this:

{ "data": [ { "type": "node--page", "id": "api_test-unpublished-page-content", "attributes": { "nid": 1, "uuid": "api_test-unpublished-page-content", "vid": 1, "langcode": "en", "status": false, "title": "Unpublished Page", "created": 1502985175, "changed": 1502985175, "promote": false, "sticky": false, "revision_timestamp": 1502985175, "revision_log": null, "revision_translation_affected": true, "default_langcode": true, "path": null, "body": { "value": "--TESTING--", "format": null, "summary": null } }, "relationships": { "type": { "data": { "type": "node_type--node_type", "id": "8bae5c5c-697d-4b8a-ab22-b72e895a3b24" }, "links": { "self": "https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/jsonapi/node/page/api_test-unpublished-page-content/relationships/type", "related": "https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/jsonapi/node/page/api_test-unpublished-page-content/type" } }, "uid": { "data": { "type": "user--user", "id": "4d7eb3c7-db6d-4a01-8b3d-7d706d314f87" }, "links": { "self": "https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/jsonapi/node/page/api_test-unpublished-page-content/relationships/uid", "related": "https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/jsonapi/node/page/api_test-unpublished-page-content/uid" } }, "revision_uid": { "data": { "type": "user--user", "id": "4d7eb3c7-db6d-4a01-8b3d-7d706d314f87" }, "links": { "self": "https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/jsonapi/node/page/api_test-unpublished-page-content/relationships/revision_uid", "related": "https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/jsonapi/node/page/api_test-unpublished-page-content/revision_uid" } }, "moderation_state": { "data": { "type": "moderation_state--moderation_state", "id": "1a5f02e6-3f14-46a7-a40c-65590c8729a9" }, "links": { "self": "https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/jsonapi/node/page/api_test-unpublished-page-content/relationships/moderation_state", "related": "https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/jsonapi/node/page/api_test-unpublished-page-content/moderation_state" } }, "scheduled_update": { "data": [ ] } }, "links": { "self": "https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/jsonapi/node/page/api_test-unpublished-page-content" } }, ...

That's pretty verbose. We could simplify the response by adding the "fields" parameter. In this example, we only want the "title" and "created" fields:

curl --request GET \  --url https://example.com/jsonapi/node/page\ ?fields[node--page]=title,created # Note that I'm using `[` and `]` here for clarity. These characters need to be # encoded with `%5B` and `%5D` respectively if you want to actually use these # examples.

Which would return something like this:

{ "data": [ { "type": "node--page", "id": "0bee8eb7-0f06-4986-9ca0-e340021a0af3", "attributes": { "title": "A Page", "created": 1502985175 }, "links": { "self": "https://{DOMAIN.COM}/jsonapi/node/page/0bee8eb7-0f06-4986-9ca0-e340021a0af3" } }, { "type": "node--page", "id": "4d7eb3c7-db6d-4a01-8b3d-7d706d314f87", "attributes": { "title": "Another Page", "created": 1502985175 }, ... Getting a specific piece of content

We can request a specific piece of content by specifying its UUID in the URL:

curl --request GET \  --url https://example.com/jsonapi/node/page/0bee8eb7-0f06-4986-9ca0-e340021a0af3

 Which would return something like this (but more verbose since we didn't use the "field" parameter):

{ "data": { "type": "node--page", "id": "0bee8eb7-0f06-4986-9ca0-e340021a0af3", "attributes": { "title": "A Page", "created": 1502985175 }, "links": { "self": "https://example.com/jsonapi/node/page/0bee8eb7-0f06-4986-9ca0-e340021a0af3" } }, "links": { "self": "https://example.com/jsonapi/node/page/0bee8eb7-0f06-4986-9ca0-e340021a0af3?fields%5Bnode--page%5D=title%2Ccreated" } } Getting a token

You will need to provide an access token for any request that anonymous users are not authorized to execute. Tokens are granted via the "/oauth/token" endpoint, and requests for a token must include a client_id, client_secret, username, and password. OAuth clients inherit the permissions of standard Drupal user roles by selecting one or more roles on the client's configuration form, under "Scopes". A typical setup would involve the following steps:

  1. Create a Drupal role ("/admin/access/roles") with the permissions you want the consuming app to be allowed to perform.
  2. Create a Drupal user ("/admin/people/create") that the API will use and assign that user the role you just created.
  3. Create an OAuth2 client ("/admin/config/people/simple_oauth/oauth2_client/add") and assign it the same role as the user you just created via the Scopes section.

Once that's done, you can use the following to obtain an access token, where:

  • CLIENT_ID = The OAuth2 client UUID, displayed after creation of the client in Step 3 at "/admin/access/clients"
  • SECRET = The "New Secret" you chose when creating the client  in Step 3
  • USERNAME = The Drupal username of the user you created in Step 2
  • PASSWORD = The password you gave the Drupal user in Step 2
curl -X POST -d \ "grant_type=password\ &client_id={CLIENT_ID}\ &client_secret={SECRET}\ &username={USERNAME} &password={PASSWORD}"\ https://example.com/oauth/token

Which should generate a response like this:

{ "token_type": "Bearer", "expires_in": 300, "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz...", "refresh_token": "def50200bdb9093a7a6cc837dhcd1..." }

If you want to give it a try without your own sandbox setup, Headless Lightning has a nightly build deployed to https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com with a client and user preconfigured. So you should be able to use the "/oauth/token" endpoint there to get a valid token to our sandbox if you're curious.

Give it a try! Copy and paste the following into a terminal window:

curl --request POST \ --data "grant_type=password\ &client_id=api_test-oauth2-client\ &client_secret=oursecret\ &username=api-test-user\ &password=admin"\ https://headlessnightlytfrimmmkug.devcloud.acquia-sites.com/oauth/token Using a token

Once you have a token, it's easy to get data that anonymous users aren't authorized to access. Just add an Authorize header to your request, like so (replacing {ACCESS_TOKEN} with the access_token value in the /oauth/token response):

--header 'authorization: Bearer {ACCESS_TOKEN}'

So let's say we wanted to get a specific piece of content just like the "Get a specific piece of content" example above. But in this case, the content is unpublished and therefore anonymous users won't be able to access it. Given that the token was acquired:

  1. For an OAuth client that has a scope with the "View unpublished content" permission
  2. For user account that has a role with the same permission

We can successfully make the same request for an unpublished piece of content if we include the token in an authorization header like this:

curl --request GET \ --header 'authorization: Bearer {ACCESS_TOKEN}'\ --url https://example.com/jsonapi/node/page/api_test-unpublished-page-content # Where `api_test-unpublished-page-content` is the UUID of some piece of # unpublished content

Note how this request is identical to the anonymous request above except that it:

  1. Requests a resource that requires authorization
  2. Includes an "authorization" header

Given the authorization header, Content API will authenticate the request and then authorize it (or not) based on the permissions of the associated client and user.

Creating content

You can create new content by sending a POST request to "jsonapi/{entity-type}/{bundle}". You'll need to include a specific Content-Type header, and most configurations will require Authorization as well since anonymous users usually can't create content. For example:

curl --request POST \ --data '{"data": {"type": "node--page","attributes": {"title": "Created via JSON API"}}}'\ --header 'Content-Type: application/vnd.api+json'\ --header 'authorization: Bearer {ACCESS_TOKEN}'\ --url https://example.com/jsonapi/node/page Content vs Configuration Entities

Drupal makes a distinction between Content and Configuration entities. Sometimes content entities are further distinguished as being renderable and/or bundle-able. Content API makes no such distinctions. If your API client/user have permission to interact with an entity, it can do so through the API. That means you can do things like add fields to a content type via the API, or edit a moderation state transition.

Headless Lightning

Everything described here can be done with Lightning. But if you're building a decoupled application, you might want to check out Headless Lightning, which has a few additional features (and a few features removed) which make it more suitable for decoupled applications.

Categories: Drupal

Mediacurrent: Webinar Recap: Estimating Web Projects

17 August 2017 - 8:33am

Everyone knows that process is important, but we have all gotten lost in the rush of daily tasks.

In our latest webinar, Project Management expert Rob McBryde and Vice President of Client Services James Rutherford shared how building and following a process for estimating web projects has driven success for their clients.

Categories: Drupal

Ben's SEO Blog: Headless Drupal and SEO: What Marketers Need to Know

17 August 2017 - 8:12am

Decoupled—or “headless”—content management systems have been trending in the last few years. This web development strategy, in its most basic form, is a “write once, publish anywhere” technology that separates the content from the presentation layer. Well, um...what the heck does that mean? It means that you can publish a piece of content and then use different systems to display that blog post on a computer, a mobile device, a voice-based system like Amazon’s Alexa, or even a smart watch. Basically, it allows developers to write to many different platforms without having to tediously recreate the wheel each time. (I think…)

It is a hot topic in the Drupal community. In fact, Acquia is holding Decoupled Developer Days this weekend (August 19-20 in NYC). Much of the conversation... Read the full article: Headless Drupal and SEO: What Marketers Need to Know

Categories: Drupal

Agiledrop.com Blog: AGILEDROP: Global Drupal Training Days are near

16 August 2017 - 9:52pm
From time to time, we check Drupical. It's a website, where »you can Find Drupal events with ease!« With the help of it, we already presented you Drupal Camps, Virtual Drupal Camps, DrupalCons, Mini Drupal Camps and Global Drupal Sprint week. One of the nearest events is Drupal Introduction Workshop, listed on Trainings, so we’ll take a look at Drupal Trainings. More specifically, Global Drupal Training Days. To be completely fair, we presented Global Drupal Sprint Week a little late last time. We will not be making the same »mistake« again, so we'll look at the Drupal Global Training Days… READ MORE
Categories: Drupal

myDropWizard.com: Drupal 6 security update for Views

16 August 2017 - 11:28am

As you may know, Drupal 6 has reached End-of-Life (EOL) which means the Drupal Security Team is no longer doing Security Advisories or working on security patches for Drupal 6 core or contrib modules - but the Drupal 6 LTS vendors are and we're one of them!

Today, there is a Moderately Critical security release for the Views module to fix an Access Bypass vulnerability.

The Views module enables you to create custom displays of Drupal data.

When creating a View, you have the option to enable the use of AJAX. The Views module does not restrict access to the AJAX endpoint to only Views configured to use AJAX. This is mitigated by having access restrictions on the view.

See the security advisory for Drupal 7 for more information.

Here you can download the Drupal 6 patch for 6.x-2.x or 6.x-3.x.

If you have a Drupal 6 site using the Views module, we recommend you update immediately.

If you'd like all your Drupal 6 modules to receive security updates and have the fixes deployed the same day they're released, please check out our D6LTS plans.

Note: if you use the myDropWizard module (totally free!), you'll be alerted to these and any future security updates, and will be able to use drush to install them (even though they won't necessarily have a release on Drupal.org).

Categories: Drupal

Abhishek Lal | GSoC Blog: Examples for Developer #11 Week of Coding

16 August 2017 - 8:21am
Examples for Developer #11 Week of Coding Abhishek Lal B Wed, 08/16/2017 - 20:51
Categories: Drupal

Lullabot: Indexing content from Drupal 8 using Elasticsearch

16 August 2017 - 8:04am

Last week, a client asked me to investigate the state of the Elasticsearch support in Drupal 8. They're using a decoupled architecture and wanted to know how—using only core and contrib modules—Drupal data could be exposed to Elasticsearch. Elasticsearch would then index that data and make it available to the site's presentation layer via the Elasticsearch  Search API

During my research, I was impressed by the results. Thanks to Typed Data API plus a couple of contributed modules, an administrator can browse the structure of the content in Drupal and select what and how it should be indexed by Elasticsearch. All of this can be done using Drupal's admin interface.

In this article, we will take a vanilla Drupal 8 installation and configure it so that Elasticsearch receives any content changes. Let’s get started!

Downloading and starting Elasticsearch

We will begin by downloading and starting Elasticsearch 5, which is the latest stable release. Open https://www.elastic.co/downloads/elasticsearch and follow the installation instructions. Once you start the process, open your browser and enter http://127.0.0.1:9200. You should see something like the following screenshot:

undefined

Now let’s setup our Drupal site so it can talk to Elasticsearch.

Setting up Search API

High five to Thomas Seidl for the Search API module and Nikolay Ignatov for the Elasticsearch Connector module. Thanks to them, pushing content to Elasticsearch is a matter of a few clicks.

At the time of this writing there is no available release for Elasticsearch Connector, so you will have to clone the repository and checkout the 8.x-5.x branch and follow the installation instructions. As for Search API, just download and install the latest stable version.

Connecting Drupal to Elasticsearch

Next, let’s connect Drupal to the Elasticsearch server that we configured in the previous section. Navigate to Configuration > Search and Metadata > Elasticsearch Connector and then fill out the form to add a cluster:

undefined

Click 'Save' and check that the connection to the server was successful:

undefined

That’s it for Elasticsearch Connector. The rest of the configuration will be done using the Search API module.

Configuring a search index

Search API provides an abstraction layer that allows Drupal to push content changes to different servers, whether that's Elasticsearch, Apache Solr, or any other provider that has a Search API compatible module. Within each server, search API can create indexes, which are like buckets where you can push data that can be searched in different ways. Here is a drawing to illustrate the setup:

undefined

Now navigate to Configuration > Search and Metadata > Search API and click on Add server:

undefined

Fill out the form to let Search API manage the Elasticsearch server:

undefined

Click Save, then check that the connection was successful:

undefined

Next, we will create an index in the Elasticsearch server where we will specify that we want to push all of the content in Drupal. Go back to Configuration > Search and Metadata > Search API and click on Add index:

undefined

Fill out the form to create an index where content will be pushed by Drupal:

undefined undefined undefined

Click Save and verify that the index creation was successful:

undefined

Verify the index creation at the Elasticsearch server by opening http://127.0.0.1:9200/_cat/indices?v in a new browser tab:

undefined

That’s it! We will now test whether Drupal can properly update Elasticsearch when the index should reflect content changes.

Indexing content

Create a node and then run cron. Verify that the node has been pushed to Elasticsearch by opening the URL http://127.0.0.1:9200/elasticsearch_index_draco_elastic_index/_search, where elasticsearch_index_draco_elastic_index is obtained from the above screenshot:

undefined

Success! The node has been pushed but only it’s identifier is there. We need to select which fields we do want to push to Elasticsearch via the Search API interface at Configuration > Search and Metadata > Search API > Our Elasticsearch index > Fields:

undefined

Click on Add fields and select the fields that you want to push to Elasticsearch:

undefined

Add the fields and click Save. This time we will use Drush to reset the index and index the content again:

undefined

After reloading http://127.0.0.1:9200/elasticsearch_index_draco_elastic_index/_search, we can see the added(s) field(s):

undefined Processing the data prior to indexing it

This is the extra ball: Search API provides a list of processors that will alter the data to be indexed to Elasticsearch. Things like transliteration, filtering out unpublished content, or case insensitive searching, are available via the web interface. Here is the list, which you can find by clicking Processors when you are viewing the server at Search API :

undefined When you need more, extend from the APIs

Now that you have an Elasticsearch engine, it’s time to start hooking it up with your front-end applications. We have seen that the web interface of the Search API module saves a ton of development time, but if you ever need to go the extra mile, there are hooks, events, and plugins that you can use in order to fit your requirements. A good place to start is the Search API’s project homepage. Happy searching!

Acknowledgements

Thanks to:

Categories: Drupal

Acquia Developer Center Blog: Decoupled Drupal Technologies and Techniques

16 August 2017 - 7:24am

We've got a new installment in the decoupled Drupal project we're working on with Elevated Third and Hoorooh.

The project we're documenting was one we worked on for Powdr Resorts, one of the largest ski operators in North America.

The first installment in the series was A Deep Dive into a Decoupled Drupal 8 Project.

Tags: acquia drupal planet
Categories: Drupal

Amazee Labs: Join us for Tour de Drupal Vienna

16 August 2017 - 6:54am
Join us for Tour de Drupal Vienna

Cycling is a great way to travel, experience new things and meet like-minded people. Join us for Tour de Drupal Vienna and let’s cycle together to DrupalCon!

Josef Dabernig Wed, 08/16/2017 - 15:54

On Sunday, 24 September we plan to start at 8am from Krems and travel to Tulln. At 11am we’ll arrive in Tulln and meet at the Weshapers office for some drinks & BBQ.

In the afternoon at 2pm, we plan to leave Tulln and cycle the remaining 40 km to Vienna to finally arrive in Vienna.

To sum-up, the meeting points are:

Source

The arrival is planned for Sunday, 24 September at 5pm in front of the big wheel in Vienna at Kaiserwiese.

How to get there?

There are many cycling routes that lead to Vienna. We created a map that currently highlights roads from east and west along the Danube. Also, check out the EuroVelo routes, bessone summarized the interesting ones for Vienna.

If you just wanna join for the last day, it’s a 30-minute train ride from Vienna to Tulln or 1:10 from Vienna to Krems and you can bring your bike on the train. Check ÖBB to book your train ticket.

Convinced? Tell us you are coming!

Categories: Drupal

Valuebound: How to push clean code by following coding standards effectively using git pre-commit hook?

16 August 2017 - 6:26am

Pushing clean codes is not every one cups of tea, it needs extensive knowledge and practice. Before a website go live, it needs to pass certain standards and checks in order to deliver quality experience. Certainly, a clean website is a demand of almost every client and it should be. 

In this blog post, you will learn why we need to implement git pre-commit hook? how it works? Simultaneously, we will also attempt to implement working examples in order to have better understanding.

Why we need to implement git pre-commit hook

Any website going live should pass certain standards and checks. If the web is built on any framework, then these checks are mandatory. How to ensure all developers are committing clean code? One way is to do code review,…

Categories: Drupal

Blair Wadman: Create a modal in Drupal 8 in a custom module

16 August 2017 - 5:54am

Modal dialogs are incredibly useful on websites as they allow the user to do something without having to leave the web page they are on. Drupal 8 now has a Dialog API in core, which greatly reduces the amount of code you need to write to create a modal dialog. Dialogs in Drupal 8 leverage jQuery UI.

In the second part of this series on modal dialogs in Drupal 8, we are going to go a step further from last week by creating the modal in a custom module.

Categories: Drupal

Mediacurrent: Integrating Amazon Alexa With a Drupal 8 Site

16 August 2017 - 5:31am

If you’ve ever used Alexa, it may seem like it must be extremely complicated to get her to respond like she does. However, if you have your content inside Drupal, it’s not terribly difficult to get her to utilize that data for your own custom Alexa skill. Let’s take a look at how to accomplish that.
 

Categories: Drupal

Amazee Labs: Extending GraphQL: Part 1 - Fields

16 August 2017 - 3:36am
Extending GraphQL: Part 1 - Fields

The last blog post might have left you wondering: "Plugins? It already does everything!". Or you are like one of the busy contributors and already identified a missing feature and can't wait to take the matter into your own hands (good choice).

In this and the following posts we will walk you through the extension capabilities of the GraphQL Core module and use some simple examples to show you how to solve common use cases.

Philipp Melab Wed, 08/16/2017 - 12:36

I will assume that you are already familiar with developing Drupal modules and have some basic knowledge of the Plugin API and Plugin Annotations.

The first thing you will want to do is disabling GraphQL schema and result caches. Add these parameters to your development.services.yml:

parameters: graphql.config: result_cache: false schema_cache: false

This will make sure you don't have to clear caches with every change.

As a starting point, we create an empty module called graphql_example. In the GitHub repository for this tutorial, you will find the end result as well as commits for every major step.

Diff: The module boilerplate

A simple page title field

Can't be too hard, right? We just want to be able to ask the GraphQL API what our page title is.
To do that we create a new class PageTitle in the appropriate plugin namespace Drupal\graphql_example\Plugin\GraphQL\Fields.

Let's talk this through. We've created a new derivation of FieldPluginBase, the abstract base class provided by the graphql_core module.

It already does the heavy lifting for integrating our field into the schema. It does this based on the meta information we put into the annotation:

  • id: A unique id for this plugin.
  • type: The return type GraphQL will expect.
  • name: The name we will use to invoke the field.
  • nullable: Defines if the field can return null values or not.
  • multi: Defines if the field will return a list of values.

Now, all we need to do is implement resolveValues to actually return a field value. Note that this method expects you to use the yield keyword instead of return and therefore return a generator.

Fields also can return multiple values, but the framework already handles this within GraphQL type definitions. So all we do is yield as many values as we want. For single value fields, the first one will be chosen.

So we run the first GraphQL query against our custom field.

query { pageTitle }

And the result is disappointing.

{ "data": { "pageTitle": null } }

Diff: The naive approach

The page title is always null because we extract the page title of the current page, which is the GraphQL API callback and has no title. We then need a way to tell it which page we are talking about.

Adding a path argument

Lucky us, GraphQL fields also can accept arguments. We can use them to pass the path of a page and get the title for real. To do that, we add a new annotation property called arguments. This is a map of argument names to the argument type. In our case, we added one argument with name path that expects a String value.

Any arguments will be passed into our resolveValues method with the $args parameter. So we can use the value there to ask the Drupal route matcher to resolve the route and create the proper title for this path.

Let's try again.

query { pageTitle(path: "/admin") }

Way better:

{ "data": { "pageTitle": "Administration" } }

Congratulations, MVP satisfied - you can go home now!

Diff: Using arguments

If there wasn't this itch every developer has when the engineering senses start to tingle. Last time we stumbled on this ominous route field that also takes a path argument. And this ...

query { pageTitle(path: "/node/1") route(path: "/node/1") { ... } }

... smells like a low hanging fruit. There has to be a way to make the two of them work together.

Attaching fields to types

Every GraphQL field can be attached to one or more types by adding the types property to its annotation. In fact, if the property is omitted, it will default to the Root type which is the root query type and the reason our field appeared there in the first place.

We learned that the route field returns a value of type Url. So we remove the argument definition and add a types property instead.

This means the $args parameter won't receive the path value anymore. Instead, the $value parameter will be populated with the result of the route field. And this is a Drupal Url object that we already can be sure is routed since route won't return it otherwise. With this in mind, we can make the solution even simpler.

Now we have to adapt our query since our field is nested within another.

query { route(path: "/admin") { pageTitle } }

Which also will return a nested result.

{ "data": { "route": { "pageTitle": "Administration" } } }

The price of a more complex nested result might seem high for not having to pass the same argument twice. But there's more to what we just did. By attaching the pageTitle field to the Url type, we added it wherever the type appears. Apart from the route field this also includes link fields, menu items or breadcrumbs. And potentially every future field that will return objects of type Url.
We just turned our simple example into the Swiss Army Knife (pun intended) of page title querying.

Diff: Contextual fields

I know what you are thinking. Even an achievement of this epic scale is worthless without test coverage. And you are right. Let's add some.

Adding tests

Fortunately the GraphQL module already comes with an easy to use test base class that helps us to safeguard our achievement in no time.

First, create a tests directory in the module folder. Inside that, a directory called queries that contains one file - page_title.gql - with our test query. A lot of editors already support GraphQL files with syntax highlighting and autocompletion, that's why we moved the query payload to another file.

The test itself just has to extend GraphQLFileTestBase, add the graphql_example module to the list of modules to enable and execute the query file.

Diff: Adding a test

Wrap-Up

We just created a simple field, passed arguments to it, learned how to attach it to an already existing type and finally verified our work by adding a test case. Not bad for one day's work. Next time we will have a look at Types and Interfaces, and how to use them to create fields with complex results.

Categories: Drupal

Pages