Jul 18 2018
Jul 18

At Droptica, remote work is something ordinary. From the very first day, we had two offices in Wrocław and Gdańsk. Recently, we also opened our third office in Rzeszów. Every day, developers, testers, graphic designers and other specialists work together in each of these locations. In addition, 90% of our clients come from abroad, like in the case of most software houses. Throughout several years, we have developed methods of effective and efficient cooperation in a dispersed team. We are constantly improving our work model, testing new tools and ways of working. In this article, you will learn how our system works today.

Project management support system

Since the beginning of Droptica’s existence, we have been using Redmine. Redmine had several add-ons, including Backlogs module supporting work in the Scrum model. These days, we are using Jira, since it works even better with Scrum. Both systems help us to control what is going on with the projects. Each of the projects is divided into sprints, and each sprint is divided further into specific tasks. All information about the realisation of every task is saved and stored in Jira. Our clients also have access to our Jira for full transparency. In our opinion, such a system is a necessity. Without it, it would be difficult, if not impossible, to control what is going on with the project, especially in the case of projects running for many months. E-mail communication is completely unsuitable for this purpose.

Two communication speeds

Project management support systems are very useful, but not sufficient for efficient implementation of the project. Members of the team must be able to communicate comfortably and quickly. If the team works in one office, it is enough to just talk to somebody and ask. In the case of a dispersed team, this issue becomes quite complex. Writing an e-mail or adding a ticket in Jira to ask a quick question takes time. Most often, you have to do the following:

  • open Jira;
  • find a project;
  • find the right task;
  • add a comment;
  • check in a while if there is an answer;

This process often takes far more time than simply asking the question and getting an answer, especially when it’s a “yes/no” type of question.  

At Droptica, we solve this problem by communicating using Slack. Thanks to this application, our distributed team works as if all the members were located in one office. We communicate quickly and efficiently. We eliminate unnecessary e-mails, phone calls and video conferences. The number of comments to tasks in Jira also goes way down – this is helpful because they often make it difficult to analyse the status of work on a given task. 

Slack at Droptica

We set up several channels for each project. Channels are used to eliminate as many notifications and as much communication via e-mails as possible and to split up messages thematically.

Most often, we set up the following chat channels:

  • projectname chat – a channel for internal communication regarding the project. This channel is used by the entire development team, as well as project support team (DevOps, testers, etc.);
  • projectname client - a channel available to the client and the development team. This channel is a place for communicating with the client, asking quick questions about tasks, setting up meeting dates, calls, etc;
  • channels with notifications from the systems used in connection with a given project, such as Jira, Jenkins, GitHub, Bitbucket, etc. Usually, each system gets its own channel. Every person can join channels that are important for them and eliminate notifications that are not important or redundant, for example, a graphic designer does not need to read GitHub notifications.

Before Slack, we used group chats on Skype, then we moved on to HipChat for a while. We found Slack to be the best solution that fits our needs perfectly and we do not plan to move to any other solution any time soon. It is also important that our clients often already use Slack, which makes it easy for them to join our channels as another organisation.

Other tools supporting remote working

Daily Scrum

There is no Scrum without Daily Scrum. In a dispersed team, it is necessary to conduct a video conference once a day. Sometimes such calls are also attended by the representative of the client, who is often hundreds or thousands of miles away from our offices. We conduct these meetings using several tools, depending on the preferences of the team or our client. Usually, we go for Google Hangouts Meet, but sometimes we resort to Zoom.us and Skype For Business.

Scrum Retrospective

For this purpose, we use a simple Google Docs sheet. We have a sheet with the following columns:

  • drop - what we should stop doing if it's possible;
  • keep - what is good and what we should keep doing;
  • improve - what needs to be improved;
  • add - what we need to add in order to better carry out the work on the project.

The worksheet contains a history of all retrospectives in the form that is easy to view and edit. The document is available to all team members, regardless of their location. This is working very well for us.

Code review

We review the code on GitHub or Bitbucket, depending on the project. These systems allow to easily browse the code and add comments to selected script lines. There is no need for one person to come to the other person's desk to view the quality of the code.

We also have several internal tools and scripts for automating tests that support Drupal development.

Good remote working practices

In my opinion, it is not possible to rely only on communication via e-mail or Jira. Video conferences and telephone calls are necessary to better understand each other. This greatly improves communication within the development team and between the client and the team. One could say that working according to the Scrum methodology forces us to do so. Every day, we carry out Daily Scrum in the form of a video chat. We also often have video calls with customers, for example during the Sprint Review or during the Backlog Refinement. Every once in a while, we also meet with the client at our office or we pay them a visit.

It is also important for the communication process to work in a way that does not disturb others too often. Slack is a very useful tool, but it can also lead to too many unnecessary messages, which can be distracting and interrupt work. The team should be aware of this and use Slack only when necessary and send messages only to those who need them. We try to never involve people whose presence is not necessary in a given case.

Is remote working better than working in one office?

Having the entire team working in one office certainly makes communication much easier. However, it also has its drawbacks – for example, it makes it much easier to disturb somebody while working with unnecessary discussions. Sometimes this can reduce productivity.

At Droptica we combine remote work with office work, which enables us to take advantage of both models. If necessary, we build teams working at just one office.
More than one location gives us a competitive advantage because we have access to more specialists from three cities and their general areas. This allows us to build great development teams for our clients.

The fact that Droptica has multiple offices also forces all of our team members to learn how to work remotely. That’s why all of our experts know how to work with a remote client right away.

Summary

At Droptica, we developed a remote working system that works very well for us. I think that such a model is by no means worse than working in one office, additionally, it also offers many benefits. If you are looking for a team of Drupal, PHP, Symfony or ReactJS experts, we will be happy to assist you and show you that communication with a remote team can also be great.

Jul 18 2018
Jul 18

Droptica helps clients from all over the world to complete and implement their projects. Each of these clients has already developed their way of working. Everyone is different. In this article, I have collected the most common ways and systems of cooperation between Droptica and our clients.

Why do we work a little differently with every client?

We are Agile. We always want to maximise the results of our work, so our development team always adjusts and adapts their way of working to the client’s needs.
The elements that are adapted and changed the most often include:

  • project implementation methods (SCRUM, Kanban, etc.);
  • number of people in the team;
  • roles in the team (backend developers, frontend developers, QA, UX/UI, etc.);
  • the method of communication; Tools: JIRA, Slack, telephone or video calls, meetings;
  • frequency of communications;
  • communication channels (who, with whom);
  • implementation standards (some clients consider application performance to be the most important, others focus on implementing and providing new functionalities on a regular basis, while another group focuses on aesthetics and want their application to look good).

On the basis of these factors, I have identified several models of cooperation with clients, which are used the most often at Droptica.

Model 1: Product Owner at the client, with the rest of the team at Droptica

This is probably the most popular model employed at Droptica. We use it mainly when the end client comes to us. In most cases, the client already has a web system based on Drupal, Symfony or React and needs developers to develop the system further. Product Owner has a vision of application development and looks for a team that can efficiently perform the envisioned tasks.

In this model, we have a great impact on the development of the system. Our team not only performs assigned programming tasks but also proposes directions of development of the system and suggests improvements. In addition to developing basic functionalities, we also design user interfaces (UX/UI) and often carry out A/B tests that show us the best solutions for the client.

We use this model to develop WydawnictwoWAM.pl website. This is what the client has to say about us and about working in this model: 

"We established cooperation with Droptica around two years ago to develop our online store available at http://www.wydawnictwowam.pl. Both the quality of all the works carried out, as well as our cooperation were stellar. The technical solutions suggested and implemented by Droptica were a great help and often improved the value of our system, often exceeding our initial expectations. Cooperation with Droptica is characterised by very friendly, direct and precise communication on their part. Thanks to that, we were – and constantly are – able to define and detail all the tasks related to the development of our sales platform. We also appreciate their very clear settlement system, which allows us to better plan and allocate funds for development. In other words, we definitely recommend working with Droptica".

Model 2: Product Owner, QA, PM on the client’s side, software developers provided by Droptica

In this model, we provide our customers with solid development support. Most of the project planning and management process is carried out by the client, while our experts carry out specific development tasks.
It is a kind of cooperation that we usually go for with large companies and corporations, expanding their Drupal, PHP and ReactJS teams.
As a rule, in such a model we work on servers and project management systems provided by the client. We adapt to their processes.

Mixed models

Other models are usually combinations of the two models presented above. For example, Droptica provides not only developers but also testers, while the entire project is managed by the client. We also sometimes work on projects where we collaborate with other software developers from the client's company, working not as an independent development team, but a part of a larger team.

We are Agile

We are flexible regarding the form of cooperation with our clients; however, we like the first model the most. In that model, we take on a great deal of responsibility for the project and we are able to influence the direction of development together with the client. This gives us great satisfaction, and we offer numerous ideas for improving the system, which allows our clients to better achieve their business goals.

Would you like to learn more about our work models? Contact us at [email protected] and we'll be happy to talk to you.
 

 

Jul 10 2018
Jul 10
Drupal is fantastic for all sorts of websites and applications. It excels especially at large, complex content projects. If you know what you are doing, you can often cut development time substantially compared to other tools made for the same purpose.  Drupal's versatility, however, is a 2-edged sword. With great flexibility, extensive API and an abundance of modules created by the community, it takes a long time to get up to speed. Often there is not enough time on a project to go through Drupal's steep learning curve.  The more experienced your team is, the more benefits of Drupal you will reap and the less technical debt you will acquire, and the more successful your project will be in the end. Looking for a Drupal team There are a few critical elements you should consider when you are looking for to outsource a Drupal project:
Jul 10 2018
Jul 10

Drupal is fantastic for all sorts of websites and applications. It excels especially at large, complex content projects. If you know what you are doing, you can often cut development time substantially compared to other tools made for the same purpose. 

Drupal's versatility, however, is a 2-edged sword. With great flexibility, extensive API and an abundance of modules created by the community, it takes a long time to get up to speed. Often there is not enough time on a project to go through Drupal's steep learning curve. 

The more experienced your team is, the more benefits of Drupal you will reap and the less technical debt you will acquire, and the more successful your project will be in the end.

Looking for a Drupal team

There are a few critical elements you should consider when you are looking for to outsource a Drupal project:

Experience of the team and its members

It takes time to master Drupal. If you are building a large application, it is good to have at least one really experienced developer/software architect (three or more years of working with Drupal), who delivered in that time a few sizable projects. This person will work as your architect and gatekeeper. Planning architecture, choosing contrib modules and code reviews and helping others would be his daily routine.

The rest of the team also should have had at least some experience in using Drupal, unless you have time to train them. Drupal 8 is a bit easier to pick up by a developer who previously worked with an MVC framework like Symfony or Laravel, but it is still quite far from allowing Drupal newbies to just joining in and coding.  Six months for smaller to 1-2 years in larger applications would be a proper exposure.

Has the team worked together?

This one is not that critical, but having a team that uses similar tools and standards goes a long way towards ensuring that your application is built smoothly. Teams assembled "for one project" tend to do much poorlier than ones that had time to iron out their cooperation practices. 

You can circumvent many of the issues stemming from a distributed by a well-established automation of the software development process. It is though, and so much easier to introduce it if all devs are already used to it.

Communication

How will you communicate with the team? Ensure there will be a clear and easy communication between you and all of the team members directly. There is nothing worse on a project than long communication channels that distort information and extend communication time. 

Trust

Can you build trust? On a long project, it is essential to build a trustworthy relationship between you and the team.  If you feel there are any issues or ambiguous situations, it is better to clear them all before the project begins.

Availability and scaling

Can the team scale if needed? Often projects start small but then grow larger and require more resources. Will the team be able to increase in size or will you have to look for additional people?

The other side of the coin is turnover. An average turnover rate in a software company is about 10-20%. If your team consists of 5 people for a project that lasts a year, it is almost certain that someone will leave. Is the team able to provide a replacement that can start quickly? 

Access to specialist knowledge

If you hire a team of Drupal developers, it is also worth exploring if they will provide you easy access to other services or expertise that might come handy on the project now and then. On a typical Drupal assignment, you may have some tasks that might require:
 - a DevOps specialist (e.g., setting up environments, servers or CI infrastructure)
 - UX/design specialists
 - Quality assurance (testers) who can perform manual or write automated tests of your application

Project setup and delivery

When you have chosen your team, it’s time to set the project up.
I wrote an extensive blog post about organizing work on a software project so that delivery can run smoothly, even if there are multiple independent teams involved.  We are great proponents of automatization. It reduces the workload associated with getting everyone in sync about the current state of the code.

We also recommend using Agile methodologies, which are a fantastic approach to managing a software project. You can read more about how we manage software projects in our blog post about remote SCRUM teams.

Summary

Outsourcing software can bring about many benefits, including reduced cost, access to the specific experience or might just fill a void of specialists on your market.

Choosing the right team for the job is not an easy process. It makes sense to look for the right one, rather than to hire the cheapest or the first one you find. With the right team, you will be able to mitigate many risks that come from hiring external outsourcing provider, like cultural mismatch, communication issues or lack of motivation and deliver your project much quicker and at a reduced cost.
 

Jul 10 2018
Jul 10
React.js is a very popular JavaScript framework created by Facebook. It allows you to build beautiful, interactive and fast interfaces, with which users will fall in love. Drupal, on the other hand, is a fantastic CMS with you can build small, medium and huge websites.   Sometimes you want to pair the two frameworks together - offer sophisticated Drupal backend, and a slick, quick frontend based on React. That is when Drupal and React can come together. In this post, I will explore various methods of combining the technologies.
Jul 10 2018
Jul 10

React.js is a very popular JavaScript framework created by Facebook. It allows you to build beautiful, interactive and fast interfaces, with which users will fall in love. Drupal, on the other hand, is a fantastic CMS with you can build small, medium and huge websites.
 
Sometimes you want to pair the two frameworks together - offer sophisticated Drupal backend, and a slick, quick frontend based on React. That is when Drupal and React can come together.

In this post, I will explore various methods of combining the technologies.

Headless Drupal vs. embedded React

The primary choice you have to make when using React with Drupal is whether you want to use a "headless Drupal" approach where Drupal is only in the backend and React is the only interface user ever sees or whether you just want to add a React app to the Drupal website rendered by the Drupal templating engine. Let me elaborate.

Headless Drupal with React frontend

In a headless scenario, Drupal serves as a backend for a frontend application built in React. The systems are entirely separate and communicate via HTTP - eg. REST of GraphQL.

This option is best if you want to:

  • Create a Progressive Web App (PWA) for users on mobile devices.
  • Create a single page app that stores data in Drupal
  • Create an easy to use the access point to a subset of a big system built on Drupal. Say you have local agents who visit local stores and send screenshots of the merchandise display. They might need only an one easy to use interface without the complexity of your complete CRM of managing stores, which the office uses
  • Create a smaller website that just pulls some data off of a big website, e.g. only displays news from one section of a huge news magazine.

How to create a Headless Drupal app

If you chose headless Drupal, you then build a separate React application which communicates with the backend via HTTP requests, just as you would with any backend system. React then does not really care what is in the backed. It only needs to be able to use the exposed API. 

Facebook prepared a fantastic boilerplate React project to help you start.

When the React app is running, you then create endpoints in Drupal, which serve as data sources for your React app. Drupal 8 is a fantastic piece of software and comes packaged with a full REST API. You can find documentation on Drupal Rest API documentation page. Specifically, have a look at the REST UI module which enables you to create clean configurable endpoints for entities. 
We wrote a great post about setting up REST endpoints for a JavaScript application.

If you prefer to use GraphQL, there is a GraphQL module which is under active development and allows you to build GraphQL endpoints.

If headless Drupal is what you are after, it is also worth checking out an example headless project: the ContentaCMS, which is an entirely headless implementation of Drupal with popular frontend frameworks. The React implementation can be inspected here.

React app embedded in Drupal

Quite often you don't need a full headless implementation, but just want one or two highly interactive elements on a few pages of your website. It might be a very complicated form with many steps which works nicer without a page reload or a different UI element which is highly interactive and will work much nicer done in JavaScript. 

In that case, it makes much more sense to use React.js to create a component and embedded in a page that is served by Drupal. This way you can use all the Drupal greatness everywhere else, in example registration, rendering of fields, views etc.

How to embed  a React app in Drupal

For starters, you will add React library to your website, just like you would add any other js library (e.g. a jQuery or some other library for a slider or gallery). Depending on whether the script is required on every page, or is it part of a theme or a module, there are various ways in which you can add a js library to the website. I will not go to details, because there is a lot of good documentation here:
1. https://www.drupal.org/docs/8/api/javascript-api/add-javascript-to-your-theme-or-module
and 
2. https://www.drupal.org/docs/8/theming-drupal-8/adding-stylesheets-css-and-javascript-js-to-a-drupal-8-theme
 

A quick method, that is not recommended, but will work for testing purposes, is to just add the script tags to html.html.twig in your template:

<script crossorigin src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>

and your own script with the app.

<script src="https://www.droptica.com/paht/to/my/scripts/myreactapp.js"></script>

One caveat of an embedded app is that the only language you can use is Javascript. You can use neither JSX, nor TypeScript, which you might use when you create a headless app. This is because in a complete react app, Webpack or Babel transpile JSX or TypeScript into JavaScript. Here in our example, for the sake of simplicity, we are not using these tools. 

Tip: To be able to use JSX you would have to use Webpack first to compile your JavaScript file and then add it to Drupal. A good approach then would be to use the create-react-app repo to start and then just copy over the resulting js file created after transpilation and embed that. You would then not need to embed react.js separately because it is already bundled in transpilation. Setting this up, however, so that auto refresh would work and the file would be copied to Drupal, is a bit more complicated and therefore we are skipping it.

Coming back to our example, the first thing to you have to create is an HTML tag in your markup in which the React app will live. It can be a div rendered in a block or by a custom controller on a separate route.

<div id="myreactapp" />

In myractapp.js create your app.

ReactDOM.render(
React.createElement(MyApp, {title: 'Hello World!'}),
  document.getElementById('myreactapp');
);

Done! You have a react app embedded in a Drupal page. You can get data for it from a REST API like you would in the Headless example, or you can use the drupalSettings global for your initial data set.

function Welcome(props) {
 if(props.isfront == true) {
return <h2> Welcome on front page<h2>
}
else{
return <h2> Welcome on another page </h2>
}

ReactDOM.render(
React.createElement(Welcome, {isfront: drupalSetting.path.isFront}),
    document.getElementById('myreactapp');
);

Just remember that if you ever want to save changes to any data in Drupal, you still need to create an endpoint and push the changes there. 

That is it! Combining React and Drupal is as easy as pie.
Enjoy!

Jul 04 2018
Jul 04
Your development team constantly makes the same mistakes and does not improve the quality of its work. Are you familiar with this issue? If so, we have a solution for you and it’s really simple – it’s called Sprint Retrospective.  What is Sprint Retrospective? This is one of the meetings in the SCRUM methodology. The meeting takes place on a regular basis, at the end of each sprint. At Droptica, we hold a meeting once every two weeks. During the meeting, the development team analyses the previous sprints and deliberates about what can still be improved – how to eliminate errors and blockers, and how to speed up work.
Jul 04 2018
Jul 04

Your development team constantly makes the same mistakes and does not improve the quality of its work. Are you familiar with this issue? If so, we have a solution for you and it’s really simple – it’s called Sprint Retrospective. 

What is Sprint Retrospective?

This is one of the meetings in the SCRUM methodology. The meeting takes place on a regular basis, at the end of each sprint. At Droptica, we hold a meeting once every two weeks. During the meeting, the development team analyses the previous sprints and deliberates about what can still be improved – how to eliminate errors and blockers, and how to speed up work.

How does the client benefit from this?

The meeting usually takes no more than 15-60 minutes. A Sprint Retrospective usually has anywhere from three to six participants, depending on the size of the team carrying out the given project. Other companies might implement this process in another way, shape or form. It's easy to calculate that this meeting can cost the client at least several man-hours. Is it worth it? 

Yes – without question! During each meeting, the team proposes improvements and agrees to implement some of them starting with the next sprint. In many cases, these improvements reduce the lead time. The change meeting is held once, and the improvement is applied continuously throughout the subsequent sprints. After a number of sprints, we can achieve pretty sizeable time and money savings.

How do we do Sprint Retrospective at Droptica?

For this purpose, we use a Google Docs – Spreadsheet. There are five columns in the document:

  1. Date;
  2. DROP – what we should stop doing;
  3. KEEP – what we should keep doing;
  4. IMPROVE – what needs to be improved;
  5. ADD – what needs to be added.

During the meeting, each person proposes various improvements that they would like to see and suggests what should be removed, corrected, added, and so on. Once everyone has spoken, the team chooses which of the proposals they want to implement with the next sprint. We try to choose 1-3 suggestions and implement them, so as to avoid making too big changes. We also identify the change owner, who is responsible for implementing the specific change. 

Examples of improvements in software development and DevOps

Below, you can find a list of selected improvements suggested throughout several of our projects. 

  • We run automatic tests more often in order to squish all bugs faster. This allows us to avoid unpleasant surprises a minute before the deployment;
  • We will improve the speed of building a new version of the website on the test server by reducing the database size by about 90%;
  • Before we start working on a task, we talk about business goals, as well as carrying out the tasks from the software development standpoint in order to maintain consistency of the whole application and to choose solutions that are optimal for the project;
  • Code review should be carried out by at least two people;
  • We use git-flow and each task is carried out on its own branch. All tests and code reviews are done on this branch. After these are carried out, we merge the branch with the main development branch; 

Examples of improvements regarding work organisation

  • Every day we send a short message to the client (Product Owner) on Slack with a summary of what we have done since yesterday and what we are going to do today;
  • We break up the tasks in Jira into smaller ones, so that one task takes no longer than 3-4 hours. We can then better follow the progress of the work and quickly react to delays; 
  • If during a sprint it turns out that the task is more difficult than we had anticipated, we change the Story Points for the task; 
  • We continuously update our documentation. We adhere to the principle that if a question is asked at least twice, it should be added to the documentation; 
  • The computer used for video calls must always be connected to the Internet with an Ethernet cable – this removes the annoyance of dropped and lagging video calls;
  • In many projects, we have also removed the deployment from DoD – usually, these deployments take place once every two weeks or once a month, sometimes even on the client’s side. When we have a weekly sprint, this should not block us from closing the task.
  • Planning with taking support into consideration – on the basis of previous sprints we know how much time we spend on things that cannot be planned (for example hotfixes added by the client);

Summary

At Droptica, Scrum Retrospective gave us some tangible effects. I highly recommend this way to objectively look back into the past to every team, even if they do not use SCRUM in project management. You can simply schedule a 1-2-hour meeting in the calendar once every two weeks and talk about what can be improved. You can achieve pretty significant results in just a few weeks. Try it for yourself! 

Jun 13 2018
Jun 13

The deadline is today. A remote development team have worked for several weeks on your software. You obtain the long-awaited access to the system. You check it and you are not satisfied with the achieved results.
All that was needed to avoid this problem is a team with experience in technology and working using SCRUM.

What is SCRUM

Wikipedia defines SCRUM as an agile framework for managing work. It is an approach used in many companies to develop software. Full definition can be found here https://en.wikipedia.org/wiki/Scrum

SCRUM solves most of the problems arising during software development

This is my opinion and many people agree with it. I have been developing commercial projects since 2008. I started as a programmer. Currently, I am supervising high-level projects.

Introduction of the SCRUM method in Droptica solved most of the problems. Which ones exactly?
Here are the most important of them:

  • The client was not regularly informed about the progress of works – the client was not satisfied. Sprints, review, backlog refinement – all this compels a constant contact with the client
  • The tasks were not thought through before starting them, therefore they took a long time to finish – the client was not satisfied. Backlog refinement and planning – these events ensure that the team has to really ponder on completing each task.

SCRUM saves money

You can ask yourself: how is that possible if you do not know the exact duration and cost of the project at its beginning? The answer can be found in the previous paragraph:

  • Regular meetings with the client (Product Owner) force them to think about which tasks are actually needed and which can be rejected.
  • Analysis of tasks by the team together with the PO, often allows to come up with better ways to implement or reject them.

SCRUM is often called the art of maximising work not done. You maximise the rejection of the tasks that are unnecessary from the point of view of your business. You do only the things that bring particular value to the system. Everything else goes straight to the waste bin.

Why so many meetings?

Planning the sprint, daily scrum, retro, review, backlog refinement. The list of meetings is long. There is no doubt that they take time. The client often expects to pay for programming, not for conversations and meetings.

I used to think the same way. However, after a test implementation of SCRUM in one of the projects, I have changed my mind. Now I want to develop all our projects – for clients and internal – using SCRUM. I see that it saves great amount of time and money. The same can be confirmed by the clients with whom we now work using SCRUM, while we did not have a specific way of working before.

Abraham Lincoln once said, "If I had eight hours to chop down a tree, I'd spend six sharpening my ax."

The meetings guarantee a good rethinking of tasks, sticking to a common direction and pursuing the same business goals. It is definitely worth it.

How long will it take and how much will it cost?

Every client asks this question at the beginning. It is not easy to answer it. The pace of each programmer is different, there are different working conditions, holidays, leaves, the requirements change (from the client, legal requirements, etc.). A longer project also means a frequently changing specification. Such changes change the cost and time.

Story Points is a solution to the problem. It is a very good tool for estimating the number of tasks that can be performed in a sprint (stage). After just 2-4 sprints you can see the team's average pace. After such a time the team knows the project well, knows the client well and plans for the future. The team can very accurately estimate the tasks waiting in the Backlog. Product Owner, knowing the pace of the team can count the number of sprints and the total cost.

Compared to creating a detailed specification at the beginning of the project, such an approach gives better estimation results.

SCRUM is not enough if the team does not have the experience with the technology

If the team will work using SCRUM, but will not be familiar with the technology, it will not be able to provide good quality software within a reasonable time. Only the combination of SCRUM and the team experienced in using the given technology ensures significant effects. The customer will definitely be satisfied with such a combination.

Why a remote team is better?

What is the difference between a remote team and a local team? Actually – just their location. If you can have a local team, it is worth choosing this option. It will be more convenient.

However, in today's IT market it is difficult to complete a team of 2, 3 or more specialists in a short time for a larger project. That is why you should think about a remote SCRUM team. A team that already has the experience in working with a remote client. By expanding the options to the whole world, you have more choices.

How can I monitor what a team thousands of miles away is doing? 

SCRUM has a way to do it: Sprint Burndown Chart. It is a chart that is updated daily. It shows the regular peace of project development. It shows whether the team implements the sprint plan. It is the best tool for monitoring the progress of works. Using Waterfall, you usually find out about delays at the end of a larger stage. With SCRUM, the client can check every day what progress the team has made. They can be sure that the team works and delivers consecutive parts of the software.

How to communicate with the team?

At Droptica we have 3 ways to do that:
- Jira - it is the main communication system; here we have all User Stories and tasks
- Slack - for short text questions, used practically every day
- Skype/Google Hangouts/Zoom - for video calls with screen sharing

These three forms of communication in 100% ensure a very good communication between the team and the Product Owner.

If possible, once in a while, the development team meets with the Product Owner at our office or in the client's office. Our offices are located close to the airport, we eagerly invite our clients to visit them.

How can I check if a remote SCRUM team will work in my case?

If you have a project for a minimum of 2-3 people for a few sprints, a well-conducted SCRUM will provide you with very good results.

If you are not sure if SCRUM will work for you, test it. Order 2-3 sprints and see what results you will get. It is a small cost within the scale of projects taking several months, and such an approach will provide an unambiguous answer to the question of whether it is worth using SCRUM.

If you still have doubts about a remote SCRUM team, I will be happy to answer your questions and share my experiences. Write at [email protected] or write your question in the comment.

Jun 13 2018
Jun 13

The deadline is today. A remote development team have worked for several weeks on your software. You obtain the long-awaited access to the system. You check it and you are not satisfied with the achieved results.
All that was needed to avoid this problem is a team with experience in technology and working using SCRUM.

What is SCRUM

Wikipedia defines SCRUM as an agile framework for managing work. It is an approach used in many companies to develop software. Full definition can be found here https://en.wikipedia.org/wiki/Scrum

SCRUM solves most of the problems arising during software development

This is my opinion and many people agree with it. I have been developing commercial projects since 2008. I started as a programmer. Currently, I am supervising high-level projects.

Introduction of the SCRUM method in Droptica solved most of the problems. Which ones exactly?
Here are the most important of them:

  • The client was not regularly informed about the progress of works – the client was not satisfied. Sprints, review, backlog refinement – all this compels a constant contact with the client
  • The tasks were not thought through before starting them, therefore they took a long time to finish – the client was not satisfied. Backlog refinement and planning – these events ensure that the team has to really ponder on completing each task.

SCRUM saves money

You can ask yourself: how is that possible if you do not know the exact duration and cost of the project at its beginning? The answer can be found in the previous paragraph:

  • Regular meetings with the client (Product Owner) force them to think about which tasks are actually needed and which can be rejected.
  • Analysis of tasks by the team together with the PO, often allows to come up with better ways to implement or reject them.

SCRUM is often called the art of maximising work not done. You maximise the rejection of the tasks that are unnecessary from the point of view of your business. You do only the things that bring particular value to the system. Everything else goes straight to the waste bin.

Why so many meetings?

Planning the sprint, daily scrum, retro, review, backlog refinement. The list of meetings is long. There is no doubt that they take time. The client often expects to pay for programming, not for conversations and meetings.

I used to think the same way. However, after a test implementation of SCRUM in one of the projects, I have changed my mind. Now I want to develop all our projects – for clients and internal – using SCRUM. I see that it saves great amount of time and money. The same can be confirmed by the clients with whom we now work using SCRUM, while we did not have a specific way of working before.

Abraham Lincoln once said, "If I had eight hours to chop down a tree, I'd spend six sharpening my ax."

The meetings guarantee a good rethinking of tasks, sticking to a common direction and pursuing the same business goals. It is definitely worth it.

How long will it take and how much will it cost?

Every client asks this question at the beginning. It is not easy to answer it. The pace of each programmer is different, there are different working conditions, holidays, leaves, the requirements change (from the client, legal requirements, etc.). A longer project also means a frequently changing specification. Such changes change the cost and time.

Story Points is a solution to the problem. It is a very good tool for estimating the number of tasks that can be performed in a sprint (stage). After just 2-4 sprints you can see the team's average pace. After such a time the team knows the project well, knows the client well and plans for the future. The team can very accurately estimate the tasks waiting in the Backlog. Product Owner, knowing the pace of the team can count the number of sprints and the total cost.

Compared to creating a detailed specification at the beginning of the project, such an approach gives better estimation results.

SCRUM is not enough if the team does not have the experience with the technology

If the team will work using SCRUM, but will not be familiar with the technology, it will not be able to provide good quality software within a reasonable time. Only the combination of SCRUM and the team experienced in using the given technology ensures significant effects. The customer will definitely be satisfied with such a combination.

Why a remote team is better?

What is the difference between a remote team and a local team? Actually – just their location. If you can have a local team, it is worth choosing this option. It will be more convenient.

However, in today's IT market it is difficult to complete a team of 2, 3 or more specialists in a short time for a larger project. That is why you should think about a remote SCRUM team. A team that already has the experience in working with a remote client. By expanding the options to the whole world, you have more choices.

How can I monitor what a team thousands of miles away is doing? 

SCRUM has a way to do it: Sprint Burndown Chart. It is a chart that is updated daily. It shows the regular peace of project development. It shows whether the team implements the sprint plan. It is the best tool for monitoring the progress of works. Using Waterfall, you usually find out about delays at the end of a larger stage. With SCRUM, the client can check every day what progress the team has made. They can be sure that the team works and delivers consecutive parts of the software.

How to communicate with the team?

At Droptica we have 3 ways to do that:
- Jira - it is the main communication system; here we have all User Stories and tasks
- Slack - for short text questions, used practically every day
- Skype/Google Hangouts/Zoom - for video calls with screen sharing

These three forms of communication in 100% ensure a very good communication between the team and the Product Owner.

If possible, once in a while, the development team meets with the Product Owner at our office or in the client's office. Our offices are located close to the airport, we eagerly invite our clients to visit them.

How can I check if a remote SCRUM team will work in my case?

If you have a project for a minimum of 2-3 people for a few sprints, a well-conducted SCRUM will provide you with very good results.

If you are not sure if SCRUM will work for you, test it. Order 2-3 sprints and see what results you will get. It is a small cost within the scale of projects taking several months, and such an approach will provide an unambiguous answer to the question of whether it is worth using SCRUM.

If you still have doubts about a remote SCRUM team, I will be happy to answer your questions and share my experiences. Write at [email protected] or write your question in the comment.

Jun 06 2018
Jun 06
Droopler is a state-of-the-art open source tool for building websites, built on the latest version of Drupal 8. The system has been designed in order to enable easy and flexible modification of content that looks great on every device. You can find out more at www.droopler.com. A demo version of the system is available at https://demo.droopler.pl/. Before you can familiarise yourselves with the possibilities and functionalities offered by Droopler, I will guide you through the set-up process. Good luck!
Jun 06 2018
Jun 06

Droopler is a state-of-the-art open source tool for building websites, built on the latest version of Drupal 8. The system has been designed in order to enable easy and flexible modification of content that looks great on every device. You can find out more at www.droopler.com.

Droopler logo combining a letter D in shades of blue and black "Droopler" text
A demo version of the system is available at https://demo.droopler.pl/.
Before you can familiarise yourselves with the possibilities and functionalities offered by Droopler, I will guide you through the set-up process.

Good luck!

Technical requirements

Several technical requirements have to be fulfilled before set-up can begin. The following stack is required to set-up Droopler:

  • Apache (or another web server),
  • SQLite, MySQL, MariaDB, Postgresql or another database;
  • PHP 7.

Most shared hosting providers (sharehost) offer such a stack. Before starting the set-up process, it is worth checking whether PHP version is set to 7.

Setting up Droopler

The following set-up process is intended for users who do not have root access to the operating system (shared hosting, etc.).

Step 1 – Downloading files to the server

The following steps should be executed in the directory to which the domain is pointed (DocumentRoot).

Consolepath shown in domains
Method 1

This method can be used if your hosting provider provides a connection to the server via SSH. 
Important:before you use this method to set-up Droopler, make sure that commands such as 

composer --help
npm help
gulp -version

are available. If executing the above commands does not return any “command not found” messages or other errors, you can carry on. Otherwise, go straight to method 2 :-)
In this method, you just need to execute the commands listed below to download the necessary files:

git clone -b no_web https://github.com/droptica/droopler_project
cd droopler_project
composer install
composer drupal-scaffold
composer install

At this point, you just have to compile SCSS files to CSS.  In order to do so, simply follow the instructions below:

cd web/themes/custom/droopler_subtheme
npm install
npm install --global gulp-cli
gulp compile

Method 2

1. Download the turnkey package from https://www.droopler.com/download
2. Unpack the downloaded package and upload it to the server via FTP.

Step 2 - setting up Droopler 

Launch your browser and enter the address. You will be automatically redirected to the Droopler set-up wizard. Follow the instructions of the wizard to complete the set-up process.

Droopler profile creator, step one, choosing language

Droopler profile creator, step two, configuration of database

Droopler profile creator, step three, installation in progress

Droopler profile creator, step four, configuration of site name and e-mail address

Droopler profile creator, step four, final message that summarise previous steps, new site is ready

Setting up Droopler in Docker using the dcon tool

Important:  Root access to the operating system is required to perform the steps listed below.

Install the dcon tool, according to the instructions at https://github.com/droptica/docker-console, and run an https://github.com/droptica/nginx-proxy container.
We wrote more about running dcon and nginx-proxy in one of our previous articles.
In order to run Docker containers on which Droopler will operate, you need a docker-compose.yml file. You can download a sample wrapper, where you will find the required files. 

git clone https://github.com/DropticaExamples/droopler-wrapper-example.git

Change the VIRTUAL_HOST parameter to the domain address of your own page in the downloaded docker-compose.yml file. When you publish your website online, it is also worth removing or commenting out the phpmyadmin container for security reasons.
Now, you need to download the Droopler repository to the /app directory – execute the following command in the directory to which you downloaded the repository (wrapper) beforehand:

git clone https://github.com/droptica/droopler_project app

To build and launch the docker containers, execute the following commands in the console:

dcon update-images
dcon up

All that you have to do is to launch the installation of a Droopler profile:

dcon build-profile

You will be asked to enter a GitHub token. Copy the link and load the page, a token will be generated, which you need to copy to the console and confirm by pressing enter.

The link with token shown next to "head to" circled in red
After carrying out multiple operations, Droopler will be ready for the first launch. Start the browser and enter the address of your page.

Updating

Droopler is constantly developed and expanded with new functionalities. In order to develop these features on your website, you should make sure to update the system on a regular basis. Updates also include security patches.
IMPORTANT! We strongly suggest making a back-up of your files and database, as well as enabling maintenance downtime – example.com/admin/config/development/maintenance – before updating Droopler.
You can update Droopler in one of two ways:

Method 1

If you set-up Droopler by downloading the codebase from the https://github.com/droptica/droopler_project repository, this method is intended for you :)
Connect to the server via SSH and execute git pull command in the directory, where you downloaded the repository beforehand.
The next step depends on whether you have installed the dcon tool or not. If dcon is available, execute the following command:

dcon compose-update

However, if you do not have dcon installed, you will need to execute:
 

composer update

Method 2

Download a new build from https://www.droopler.com/download
The downloaded package needs to be unpacked and uploaded to the server via FTP, overwriting the existing files on the server.
Launch your browser and go to www.example.com/update.php 

Conclusion

Congratulations! You just learned several ways to set-up and update Droopler, a Drupal distribution. As you can see, this is really easy :-) However, if you stumble upon any issues that you can’t solve on your own, leave us a message. We’ll be glad to help you!

Mar 16 2018
Mar 16

Droptica is an amazing company. I've worked with Drupal specialists in the past... Nothing worked in terms of quality and value, but they hit the sweet pot. They provided good-quality code at a reasonable price point.

Founder, E-Commerce Platform

I could not rate Droptica highly enough. They have genuinely helped our dream service became a reality... The site is looking awesome, and we can't wait to relaunch. We have untold efficiency gains now.

Head of IT, Compliance & regulatory Platform

Mar 16 2018
Mar 16

Yoast SEO is a module that has everything you need to make your content visible to search engines. The plug-in that took the WordPress community by storm is slowly getting more and more traction in the Drupal community as well.
What exactly is SEO? SEO is an acronym of Search Engine Optimisation, which basically means optimising websites for a search engine, which in reality translates into getting your website as high as possible in search results, and thus getting more and more people to visit the website.
Before using the module, it is worth investing some time in getting hang of the basic requirements for SEO, this will make it easier to understand some rules and principles which you should adhere to. There is a lot of more and less useful information on the Internet regarding that subject. There are also many SEO analysers available online, but they only enable you to analyse content that you already have on your website. The module I present today gives you an advantage, because it allows you to check your content during the process of writing the article. I am not going to discuss the recommendations and principles of SEO, which should be used. Instead, the main goal of this article is showing you the benefits of a module that will help you optimise your content.

Setup:

We are going to start by installing the module on our Drupal 8 based website. At the time of writing this article, I have been using the latest available version of the yoast_seo module (8.x-1.3)
The module is available here https://www.drupal.org/project/yoast_seo 
In order to install the Real-time SEO for Drupal module, you first need to add the required modules which are not included in Drupal core – Metatag and Token.

The Yoast SEO module checked on the list of available modules. Additional information, including other modules needed to install Yoast are provided below the main description

Settings view:

After going to the settings view, you will have access to three sections, namely: 

  • SITEMAP
  • CONFIGURE METATAG DEFAULT TEMPLATES 
  • CONFIGURE REAL-TIME SEO BY BUNDLES

Aforementioned three sections one under the another, with additional descriptions

We are going to ignore the top two because they are used for configuring sitemap and metatags. Instead, we are going to focus on the last one because that’s exactly where we will be able to play with the module settings. As you can see, there are not many options to choose, the only thing you can set are types of content for which the Yoast widget will be active.
By default, the plug-in should be set to active for all the available options.

Permissions:

In the permission settings, you can assign user roles for managing the module settings, as well as pick users who can use it. We recommend leaving administration to administrators. Additionally, you should enable the plug-in for every user who creates content for your website, because you certainly want your content to be as optimised as possible.

Permission label. Some options are mentioned along with checkboxes under the user roles

Adding a node, whole page view. Below, under the fields, you can see the Yoast module widget.

Adding a node, whole page view.

The widget is divided into three main sections:

  • Focus keyword, where you can check the keywords in your article.
  • Snippet editor, showing you how your website is seen by Google. It displays the elements such as the title and description.
  • Content analysis, which analyses the content of your article. Thanks to coloured tags, you will find it easy to see whether your article was written well from the SEO perspective. It also shows you how many words are there in your article.

A close up on information provided by YOAST

Note: The plug-in uses Flesch reading content analyser, which currently works properly for English, German and Dutch.
An example article from Droptica blog analysed using Yoast SEO plug-in.

A sample page analysed by module. Red dot signifies things that should be reworked. Green ones mark areas where the blog post is doing great

By setting up this simple module, you can make work easier both for yourself, as well as for other people who create or edit the content on your website. After all, when you create something you want to make sure that it is of the highest possible quality and that it reaches as many people as possible. I believe that thanks to the Yoast plug-in, you can achieve that in a simple and clear way. Perhaps thanks to this tool you will understand better how the website is seen by the search engines, and you will be able to make the content attractive not only for your readers but also for robots... since as you probably already know, they’re all around us.

Mar 05 2018
Mar 05
In one of our previous articles, we showed you how to configure CKEditor in Drupal 8. This time, we are going to demonstrate how you can expand the editor’s functionality on your own.   In the case of many websites, the basic functions of CKEditor are more than enough.  However, there are projects where clients demand expanding the functionality of the content editor. With CKEditor, you can do that using plug-ins – all of them are available on the official website.http://ckeditor.com/addons/plugins/all  Adding a new plug-in to the website based on Drupal 8 is very simple compared to the way it was done in the previous version of Drupal. All you need is to create a simple module.  
Mar 05 2018
Mar 05

In one of our previous articles, we showed you how to configure CKEditor in Drupal 8.
This time, we are going to demonstrate how you can expand the editor’s functionality on your own.
 
In the case of many websites, the basic functions of CKEditor are more than enough. 
However, there are projects where clients demand expanding the functionality of the content editor.
With CKEditor, you can do that using plug-ins – all of them are available on the official website.
http://ckeditor.com/addons/plugins/all 
Adding a new plug-in to the website based on Drupal 8 is very simple compared to the way it was done in the previous version of Drupal. All you need is to create a simple module.
 
As our example, I chose a plug-in that will enable us to post a YouTube clip using an embed code or its URL.
 

The catalogue tree with the structure of the module

The plug-in in question: https://ckeditor.com/cke4/addon/youtube 
Create a module named cke_youtube (or choose your own name).
 
The structure of the module is as follows:
 
cke_youtube.info.yml file contains the standard data of the module.
cke_youtube.module file is an empty PHP file, we don’t need any code there.
 
The structure contains two additional directories:
Plug-in directory - js. 
There, you will find another directory named “plugins”.
Unpack the files downloaded from https://ckeditor.com/cke4/addon/youtube  there.
 
 The -js. plugin catalogue visible in the catalogue tree of module

Creating a new plug-in in Drupal takes place in a new class file, which we have to create and then properly configure.
In our case, it is going to be Youtube.php, and the entire structure needs to look like as follows.
 

full structure of module

Code:

<?php

namespace Drupal\cke_youtube\Plugin\CKEditorPlugin;

use Drupal\ckeditor\CKEditorPluginInterface;
use Drupal\ckeditor\CKEditorPluginButtonsInterface;
use Drupal\Component\Plugin\PluginBase;
use Drupal\editor\Entity\Editor;

/**
 * Defines the "Youtube" plugin, with a CKEditor.
 *
 * @CKEditorPlugin(
 *   id = "youtube",
 *   label = @Translation("Youtube Plugin")
 * )
 */
class Youtube extends PluginBase implements CKEditorPluginInterface, CKEditorPluginButtonsInterface {

  /**
   * {@inheritdoc}
   */
  public function getDependencies(Editor $editor) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getLibraries(Editor $editor) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function isInternal() {
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function getFile() {
    return drupal_get_path('module', 'cke_youtube') . '/js/plugins/youtube/plugin.js';
  }

  /**
   * @return array
   */
  public function getButtons() {
    $iconImage = drupal_get_path('module', 'cke_youtube') . '/js/plugins/youtube/images/icon.png';

    return [
      'Youtube' => [
        'label' => t('Add Youtube Video'),
        'image' => $iconImage,
      ]
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getConfig(Editor $editor) {
    return [];
  }

}

The YouTube class uses two interfaces -  CKEditorPluginInterface, CKEditorPluginButtonsInterface
Take a closer look at its comment. The “id” variable must contain the same name as the name of the plug-in you’re installing. 
In this case, the name is “youtube”.
For other plug-ins, you will find the name in the plugin.js file.

Plugin.js file. The name in the bracket is name of your plugin. Here: Youtube name is visible

Below we will briefly discuss all the methods and what they do:
getDependencies()
Here you will put in all the names of the plug-ins which are required for your plug-in to work.
If they are not needed, you leave the method empty, and our YouTube plug-in is one of such cases.
You will find the required plug-ins in the plugin.js file.
Example for Layout Manager plug-in:
 

List of plugins needed to install tle "layout manager" plugin from plugin.js file

In this case, you would have to first install basewidget, and then add layoutmanager.

getLibraries()
Specifies additional libraries.

getFile()
Plug-in location.

getButtons()
Adds a new button to the editor.
 
Keep in mind that you have to use a correct name in the return array:
In the case of this plug-in, the correct name is “Youtube”.

The right name used in the table. At this case it's "Youtube"

You can find the required name in the plugin.js file.

Plugin.js file. The name after .addbutton is the name of your plugin.

At the point where the entire structure and names are correct, you can turn on your new module.
Go to Extend (/admin/modules/)
 

Extend/admin/modules with new plugin available

Now, go to text formats and editor configuration

Configuration → Content Authoring → Text formats and editors (/admin/config/content/formats/)

Add a new button to the editor for a selected format.

New button is being added to CKEditor

After applying changes, add new content and select text format for which you just set up the Add YouTube Video button.
If everything works well, a window will open after clicking the button, allowing you to put in your embed code or URL to your clip.

"Embed youtune video" window that let's the user to add youtube films to the page that appeared after using the new button of the CKEditor.

Feb 07 2018
Feb 07

The projects implemented by Droptica require a large amount of coding in PHP. Taking advantage of various tool and configurations allows us to streamline the process and make it far more convenient and pleasant. In this post, we wanted to share our experiences and describe an ideal software configuration for coding in PHP (mainly in Drupal) from our standpoint at Droptica. The base software that we use includes Linux (most people use Ubuntu) and PHPStorm as IDE. We also use Docker for setting up and running services like Apache, MySQL, Solr, etc. 

Docker instead of locally installed Apache and PHP

Many web developers prefer installing a full LAMP stack on their local server, with Apache/MySQL and PHP installed on top of Linux. This is not a bad solution, but such a local installation is always going to be different from the client’s server environment. And in this case, the more differences, the more work and potential conflicts you will face, along with the “works for me” responses. :-)
Docker offers a nice solution to this issue, as it allows you to run identical server configurations in both development and production environments. However, the most crucial advantage of Docker is the fact that the developer is no longer required to manually configure all the .conf and .ini files. Thanks to Docker, you can focus on coding and leave all the server matters in the hands of experts.
At Droptica, we use a custom piece of software called docker-console, which allows our developers to quickly start a new or existing project in Drupal. Tools such as Composer, Drush, Sass/Compass are in their containers and they work without the need to install them locally on developer’s machine. Usually, they also have a range of tools for making debugging easier at their disposal. One of such tools is Mailcatcher, which catches all the e-mails sent by Drupal.

Nginx proxy for Docker

The nginx proxy image for Docker allows for using hosts (local domains) in order to display websites running on Docker in a web browser. In short, thanks to nginx proxy, we can type in http://www.droptica.dev instead of an IP address (for example: "172.17.0.4".) Nginx proxy is very useful when we are running a Drupal multisite and there are multiple domains under a single container’s IP address (e.g. sites/droptica.com, sites/droptica.pl).
Installing nginx proxy:
1. Before installation, make sure to remove all the existing versions of nginx proxy. Depending on the name, it is going to look more or less like:

docker stop ngnix-proxy && docker rm ngnix-proxy

2. Clone the repository: https://github.com/droptica/nginx-proxy 
3. Enter the repository directory and run it using the command:

docker-compose up -d

4. Check nginx IP, if the address changed, change it in the /etc/hosts file:

docker inspect --format
"{{ .NetworkSettings.IPAddress }}" nginx-proxy

5. If you want to add https for a xxx.dev domain, copy default.crt and default.key files to xxx.dev.crt and xxx.dev.key. It is possible that you will have to do chmod 777 on them and then restart the nginx container:

sudo chmod 777 -Rf certs && docker-compose restart

6. Add the code responsible for https to the configuration file (example for the xxx.dev domain):

if(strpos($_SERVER['SERVER_NAME'], 'xxx') !== FALSE) {
  $base_url = 'https://'.$_SERVER['SERVER_NAME'];
  $conf['https'] = TRUE;
}

7. When the machine runs something on port 80 (apache/nginx), comment the following lines in docker-compose.yml:

ports:
    - 80:80 
    - 443:443 

8. Docker compose version 2 and higher with nginx-proxy. On versions newer than 1, docker-compose sets private network for the containers, and because of that nginx-proxy cannot connect to it by default. In order to get it running, you have to find out the network and add it manually.

# list networks
docker network ls

# connect you nginx_proxy to your network
docker connect you_network_name nginx_proxy

PHP CodeSniffer

PHP CodeSniffer is a very useful tool, which helps you maintain clear codebase, conforming to standards. As you can read in the Readme file, CodeSniffer is made up of two scripts. One is used for detecting violations of a defined coding standard (phpcs), and the other is used to automatically correct coding standard violations (phpcbf). 
PHPStorm, however, only allows you to use the former one (phpcs). After configuration, all the lines containing code violating the standard will be highlighted in the currently edited file.
In order to be able to use PHP CS, you have to install it first, for example by using composer or in any other way described in the project’s readme file. https://github.com/squizlabs/PHP_CodeSniffer 
for instance:

composer global require "squizlabs/php_codesniffer=*"

If you did not add the $HOME/.composer/vendor/bin path to your $PATH variable, you should do it now. To do this, in the case of Linux, add the following line at the end of the ~/.bashrc file:

export PATH="$PATH:$HOME/.composer/vendor/bin"

In order to apply the changes, log out and log back in or execute the following command:

source ~/.bashrc

Another thing that you have to do is adding Drupal coding standards to PHP CS. Simply install the coder module - https://www.drupal.org/project/coder.
The easiest way to do it is by using composer:

composer global require drupal/coder

The detailed installation instructions can be found here: https://www.drupal.org/node/1419988 
Before you move on to the next step, make sure that there is no second instance of PHP CS installed anywhere in the system, you can do this by executing the following command:

whereis phpcs

It should return an output that is similar to the one below:

phpcs: /home/<username>/.composer/vendor/bin/phpcs

If the command returns more locations, you should get rid of the unnecessary versions, so that only one remains on your machine.
Then, register Drupal standards from the coder module:

phpcs --config-set installed_paths ~/.composer/vendor/drupal/coder/coder_sniffer

After installing PHP CS and Coder in the system, you can move on to configuring PHPStorm:
Settings -> Languages & Frameworks -> PHP -> Code Sniffer
In the “Development environment” section, click three dots next to the “Configuration” option.

PHPStorm window visible. There is box with "local" text inside and an arrow. Further right there is a button with three dots on it

In the Code Sniffer window, provide the path to the phpcs script (the one returned by the whereis phpcs command) in the “PHP Code Sniffer (phpcs) path” for the “Local” configuration.

A path to the "Local" configuration pasted in the box in the upper right corner of the window

After entering the path, click Validate in order to make sure that PHP CS works fine. If everything works, you should see the following message on a green background:

Validated file. The label "ok, PHP_CodeSniffer version 3.0.2 (stable) by Squiz (http://squiz.net) visible on the green background, as described in the text.
Then, turn on inspecting code by Code Sniffer. You can do it by going to the settings:
Settings -> Editor -> Inspections 
Select PHP from the list of languages, and then turn on
‘PHP Code Sniffer validation’. After ticking the checkbox, refresh the list of available coding standards A PHPStorm "reload icon" and then choose Drupal. 

A drop-down menu of described configuration visible. The cursor highlights Drupal among the others visible on the list
After applying the settings, you can open a PHP file and check how Code Sniffer works.

Xdebug (working on every project)

XDebug enables debugging web applications developed in PHP in a “classic” style, using breakpoints and running code line-by-line. XDebug is fully compatible with PHPStorm, and connecting the IDE to the debugger is very simple. 
Regardless of whether you use docker or set up the entire environment all by yourself, XDebug should broadcast information about the scripts on port 9000. In order to make PHPStorm listen to this port, click “Run -> PHPStorm "Start listening" icon Start listening for PHP Debug Connections”. After refreshing the debugged page in the editor, a window will open, confirming that the connection with XDebug has been successfully established. Sometimes it may be necessary to adjust directory mapping between the server’s webroot and project directory in PHPstorm.
If the connection was not established properly, first make sure that XDebug works at all (by running php --version or phpinfo()). Then check whether you need any bookmarklets (specially prepared links added to bookmarks) activating debugging. You can find them at https://www.jetbrains.com/phpstorm/marklets/ 
A very good and in-depth manual regarding connecting XDebug and PHPStorm is available here:
https://confluence.jetbrains.com/display/PhpStorm/Zero-configuration+Web+Application+Debugging+with+Xdebug+and+PhpStorm 

XDebug plug-in for Chrome/Firefox

There are many plug-ins available, just install it, enable it for a given page and enjoy the possibilities offered by XDebug.
Some examples:
Firefox: https://addons.mozilla.org/en-US/firefox/addon/xdebug-helper-for-firefox/ 
Chrome: https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc 

MySQL Workbench

A piece of software for managing MySQL databases. It allows you to import and export databases, view tables, as well as query databases, regardless of whether they are local, in docker or remote via ssh. It does not have any limits regarding the size of an imported database (compared to the default PHPMyAdmin configuration).  
The packages can be downloaded at https://dev.mysql.com/downloads/workbench/, after downloading just install them.

Chrome plug-in for JS debugging

The add-on is available for Chrome only:
https://chrome.google.com/webstore/detail/jetbrains-ide-support/hmhgeddbohgjknpmjagkdomcpobmllji 

Code formatting in PHPStorm:

Drupal has a very specific code formatting standards. Some of the most important things to remember are indent of two spaces, as well as putting else/elseif/catch/while always in a new line. PHPStorm is compatible with Drupal out of the box. 
Simply go to Settings -> Editor -> Code Style -> PHP and select Set From -> Predefined Style -> Drupal. Do not forget about formatting settings for CSS, JS, SASS/LESS.

Drupal Coding standards chosen in PHPStorm settings

Additional PHPStorm configuration

Below you can find some additional PHPStorm configuration options, which also make your work easier by automatically formatting your code according to the accepted standards:
Automatically adding an empty line at the end of the file when saving: 
Settings -> Editor -> General, select Ensure line feed at file end on Save
Automatically removing white spaces at the end of the lines when saving the file.
Settings -> Editor -> General, Strip trailing spaces on Save, select ‘All’. 
You can also choose ‘Modified Lines’ if you do not want white spaces to be removed from other places in the code, which were not modified.
Automatically formatting the code after typing in the closing curly bracket.
Settings -> Editor -> General -> Smart Keys, select Reformat block on typing '}'

Summary

The above article features our current recommendations. They are different now from what we recommended a year or two ago, and they will probably be different in the future – the configuration will get even better. :)
Is there anything that we should improve in your opinion? Perhaps you have your own way to configure your development environment? Share your insights and ideas in the comments!

Feb 07 2018
Feb 07

The projects implemented by Droptica require a large amount of coding in PHP. Taking advantage of various tool and configurations allows us to streamline the process and make it far more convenient and pleasant. In this post, we wanted to share our experiences and describe an ideal software configuration for coding in PHP (mainly in Drupal) from our standpoint at Droptica. The base software that we use includes Linux (most people use Ubuntu) and PHPStorm as IDE. We also use Docker for setting up and running services like Apache, MySQL, Solr, etc. 

Docker instead of locally installed Apache and PHP

Many web developers prefer installing a full LAMP stack on their local server, with Apache/MySQL and PHP installed on top of Linux. This is not a bad solution, but such a local installation is always going to be different from the client’s server environment. And in this case, the more differences, the more work and potential conflicts you will face, along with the “works for me” responses. :-)
Docker offers a nice solution to this issue, as it allows you to run identical server configurations in both development and production environments. However, the most crucial advantage of Docker is the fact that the developer is no longer required to manually configure all the .conf and .ini files. Thanks to Docker, you can focus on coding and leave all the server matters in the hands of experts.
At Droptica, we use a custom piece of software called docker-console, which allows our developers to quickly start a new or existing project in Drupal. Tools such as Composer, Drush, Sass/Compass are in their containers and they work without the need to install them locally on developer’s machine. Usually, they also have a range of tools for making debugging easier at their disposal. One of such tools is Mailcatcher, which catches all the e-mails sent by Drupal.

Nginx proxy for Docker

The nginx proxy image for Docker allows for using hosts (local domains) in order to display websites running on Docker in a web browser. In short, thanks to nginx proxy, we can type in http://www.droptica.dev instead of an IP address (for example: "172.17.0.4".) Nginx proxy is very useful when we are running a Drupal multisite and there are multiple domains under a single container’s IP address (e.g. sites/droptica.com, sites/droptica.pl).
Installing nginx proxy:
1. Before installation, make sure to remove all the existing versions of nginx proxy. Depending on the name, it is going to look more or less like:

docker stop ngnix-proxy && docker rm ngnix-proxy

2. Clone the repository: https://github.com/droptica/nginx-proxy 
3. Enter the repository directory and run it using the command:

docker-compose up -d

4. Check nginx IP, if the address changed, change it in the /etc/hosts file:

docker inspect --format
"{{ .NetworkSettings.IPAddress }}" nginx-proxy

5. If you want to add https for a xxx.dev domain, copy default.crt and default.key files to xxx.dev.crt and xxx.dev.key. It is possible that you will have to do chmod 777 on them and then restart the nginx container:

sudo chmod 777 -Rf certs && docker-compose restart

6. Add the code responsible for https to the configuration file (example for the xxx.dev domain):

if(strpos($_SERVER['SERVER_NAME'], 'xxx') !== FALSE) {
  $base_url = 'https://'.$_SERVER['SERVER_NAME'];
  $conf['https'] = TRUE;
}

7. When the machine runs something on port 80 (apache/nginx), comment the following lines in docker-compose.yml:

ports:
    - 80:80 
    - 443:443 

8. Docker compose version 2 and higher with nginx-proxy. On versions newer than 1, docker-compose sets private network for the containers, and because of that nginx-proxy cannot connect to it by default. In order to get it running, you have to find out the network and add it manually.

# list networks
docker network ls

# connect you nginx_proxy to your network
docker connect you_network_name nginx_proxy

PHP CodeSniffer

PHP CodeSniffer is a very useful tool, which helps you maintain clear codebase, conforming to standards. As you can read in the Readme file, CodeSniffer is made up of two scripts. One is used for detecting violations of a defined coding standard (phpcs), and the other is used to automatically correct coding standard violations (phpcbf). 
PHPStorm, however, only allows you to use the former one (phpcs). After configuration, all the lines containing code violating the standard will be highlighted in the currently edited file.
In order to be able to use PHP CS, you have to install it first, for example by using composer or in any other way described in the project’s readme file. https://github.com/squizlabs/PHP_CodeSniffer 
for instance:

composer global require "squizlabs/php_codesniffer=*"

If you did not add the $HOME/.composer/vendor/bin path to your $PATH variable, you should do it now. To do this, in the case of Linux, add the following line at the end of the ~/.bashrc file:

export PATH="$PATH:$HOME/.composer/vendor/bin"

In order to apply the changes, log out and log back in or execute the following command:

source ~/.bashrc

Another thing that you have to do is adding Drupal coding standards to PHP CS. Simply install the coder module - https://www.drupal.org/project/coder.
The easiest way to do it is by using composer:

composer global require drupal/coder

The detailed installation instructions can be found here: https://www.drupal.org/node/1419988 
Before you move on to the next step, make sure that there is no second instance of PHP CS installed anywhere in the system, you can do this by executing the following command:

whereis phpcs

It should return an output that is similar to the one below:

phpcs: /home/<username>/.composer/vendor/bin/phpcs

If the command returns more locations, you should get rid of the unnecessary versions, so that only one remains on your machine.
Then, register Drupal standards from the coder module:

phpcs --config-set installed_paths ~/.composer/vendor/drupal/coder/coder_sniffer

After installing PHP CS and Coder in the system, you can move on to configuring PHPStorm:
Settings -> Languages & Frameworks -> PHP -> Code Sniffer
In the “Development environment” section, click three dots next to the “Configuration” option.

PHPStorm window visible. There is box with "local" text inside and an arrow. Further right there is a button with three dots on it

In the Code Sniffer window, provide the path to the phpcs script (the one returned by the whereis phpcs command) in the “PHP Code Sniffer (phpcs) path” for the “Local” configuration.

A path to the "Local" configuration pasted in the box in the upper right corner of the window

After entering the path, click Validate in order to make sure that PHP CS works fine. If everything works, you should see the following message on a green background:

Validated file. The label "ok, PHP_CodeSniffer version 3.0.2 (stable) by Squiz (http://squiz.net) visible on the green background, as described in the text.
Then, turn on inspecting code by Code Sniffer. You can do it by going to the settings:
Settings -> Editor -> Inspections 
Select PHP from the list of languages, and then turn on
‘PHP Code Sniffer validation’. After ticking the checkbox, refresh the list of available coding standards A PHPStorm "reload icon" and then choose Drupal. 

A drop-down menu of described configuration visible. The cursor highlights Drupal among the others visible on the list
After applying the settings, you can open a PHP file and check how Code Sniffer works.

Xdebug (working on every project)

XDebug enables debugging web applications developed in PHP in a “classic” style, using breakpoints and running code line-by-line. XDebug is fully compatible with PHPStorm, and connecting the IDE to the debugger is very simple. 
Regardless of whether you use docker or set up the entire environment all by yourself, XDebug should broadcast information about the scripts on port 9000. In order to make PHPStorm listen to this port, click “Run -> PHPStorm "Start listening" icon Start listening for PHP Debug Connections”. After refreshing the debugged page in the editor, a window will open, confirming that the connection with XDebug has been successfully established. Sometimes it may be necessary to adjust directory mapping between the server’s webroot and project directory in PHPstorm.
If the connection was not established properly, first make sure that XDebug works at all (by running php --version or phpinfo()). Then check whether you need any bookmarklets (specially prepared links added to bookmarks) activating debugging. You can find them at https://www.jetbrains.com/phpstorm/marklets/ 
A very good and in-depth manual regarding connecting XDebug and PHPStorm is available here:
https://confluence.jetbrains.com/display/PhpStorm/Zero-configuration+Web+Application+Debugging+with+Xdebug+and+PhpStorm 

XDebug plug-in for Chrome/Firefox

There are many plug-ins available, just install it, enable it for a given page and enjoy the possibilities offered by XDebug.
Some examples:
Firefox: https://addons.mozilla.org/en-US/firefox/addon/xdebug-helper-for-firefox/ 
Chrome: https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc 

MySQL Workbench

A piece of software for managing MySQL databases. It allows you to import and export databases, view tables, as well as query databases, regardless of whether they are local, in docker or remote via ssh. It does not have any limits regarding the size of an imported database (compared to the default PHPMyAdmin configuration).  
The packages can be downloaded at https://dev.mysql.com/downloads/workbench/, after downloading just install them.

Chrome plug-in for JS debugging

The add-on is available for Chrome only:
https://chrome.google.com/webstore/detail/jetbrains-ide-support/hmhgeddbohgjknpmjagkdomcpobmllji 

Code formatting in PHPStorm:

Drupal has a very specific code formatting standards. Some of the most important things to remember are indent of two spaces, as well as putting else/elseif/catch/while always in a new line. PHPStorm is compatible with Drupal out of the box. 
Simply go to Settings -> Editor -> Code Style -> PHP and select Set From -> Predefined Style -> Drupal. Do not forget about formatting settings for CSS, JS, SASS/LESS.

Drupal Coding standards chosen in PHPStorm settings

Additional PHPStorm configuration

Below you can find some additional PHPStorm configuration options, which also make your work easier by automatically formatting your code according to the accepted standards:
Automatically adding an empty line at the end of the file when saving: 
Settings -> Editor -> General, select Ensure line feed at file end on Save
Automatically removing white spaces at the end of the lines when saving the file.
Settings -> Editor -> General, Strip trailing spaces on Save, select ‘All’. 
You can also choose ‘Modified Lines’ if you do not want white spaces to be removed from other places in the code, which were not modified.
Automatically formatting the code after typing in the closing curly bracket.
Settings -> Editor -> General -> Smart Keys, select Reformat block on typing '}'

Summary

The above article features our current recommendations. They are different now from what we recommended a year or two ago, and they will probably be different in the future – the configuration will get even better. :)
Is there anything that we should improve in your opinion? Perhaps you have your own way to configure your development environment? Share your insights and ideas in the comments!

Jan 09 2018
Jan 09
Another year is over, and we are glad to acknowledge that we are very proud of what happened during this period! In short, 2017 was the best year in the company’s five-year history. That is why we decided to share a brief summary of the year with you. See what we achieved over the last 12 months and what we have in store for 2018.    Reasons to be proud
Jan 09 2018
Jan 09

Another year is over, and we are glad to acknowledge that we are very proud of what happened during this period!
In short, 2017 was the best year in the company’s five-year history. That is why we decided to share a brief summary of the year with you. See what we achieved over the last 12 months and what we have in store for 2018. 

 
Reasons to be proud

https://www.droptica.com/blog/droptica-among-15-best-drupal-companies-world/

At the beginning of the year, Clutch recognised us as a worldwide leader among development companies working with Drupal. It is a huge success and a distinction on a global scale. 
Soon afterwards, we received another award. Our team was listed in the top 15 of the "Leading Developers in Poland" ranking. We were distinguished not only in the Drupal world but also among software development companies dealing with various other technologies.  
We are pleased that the individual customer approach and the implementation of increasingly complex projects have been noticed and appreciated.

 
DrupalCamp 2017

A photo of Drupal Camp Wrocław 2017 attendees

After a fruitful beginning of the year, we did not rest on our laurels. Quite the contrary, in fact – it motivated us even more! 
The sixth edition of the DrupalCamp conference organised by Droptica started at the end of May and attendance was very high! We hosted 70 participants from all over Poland and abroad. Our guests had the opportunity to take part in twelve lectures presented in both Polish and English.
After the conference, we started working on DrupalCamp for 2018. We believe DrupalCamp 2018 will be better than ever before. Many guests from both Poland and abroad have already accepted their invitations.
See www.drupalcamp.pl for more information.
 

We share our knowledge with others

Drupal Day in Wrocław attendees seen from above

We continue conducting a free DrupalDay training in Poland every single month. DrupalDay is for people who want to learn about Drupal 8 or hone their skills.  
This year we organised the largest number of training sessions and achieved an exceptionally high attendance rate. In 2017 we visited Warsaw, Gdańsk, Katowice, Wrocław and Opole. In 2018 we will be conducting even more free training courses.
See www.drupalday.pl for details.

We focused on new challenges - Droopler 

A few cellphones with main page of Droopler visible on their screens. Droopler logo and a flag with text "100% free" are shown in the corners

In response to the market demand for simpler and cheaper websites, which can be expanded and built upon, we created Droopler.
Droopler is a revolutionary approach that enables its users to quickly build a modern website based on Drupal, meeting the needs of most SMEs. In the spirit of open source, we have made all our work available free of charge so that the whole community can benefit from it.
It is our second open source project on such a scale – the first one was Docker-console. In 2018, we are going to continue its development.
 

Our foreign missions

Maciej Lukianski giving lecture on Docker-console and Drupal in Schwerin, 2017

2017 is the year of travel, meetings and training courses.
We participated in a record number of international conferences, including:
Drupal Business Days Frankfurt 2017
Drupal Business and Community Days 2017, Heidelberg 
DrupalCon 2017, Vienna
DrupalCamp, Schwerin 2017
At the Schwerin and Heidelberg conferences, Maciej Łukiański talked about Docker and Docker-console. You can see the Heidelberg presentation on our YouTube channel.

 
#DropticaLife

Droptica team members, Zegrze 2017

2017 also meant growth. Our team has grown to 24 people. We are also expanding the scope of our activities. We are no longer just a Drupal shop; instead, we are gradually becoming a full-service agency. This year we hired a graphic designer and a marketing specialist. There are more and more of us and we are certainly not going to stop growing anytime soon. 
Since we have many new employees, we have also focused on team integration. We had several outings after work – we went karting, we also played some laser tag. At the end of the year, we went to Zegrze near Warsaw. There, we spent three intense days on both integration and training in the basics of ReactJS and PHP SOLID.

Plans for the New Year?

In short, development. 
To sum up, over the last year, we managed to achieve the highest revenue to date, we grew larger than ever before as a team and the number of customers exceeded our wildest expectations. This is undoubtedly a great success of the entire team, and thanks to that we enter the new year full of motivation and positive energy. The new year is going to be even more intense than the last one :)
We are planning to steadily develop the company even further. We currently have offices in Wrocław, Gdańsk and Rzeszów. Now it’s time for Opole! We believe that next year, we are going to have twice as many employees as we do now. 
We focus on self-improvement, constantly undertaking new challenges and interesting projects, training internally and getting new certifications. The fact that we have the only certified Drupal 8 developer in Poland can serve as a proof of that. We are also going to improve processes and increase process automation in order to provide great software in an even more efficient manner. 
If you think that our vision is the same as yours and you would like to join us to carry out our plans for 2018 – feel free to visit http://kariera.droptica.pl.
Finally, we wish you all the best in 2018! See you at one of the Droptica events! :)
 

Dec 19 2017
Dec 19
To create a big, frequently updated website, you need more than just skilled editors. A solid technological foundation is also a must.  If you have a hard time choosing from the ocean of possibilities, Drupal, a versatile system of CMF-class comes to your rescue.  When you’re building an advanced website, you can choose from among many technologies. Usually, the first choice is the programming language (PHP, Python, Java, ASP.NET, etc.) and then we decide whether we should code everything from scratch or use a framework to do all the heavy lifting. There is also a third choice, a more comprehensive solution –so-called CMF systems, which stands for content management framework. Drupal 8 is one of these systems. In this article, I will tell you why it’s worth it to choose Drupal as the basis for any large and advanced website. 
Dec 19 2017
Dec 19

To create a big, frequently updated website, you need more than just skilled editors. A solid technological foundation is also a must.  If you have a hard time choosing from the ocean of possibilities, Drupal, a versatile system of CMF-class comes to your rescue. 

When you’re building an advanced website, you can choose from among many technologies. Usually, the first choice is the programming language (PHP, Python, Java, ASP.NET, etc.) and then we decide whether we should code everything from scratch or use a framework to do all the heavy lifting. There is also a third choice, a more comprehensive solution –so-called CMF systems, which stands for content management framework. Drupal 8 is one of these systems. In this article, I will tell you why it’s worth it to choose Drupal as the basis for any large and advanced website. 

How big is “big”, really?

By large and advanced, I mean one that is changed frequently. Content changes are carried out by at least one editor, supported by at least one developer (along with a QA tester and a sysadmin), who’s responsible for continuous development of the website, adding new functionalities, fixing the emerging bugs and so on. 

Some examples of large and advanced websites:

  • A website of a medium or large production or service company, offering hundreds or thousands of various products or services. The website’s content has to be updated on a continuous basis, including information regarding products, services, promotions, availability and so on. The website is one of the key sales tools and is managed by the company’s marketing and sales departments. It may be a part of a bigger system used to process the orders and post-sale customer support.
  • An informational website, for example, run by a paper or magazine. The new content for the website, which is published on a daily basis, is created by a team of editors. The content creation process has a number of steps (draft, proofreading, approval, publication on a given date, etc.) Once published, content might be edited without the need of reposting it from the scratch, i.e. when broadcasted life situation changes dramatically.

Strona telewizji FOX.com

The Fox.com channel website is made on React front-end and Drupal back-end.

  • An internal web application for managing processes in the company, such as a CRM system, a system supporting the activities of regional sales representatives or a number of company’s branches, intranet system. A system with a variety of data types. The application is available only to users who are logged in and predefined roles in the system define responsibilities. Users create large amounts of data every day.
  • A website of a school or university publishing information from lecturers and teachers for students and employees. There are many types of information divided into categories and displayed in many ways. Users are allowed to take various independent actions on the website, ie. the same Ph.D. student may be able to see the information for students and publish as a lecturer.
  • A system feeding content to other systems – an API with content for other websites and mobile application. There is a need to manage many different types of data and quickly providing them to other external systems.

A chart showing multiple cmf-s and cms-esant their position in market. Wordpress leads, however Drupal is next, and first in the sector of big websites

(Source: https://w3techs.com/technologies/market/content_management)

Drupal in comparison to other systems

Wordpress is still an unquestionable king if it comes to the amount of the websites created with it. It is however mainly used by smaller, static web pages and blogs. Drupal, however, is chosen more often by companies that need big, frequently updated website. Drupal is a leader in this segment of the market thanks to its scalability and easiness of joining it with other systems.
The opinions about Drupal found in many articles only confirm the data from the chart above: Drupal is chosen for building large websites more often than WordPress. 

Why should you use Drupal 8 for building your website?

Because:

  1. It’s a tried and proven system used by large international companies and organisations. Some examples of Drupal users include:  [embedded content]
  2. Drupal 8 is Open Source. It’s completely free. What is also free are thousands of modules available at www.drupal.org. You don’t have to cover any licensing costs like you would have to do with commercial software. 
  3. Thousands of companies around the world work hard on adapting Drupal to customers’ needs (installation, setup, creating templates and modules, hosting). By choosing Drupal, you are not limiting yourself to cooperating with just one company for many years (usually a website is built for 3-6 years).
  4. As a project, Drupal is developed by a community spanning the entire world. Over 100,000 users actively develop Drupal core and its modules. 100,000 developers are definitely more than 10 or even 100 coders working on a given commercial solution. What is more, over 1 million users are registered with www.drupal.org, helping the development by making change requests for the core and the modules.
  5. From the technological standpoint, Drupal 8 was developed in PHP (it uses PHP 7, which is blazing fast), uses Symfony Framework components (believed to be the best solution for developing complex applications in the PHP ecosystem) and Twig template engine, which streamlines front-end works and improves security. 
  6. Drupal Security Team is a special group of people who take care of the security of both Drupal and its modules. The team constantly checks Drupal in order to find any and all bugs. In the case of a security hole, the team quickly publishes bugfixes and updates. Notifications announcing new updates are visible in the website’s administration panel, they can also be received via e-mail. Every Drupal-based website automatically checks whether they have the most current version of Drupal and all the modules. If a new version is released, the administrator gets informed about it at once.
  7. New versions of Drupal 8 are released every six months. Drupal 8.0 was released at the end of 2015. Currently, we are in version 8.4. Every new version introduces new bugfixes, as well as new functionalities and modules available in Drupal core. The Drupal development team aims for adding new functions to expand its usability and capabilities. By choosing Drupal 8 you ensure getting new functions for your website – completely free of charge! 
  8. Webservices – You can use Drupal to build APIs and communicate with other systems. Thanks to this, you can easily fit your new solution into existing systems in the company. You can also use Drupal as a backend for so-called headless systems – Drupal will take care of feeding all the data and content, while they will be displayed by other systems.
  9. Modules and functions in Drupal core – there are many of them, but the most important of them are: 
    • creating any number of data types with any structures, along with relations between various data types
    • extensive categorisation of content (categories, tags, tree structure, many categories for one type of content),
    • version control – tracking changes in the content,
    • activity logs in the system, user activity history (who logged in and where, when was the content added, etc.),
    • extensive user management, roles and permissions,
    • support for many languages,
    • multisite: the ability to build many copies of a single website on a single installation, e.g. for a given country, or separate versions of the website for each product or service,
    • media management (photos, videos),
    • convenient content management: CKeditor – a WYSIWYG editor, content moderation, quick edition and others,
    • views and fields – flexible data structures and displaying,
    • mobile-friendly system, responsive images,
    • migrate API: the core includes a mechanism allowing for convenient content and data export to Drupal,
    • capability to block users based on IP, e-mail, hostname.
  10. Additional modules. There are thousands of them and you can download them for free at https://www.drupal.org/. The most interesting and noteworthy modules are: 
    • Paragraphs – enables flexible content creation. At first, the developer creates various types of recurring elements. Then, editors have the option to use these elements to build their subpages. The subpages can have any number of these elements arranged in any way. You can read more in our blog post.
    • Metatag – enables managing meta tags for all your SEO needs. You can create tags separately for each subpage or define templates, based on which Drupal will automatically create tags for new subpages.
    • Google Analytics: integrate your website with Google Analytics, you can go for simple or complex integration in order to learn more about your users.
    • Pathauto: enables automatic creation of URL aliases based on a given template (e.g. /news/category(title)).
    • Webform: enables creating forms using Drupal administration panel. Thanks to that module, you can create a form for gathering your users’ data or a survey within minutes.
    • SitemapXML: creates an XML map with your website’s structure, required by Google and other search engines.
    • Captcha: add captcha tests to any form in order to protect your website from spam.
    • Panels: enables the creation of new subpages using the drag&drop methodology. You can define a new page, decide its layout (e.g. 3 columns) and add content to each of the elements.
    • SMTP: enables sending e-mails from Drupal using external servers. You can also set it up to send e-mails with HTML content. It's very useful when you send a lot of e-mails to your users and you want for example to track their statistics using external services.
    • Search API + Solr: enables you to connect Apache Solr to Drupal. This significantly speeds up searching your website, especially if you have a lot of content.
    • Scheduler: enables to you schedule publication of your content to a given date.
    • AddToAny share buttons: allows for quickly adding icons to share your content on social media.
    • Commerce: a module that is used to build online stores.
    • MailChimp or Freshmail: integration with popular newsletter systems.
    • Focal point: cropping photographs before publication.

Summary

You can find the full list of modules at https://www.drupal.org/project/project_module
Above, I listed my take on the ten most important reasons for using Drupal. There are, however, many more benefits to using that framework. The best way to discover them all is to try it yourself. In this case, it would be also best to install additional modules to learn the full extent of its capabilities. 
We released a distribution (consisting of Drupal core and additional modules) which includes much more functionality than the bare core and, on top of that, a very beautiful design. You may find more details on our blog and at www.droopler.pl
Already a Drupal user? Tell us in the comments what are the most important reasons and why do you consider it worthwhile to use Drupal! 

Dec 12 2017
Dec 12
What is the CKEditor? It is one of many visual HTML editors. It allows you to easily enter text using an interface that resembles such editors as OpenOffice.  It makes text formatting easier through a set of buttons that serve, among others, for things such as: changing the font, text size, adding an image, making lists, and many others. The CKEditor is the default text editor in the Drupal 8 system. You do not need to add any libraries or modules in order to use it.  Enabled editor in the contend adding form By default, the editor is enabled for two text input formats:
Nov 23 2017
Nov 23

Droptica is an amazing company. I've worked with Drupal specialists in the past... Nothing worked in terms of quality and value, but they hit the sweet pot. They provided good-quality code at a reasonable price point.

Founder, E-Commerce Platform

I could not rate Droptica highly enough. They have genuinely helped our dream service became a reality... The site is looking awesome, and we can't wait to relaunch. We have untold efficiency gains now.

Head of IT, Compliance & regulatory Platform

Jul 31 2017
Jul 31
Has it ever happened to you that when you were looking on a website, you weren’t sure whether a font you used was 12 pt or 13 pt? Or maybe you kept looking at an image, wondering whether it had been moved slightly to the left before? If the layout is a priority on your website, maybe it’s time to think about automating the testing of this aspect of your project. VisualCeption is a noteworthy solution for exactly this use case. In this article, we are going to show you how to launch this add-on on a project built using the docker-console. Just like in our previous articles, our examples will be based on the project that you already know from our previous posts.
Jul 14 2017
Jul 14
Taking into consideration the fact that most of our products are based on Drupal, the tests should also naturally work best with such projects. This is why we decided to complement the standard functionality of Codeception with some new modules dedicated for Drupal. As in our previous article, all examples listed below will be based on a project based on docker-console, which is why we encourage everybody to read the previous articles first if you didn’t do so yet. If you already have your Codeception project and just want to slightly modify it so that it works better with Drupal, this article is also for you.
Jun 26 2017
Jun 26
If you read our previous posts, you already know very well how to start a project in the docker-console. If you haven’t done it yet, you should start with this article, because for the purpose of this article we assume that your project in the docker-console is already up and running, therefore all commands executed below will refer to it. In this article, we would like to introduce you to the world of automatic tests using Codeception, based on this kind of a project. Of course, not everyone has to automate all the tests on their projects, but if this will not require too much work, we bet that many people will look at a set of “smoke tests” favourably, to say the least. 
Jun 06 2017
Jun 06

People who follow our blog already know that we’re using Docker at Droptica. We've also already shown you how easy it is to start a project using our docker-drupal application (https://www.droptica.pl/blog/poznaj-aplikacje-docker-drupal-w-15-minut-docker-i-przyklad-projektu-na-drupal-8/). Another step on the road to getting efficient and proficient with Docker is docker-console application, which is a newer version of docker-drupal, and exactly like its predecessor it was created in order to make building a working environment for Drupal simple and more efficient. How does it all work? You are going to see that in this write-up. Since we're all working on Linux (mainly on Ubuntu), all commands shown in this post were executed on Ubuntu 16.04.

Installing Docker

Of course, our adventure starts with installing Docker, you could read about this in one of our earlier posts. Just for the sake of clarity, in order to install Docker, you have to execute the following commands:
 

wget -qO- https://get.docker.com/ | sh 

sudo usermod -aG docker $(whoami) 

sudo apt-get -y install python-pip

sudo pip install docker-compose

Installing docker-console

Another step is to install the docker-console application. In order to do so, you should first install python-pip package, which allows to quickly install and upgrade our application:

sudo apt-get update && sudo apt-get -y install python-yaml python-setuptools python-pip python-dev build-essential 

Now all you have to do is to install docker-console, which can be done using the following command:

sudo pip install docker-console 

After the installation completes, a new command – docker-console (or dcon for short) – will be available in your terminal. After launching it, you should get a list of available options and actions:

Docker console available options and actions

Initialisation of a new project

Now we can finally begin our adventure with docker-console. To start with, let's assume that we don't have any Drupal project available, so we have to start a new one. This is possible by using the following command:

docker-console init --tpl drupal7 

Project's structure with visible folders

After running it, it should generate an entire project structure for us (like on the image above), which will allow us to quickly and efficiently organise a project. The command is used for generating Drupal 7 project structure, but nothing stops you from using a command to generate a Drupal 8 project instead:

docker-console init --tpl drupal8 

However, for the purpose of this guide, I will stick to a Drupal 7 project. The next step is downloading an appropriate version of Drupal from https://www.drupal.org/project/drupal and unpacking the archive to the “app” folder.

Start the containers

At that point, in order to start working with the project, you will also have to launch the containers with services required for the page to work (e.g. Apache, MySQL, PHPMyAdmin, Nginx – in a traditional working environment, you would have to install them locally on your machine). All the services we will need for work should be added and configured in docker-compose.XML file (the file for this project is presented below and can be found in the main folder of the project.) We build our docker-compose files based on version 1. If you would like to learn more about how it’s built, you should visit the project’s website:  https://docs.docker.com/compose/compose-file/compose-file-v1/ 
The configuration you can see below will launch three containers:

  • web: Apache and PHP,
  • MySQL,
  • PHPMyAdmin.

Three containers ready to be opened

In order to start the containers, execute the following command:

dcon up 

After a moment (a longer moment during the first launch, because all the images will have to be downloaded first) you should see a result that’s similar to this:

Containers opened up and running

The website is now built, you can go to the container’s IP address and take a look. You can check the IP address by running “docker inspect”.

docker inspect --format "{{ .NetworkSettings.IPAddress }}" dockerconsoleprojectexample_web_1 

In my case, the address was  http://172.17.0.23/ (it may be different, depending on the containers you launch).

Installing Drupal

After going to that address, you should see Drupal installation screen. It is by no means different than a standard one, therefore I am not going to write a step-by-step instruction. However, it is very important to use the data from your docker-compose.yml file when prompted to configure your database, exactly as it is shown in the illustrations below. The database name should be in line with MYSQL_DATABASE parameter, same goes to the user details (the username can be set in MYSQL_USER with a password stated in MYSQL_PASSWORD, you may also decide to use root, the password for root is set in MYSQL_ROOT_PASSWORD), you also have to enter the name of our database container as a host, otherwise you will not be able to connect to it.

All names are in line, database connected

All names are in line, database connected

Website launched

Now, when your website is ready and available at the container’s IP address, you can implement your changes and add content. You should, however, keep in mind that everything is happening in Docker containers, so if you remove them, everything – including the database – will be lost. This does not apply to the application files since they are only mapped from a local folder to the app folder in a container. If you want to secure your database and prevent losing it even if you remove the containers, you should also map your database files to a local folder. By doing so, you will allow them to synchronise with a folder in the container. What is more important, the database is not deleted when the containers are just stopped, for example when you turn off your computer. In this case, you can quickly relaunch them by running “dcon up” again. In another example, we will dump the database, which we will be able to use later in order to build another project.

Rebuilding a project

The first thing you should do is dump your database and files. To do this, I used the backup and migrate module ( https://www.drupal.org/project/backup_migrate), but you can do it in any way you like. It is, however, crucial that the files and the database end up as tar.gz archives named database.sql.tar.gz and files.tar.gz. After that, place the database file in the app_data folder, then move the compressed files to app_files.
If you would like to get to the PHPMyAdmin container in order to dump the database, you can, of course, do it just as easily by going to the IP address of the PHPMyAdmin container in your browser and logging in with the data from docker-compose.yml file shown above.
If you did not go through all the earlier steps, you can download my project, database and files. This way, you will be able to start your adventure with docker-console without creating your own project after installing docker, docker-compose and docker-console.
Project repository: https://github.com/DropticaExamples/docker-console-project-example
Database dump: https://www.dropbox.com/s/tcfkgpg2ume17r3/database.sql.tar.gz?dl=0
Project files: https://www.dropbox.com/s/hl506wciwj60fds/files.tar.gz?dl=0
In order to clone my project and launch the service containers, you will have to run the following commands in your terminal:

cd

git clone https://github.com/DropticaExamples/docker-console-project-example

cd docker-console-project-example 

git checkout docker-console-start 

cd app_databases wget https://www.dropbox.com/s/tcfkgpg2ume17r3/database.sql.tar.gz?dl=0 

cd ../app_files wget https://www.dropbox.com/s/tnl0ftfluyr5j7p/files.tar.gz?dl=0 

cd .. 

dcon up 

Otherwise, if you are using a project created beforehand, all you have to do is just:

dcon up 

Unless, of course, you had the containers already launched, in this case, you will not have to start them again (running “dcon up” when your containers are up and running should only tell you that they are running and up-to-date.)

Installed and running containers

If you are not sure whether your docker containers are built and active, you can check it using:

docker ps -a 

If everything went well, you should have three containers up and running:

  • web: Apache and PHP,
  • MySQL,
  • PHPMyAdmin.

Building a project

In this step, we are going to restore our working environment based on the files and the database, which were placed in proper folders beforehand. By doing so, we can constantly work in an environment that is close to production. Now we can build a website on working containers. In order to do so, execute the command:

dcon build 

In previous examples, we did not do it, because there was no need to start a project building sequence – there are no files and the database is empty when you are starting a new project). In this example, the building process covers the following steps:

  • confirmation that the building process should start;
  • copying settings;
  • cleaning database;
  • importing database;
  • unpacking files;
  • cleaning cache (drush cc all);
  • generating login link (drush uli);
  • changing file permissions.

This is why when we want to import a database and files to a project, we have to run dcon build.

Website’s ready

The website is now built and you can take a look at it exactly like before, by going to the container’s IP address.

Website is ready!

Summary

This is how you can quickly set up a project based on Docker and docker-console. At your first attempt, it may seem that the procedure is quite complicated, but you can take my word that you will quickly see a return on all your time invested into learning Docker, especially when you will want to quickly add a new service to an existing project or test some other configurations. Of course, this post is not fully exhaustive, and if the time allows, we are going to write more about docker-console. In the meantime, I encourage everyone to read the project’s readme file at  https://github.com/droptica/docker-console and try to set up your own project with Drupal 8. Let us know how it went :) We are also going to share the DrupalCamp Wrocław 2017 videos with you soon, featuring Maciej Łukiański talking about docker-console and some other stuff. 

Apr 04 2017
Apr 04

In Drupal 8 we can easily add our own command to Drush. The whole code for the new command will be put in a custom module.

We have to create only 2 files.
The structure looks as follows.

The structure of the file visible as tree of catalogs

File d_drush_command_pack.info.yml

A standard file of every module in which there is information about our plugin.

name: Droptica Drush Command Pack
description: Provide useful custom drush commands
package: Drush Commands
type: module
core: 8.x

File d_drush_command_pack.drush.inc

Here, we define our commands and we put our logic that will be executed by a given command.
The following example generates two new commands.

<?php

/**
 * Implements hook_drush_command().
 */
function d_drush_command_pack_drush_command() {   $commands['rebuild-aggregate-file'] = [
    'description' => 'Rebuild aggregate css/js files',
    'aliases' => ['raf'],
    'arguments' => [      
       'js' => 'Rebuild aggregate js files only',
      'css' => 'Rebuild aggregate css files only',
    ],
    'examples' => [       
      'drush raf' => 'Rebuild aggregate css/js files',
      'drush raf js' => 'Rebuild aggregate js files',
      'drush raf css' => 'Rebuild aggregate css files',
    ],
  ];

  $commands['delete-node-alias'] = [
    'description' => 'Delete a node alias',
    'aliases' => ['dna'],
    'arguments' => [       
      'source' => 'Delete by source',
      'alias' => 'Delete by alias',
    ],
    'options' => [      
        'name' => 'Name of source or alias',
    ],
    'examples' => [       
      'drush dna source /node/1' => 'Delete an alias by source path',
      'drush dna alias /path-alias-name' => 'Delete an alias by alias path name',
    ],
  ];

  return $commands;
} /**
 * Drush command logic for rebuilding file cache.
 *
 */
function drush_d_drush_command_pack_rebuild_aggregate_file($arg = NULL) {   $tokens = ['@arg' => $arg];
  switch ($arg) {     case 'js':
      \Drupal::service("asset.js.collection_optimizer")->deleteAll();
      _drupal_flush_css_js();
      drush_print(dt('Rebuild aggregate @arg files.', $tokens));
      break;
    case 'css':
      \Drupal::service("asset.css.collection_optimizer")->deleteAll();
      _drupal_flush_css_js();
      drush_print(dt('Rebuild aggregate @arg files.', $tokens));
      break;
    case '':
      \Drupal::service("asset.css.collection_optimizer")->deleteAll();
      \Drupal::service("asset.js.collection_optimizer")->deleteAll();
      _drupal_flush_css_js();
      drush_print(dt('Rebuild aggregate js/css files.'));
      break;
    default:
      drush_print(dt('Wrong argument. Possible arguments: js, css or use command without argument.'));
  } }

/**
 * Drush command logic for deleting aliases
 *
 */
function drush_d_drush_command_pack_delete_node_alias($arg = NULL, $opt = NULL) {   $tokens = ['@arg' => $arg, '@opt' => $opt];

  switch ($arg) {     case 'alias':
    case 'source':
      $condition = [$arg => $opt];
      \Drupal::service('path.alias_storage')
        ->delete($condition);
      drush_print(dt('Alias @opt deleted', $tokens));
      break;

    default:
      drush_print(dt('Wrong argument and options. Example use: drush dna source /node/1'));
  } }

The above code creates two new drush commands for us
The first one is rebuild-aggregate-file
The second one is delete-node-alias
The commands are defined in the hook:   hook_drush_command(),
here, we set alias, arguments, options and examples for our command
Logic for each of them is created in separate functions.
We create the names of the functions like this: 
drush_[MODULE_NAME]_[COMMAND_NAME]()
All we have to do is turn our new module on, clear cache and test the commands.
Examples of launching the commands from the above code.

drush rebuild-aggregate-file css
drush raf js
drush raf

drush dna source /node/1
drush dna alias /alias-name

You will find the files of the sample module on GitHub.

Mar 01 2017
Mar 01

Content creation using the Paragraphs module is a completely different approach compared to the "standard" content creation in Drupal.
In short: we prepare the components (paragraph type) and then, during the creation of an entry, we select any of the available components. 
The components can be simple elements containing text, contents with columns or such complex elements as sliders, videos or photo galleries. There are practically no constraints; we can define the available components by ourselves, which will then be used by people dealing with content management. 
We can prepare our own templates for the components (tpl.php files). Properly prepared templates and styles for them will ensure the same display of components, regardless of their place of use and the device (responsiveness).
It is a much more flexible and repeatable solution than creating such things in WYSIWYG editors, where the elements do not always look like we want them to be, not to mention adapting such content to a mobile versions of a website.
The result is a nicely formatted page of elements that are repeatable and consistent throughout the whole website.

Paragraphs is a great convenience for the editor of a website

Nothing can be more upsetting for a website editor than when during adding the content, he fills it with photographs or other elements and after saving, the entire content does not look like it was during the editing process.
Attempts to fix this are usually difficult, time-consuming and inconvenient (you must often add styles in the WYSIWYG view source mode). For people unfamiliar with HTML and CSS it will often become an insurmountable problem. 
The properly prepared configuration of the Paragraph module saves time for those involved in content management. They can concentrate on the content, that is – on what they actually should be doing, and not on text formatting (which should be automatically done by CMS).

Content creation with the paragraph module

On the page with the content adding form, we will see a list with types of components (defined by the programmers) available in the system.
In one entry, we can choose an infinite number of components (of the same type or different types) and then freely change their order.

paragraph with addition

Below are shown exemplary types of paragraphs.

Slider Slick with pictures added during content editing

slick slider

And here is how creating a slider looks like – it is a simple thing to do as you just add pictures.

adding new photos

A simple text field

simple text area

It can be freely styled and each time it will look the same.
In addition, to each paragraph, we can hook up its own predefined class with the styles.
For example, changing the background colour or background image is only a matter of choosing the appropriate class.

adding the predefined class

 

Multi-column fields
Text with a picture

text with photo

Three pictures next to each other

three photos together

The module forms the programmer's side

Using the module and creating new types of paragraphs is very easy for a programmer.
Everything is done on the page and in most cases, the whole process consists of adding the appropriate boxes for a given type.
In the examples in the text, aside from the Paragraphs module, we also use the Classy paragraphs module. Thanks to that, we can attach predefined CSS classes to the selected paragraph.

Creation of a new type of the paragraph

Structure -> Paragraphs types
admin/structure/paragraphs_type

creating the new paragraph

After adding the paragraph, you just have to add the boxes. 
Many types of boxes are available and located in the Drupal's core as well as those from the contrib and custom modules. 

managing the fields

Once we have created the types, they must be "hooked" to the entity eg. the content, block or any other serving the boxes.
Linking is performed with a special field: Reference revision - Paragraph
In this case, it adds the paragraphs to the Page type of content

adding a field

In field settings we select which types of paragraphs we want to have available in a given type of entity. If we do not select anything, then all types are available.

all types available

 We just have to save; and during the adding of content, any paragraph can be introduced.

new paragraph enabled

Adding your own CSS classes to the paragraph.
The Classy paragraphs module is a useful tool if you want to give editors a possibility to eg. change the background colour of a given paragraph. 
Of course, we do not have to limit ourselves to just changing colours. All that CSS offers can be implemented here.
Add a linking field to the paragraph.

adding a field

 

After saving, choose the Classy paragraph styles as a reference.

classy field

At this stage, it is all.
Now you have to define classes so they can be hooked to the paragraph.
You can define them with Structure ->Classy paragraphs style

classy paragraph style

Here are the defined three simple classes for changing the background colour.
The settings are important when it comes to choosing the name of the class. 
Remember that the label should be understood by the editor, it is precisely this text that will be displayed during the selection.

editing classy paragrapgh styles

All the magic happens already in CSS.

"css "magic""

From this point, the editor can choose the class when creating a paragraph.
As you can see in the example, there can be several such fields with classes.

fields with some classes

References:

https://www.drupal.org/project/paragraphs 
https://www.drupal.org/project/classy_paragraphs 
https://dev.acquia.com/blog/drupal-8-module-of-the-week/drupal-8-module-of-the-week-paragraphs/15/03/2016/9881

Jan 05 2017
Jan 05

Over the course of recent years, websites have undergone a significant change. Many new services and social media websites have been created, mobile applications now play a very significant role on the internet, and various on-line services exchanging data is nothing out of the ordinary anymore. We could even say that integration with external services is standard now, especially in the case of large e-commerce applications or on-line payment systems.
Here we may ask ourselves a question: can we communicate with external services using Drupal? Of course we can. This functionality was available in old versions of Drupal, but with Drupal 8, the RESTful Web Services API module started being included by default in Drupal core, which shows that it is an important and much-needed element in complex on-line applications.

Today we are going to discuss one of the more popular data exchange formats - JSON.

In our example, we are going to use Drupal 8.2^ and jQuery to write a simple JavaScript application. We are going to use Drupal as our CMS for managing data, and our content will be displayed on a “light” HTML website.

1. First, we install Drupal 8 and turn on our modules:

  • The RESTful Web Services API is new in Drupal 8
  • Serialization

chosen services being ticked

2. Then we download and turn on the REST UI module (this step is optional but useful).

https://www.drupal.org/project/restui
This module enables the user to manage access and data format via the UI (administration panel). It works with Drupal 8.2 or newer.

3. Configuration using REST UI - displaying the node in JSON format.

Now we are going to adapt our content type to integration. In our example, we are going to use the NODE entity. Go to /admin/config/services/rest. Select “content type” and set format json, auth cookie in the GET method. In this case, we are only going to download data, so the GET method will be perfectly fine.

Drupal 8 rest UI

If you decide not to install the REST UI module, you will have to enter the settings for all entities manually in config files. The above settings look as follows:
Filename:  rest.resource.entity.node.yml

uuid: add2fdec-b11f-45ad-a74f-3d30e36ad72f
langcode: en
status: true
dependencies:
  module:
    - node
    - serialization
    - user
id: entity.node
plugin_id: 'entity:node'
granularity: method
configuration:
  GET:
    supported_formats:
      - json
    supported_auth:
      - cookie

4. Let’s now create our node.

Assuming that our new node is located at http://www.drupal8.dev/node/1
we have to add a ?_format=json parameter, which gives us the following address: domain.example/node/1?_format=json 

If everything is configured properly, we should now have a node object in JSON format. If you display JSON content in your browser, you can install an add-on or extension for formatting JSON code (the one you can see on the screenshot is JSON Lite https://addons.mozilla.org/en-US/firefox/addon/json-lite/?src=api)

drupal node in JSON format

5. List of nodes in JSON

All right, so downloading single nodes is already working. Let’s now try to get a list of nodes.
We are going to use the Views module.

views - creating json

Provided that we are not going to use the majority of available data, we can select just the fields that concern us in order to reduce the amount of data transferred.

JSON rest options in views

To sum up: we created a list of content located at /node_list, and by adding ?=_format=json to our URL we can download any of them in JSON format.

6. Own address for REST/JSON (endpoint)

If - for any reason - the above solutions aren’t enough, we can create our own endpoint and add new data to our JSON.
Let’s create routing and a controller.

Routing

First, let’s start from creating a routing at, e.g. /v1/custom_endpoint. Entering our API version in the URL is definitely good practice, since while creating a newer version we can leave it at /v2/custom_endpoint, /v3/... etc. This way our users who use an older version of the API won’t get cut off from our resources.
Routing example:

ev_client_endpoint:
  path: '/v1/custom_endpoint'
  methods:  [GET]
  defaults:
    _controller: 'Drupal\ev_client_endpoint\Controller\EvEndpoint::get'
  requirements:
    _permission: 'access content'

Explanation: by requesting GET at /v1/custom_endpoint we are going to receive the data returned by EvEndpoint controller executing GET method.

Controller

For this example, we will assume that our endpoint is supposed to return basic information about our website - the name and e-mail address, current time stamp and a random node with ID of 1 through 10.

<?php

namespace Drupal\ev_client_endpoint\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\node\Entity\Node;
use Symfony\Component\HttpFoundation\JsonResponse;

/**
 * An example controller.
 */
class EvEndpoint extends ControllerBase {

  /**
   * {@inheritdoc}
   */
  public function get() {

    $response = new JsonResponse();
    $config = \Drupal::config('system.site');
    $node = Node::load(random_int(1,10));
    $data = array(
      'date' => time(),
      'site_name' => $config->get('name'),
      'site_email' => $config->get('mail'),
      'random_node' => array(
        'title' => $node->get('title')->getValue()[0]['value'],
        'body' => $node->get('body')->getValue()[0]['value'],
      )
    );

    $response->setData($data);

    return $response;

  }
}

After doing everything correctly, we can clean our cache and go to /v1/custom_endpoint. The end result should be as follows.

​
{
"date": 1481920261,
"site_name": "custom endpoint site",
"site_email": "[email protected]",
"random_node": {
"title": "title node 5",
"body": "body node 5"
}
}

​

7. Receiving JSON

Let’s now create a simple JavaScript to display our data on the website.
If we are going to connect from domains other than our Drupal, the https://www.drupal.org/project/cors, adding headers to requests or creating a virtual proxy might be useful, so that all the requests are seen as local (you can find out more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)

Code html index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="http://www.droptica.com/blog/drupal-8-restjson-integration-simple-javascript-application//app.js"></script>
</head>
<body>

</body>
</html>

Now we can add our app.js file and jQuery library in the Head section.
Script app.js

$(document).ready(function () {
  $.ajax({
    type: 'GET',
    url: 'http://drupal8.dev/v1/custom_endpoint',
    success: function (data) {
      {
        var date = new Date(data.date * 1000);
        $('body').append('' +
          '<h1 class="name">' + data.random_node.title + '</h1>' +
          '<content class="body">' + data.random_node.body + '</content>' +
          '<email class="mail">' + data.site_email + '</email>' +
          '<div class="date">' + date  + '</div>' +
          '<h2 class="email">' + data.site_name + '</h2>'
        );
      }
    }
  });
});

Download JSON from our Drupal: /v1/custom_endpoint

The data variable contains our json, now we can add it with our variables to the HTML body using append function.

If everything has been done properly, upon displaying index.html in our browser, the JavaScript requests the data from our Drupal and downloads it in JSON format, and then adds them to the body of our website.

Summary

These are some basic information regarding starting the adventure with web services using Drupal. In the next part, we are going to write about logging into Drupal using an existing user account, as well as adding and editing content via REST/JSON.
If you want to further expand your knowledge about D8 and other tools useful for designing web applications, give us a like on Facebook, where we share our tutorials, guides and various interesting stuff from the industry. You can also take part in Drupal Day and the Drupal Camp! New content is also coming soon to our blog!

Dec 13 2016
Dec 13

Time has already passed since the premiere of Drupal 8. New projects and modules are released all the time, and there is an ever-increasing number of projects compatible with version 8.x at drupal.org. Sadly, these versions are often still unstable and filled with various bugs. As of today, the number of additional modules available for Drupal 8 is around 2,250, compared to 12,400 Drupal 7 modules. It is immediately visible that the range of ready-made solutions is far more narrow in the case of the new generation, compared to the older one. However, even though in the case of advanced projects, writing them from scratch might be pointless, in the case of smaller add-ons, we can try to port the entire module or its interesting functionalities to version 8.x. In this guide, we are going to port a module used by us to display the cookies disclaimer on our website to be used with Drupal 8.

v. 7.x structure image

This is what the file structure of v. 7.x looks like. The module is fairly simple, as it contains a custom CSS file, a JavaScript, two templates, one included .inc and the standard .info and. module files.
In order for the script to be visible by Drupal 8, we are going to need an .info.yml file. Let us start with this one. In D8, it is the only file required for the module to be seen by the system.

Drupal 7

cookiec.info

name = CookieC
description = This module aims at making the website compliant with the new EU cookie regulation
core = 7.x

Drupal 8

cookiec.info.yml

name: CookieC
type: module
core: 8.x
version: 8.x-1.0
description: This module aims at making the website compliant with the new EU cookie regulation
configure: cookiec.settings

The files are fairly similar – as you can see, the main difference here is the file format. Since Drupal 8 uses YML files, the file needs to have an .info.yml extension. Additionally, we also have to add type: because skins are using similar syntax, in our case this is going to be type: module. Additionally, in this file, we can add ‘configure:’ – a routing hook to the configuration page. However, we are going to discuss routing in the next part. It is worth mentioning that – just like in Python – indentations in the code are crucial. After purging the cache, the module should be already visible on the list.

CookieC visible on the list

Let’s now see what can be found in a D7. module file. Our module uses the following hooks/functions:

  • hook_menu – used for defining /cookiec page, which displays our cookie policy,
  • hook_init – used to initiate our functionality, including the function loading our custom css and js files,
  • hook_permission – permission for administering our module,
  • hook_theme – template definitions.

In D8 hook_menu, hook_permission and hook_init were done away with.
The tasks of hook_menu are now covered by “module_name.routing.yml”, and instead of hook_init we are going to use EventSubscriber.
 

Drupal 7

Hook menu included in the .module file

<?php
/**
 * Implements hook_menu().
 */
function cookiec_menu() {
 $items['cookiec'] = array(
  //'title' => '',
  'description' => 'Cookie policy page.',
  'page callback' => 'cookiec_policy_page',
  'access arguments' => array('access content'),
  'file' => 'cookiec.page.inc',
 );
 return $items;
}

Drupal 8

Contents of the cookiec.routing.yml file:

cookiec.render_cookiec:
  path: '/cookiec'
  defaults:
    _controller: '\Drupal\cookiec\Controller\Cookiec::renderPage'
    _title: ''
  requirements:
    _permission: 'access content'

The *.routing.yml file contains the name of the routing – cookiec.render_cookiec.
Path: URL address, allowing us to access a given functionality; as in D7 we can also use dynamic paths, such as for example: path: 'example/{user}', in this case it won’t be needed, since our module displays only a static page.
defaults: _controller: '\Drupal\cookiec\Controller\Cookiec::renderPage’ at /cookiec content will be displayed, returned by Cookiec class using renderPage() method. We will write about this in detail while creating /cookiec. static page.
Requirements: We are going to add access permissions in _permission: access content.
We should create all the classes and methods assigned to our routings at once in order to avoid displaying errors.
We are going to create a simple “Hello World” example. Let’s start by creating a Cookiec.php file in /src/Controller:

namespace Drupal\cookiec\Controller;

use Drupal\Core\Controller\ControllerBase;

class Cookiec extends ControllerBase {

 function renderPage(){

  return array(
   '#title' => '',
   '#markup' => 'hello word!',
  );
 }
}

After purging the cache and going to /cookies we should get a page saying “Hello World”.
 

In order to create our own permissions, we are going to create module.permission.yml file, similarly to other .yml files:

administer cookiec:
 title: 'Administer cookiec administration message module'
 description: 'Perform administration tasks for cookiec'

We also add the following to our routing:

requirements:
 _permission: 'administer cookiec'

Using the form class is a useful solution in this case.

cookiec.settings:
 path: '/admin/config/content/cookiec-settings'
 defaults:
  _form: '\Drupal\cookiec\Forms\CookiecSettingsForm'
  _title: 'cookiec configuration'
 requirements:
  _permission: 'administer cookiec'

The name of the cookiec.settings routing is going to be placed in the info.yml file (configure: cookiec.settings), thanks to which the module configuration button will redirect us to this form.
 

Hook_init, which in D7 started every time the page loaded was removed in D8. In order to get a similar functionality, we are going to use Events, specifically EventSubscriber.
In order to create EventSubscriber in Drupal 8 we are going to need a service. We create service just like other .yml files:
Add the following to cookiec.service.yml:

services:
 cookiec_event_subscriber:
  class: Drupal\cookiec\EventSubscriber\CookiecSubscriber
  tags:
   – {name: event_subscriber}

In order for our service to be an Event Subscriber, we need to create a class implementing the interface – EventSubscriberInterface. In order for it to work correctly, we are going to create three methods:
in src/EventSubscriber/CookiecSubscriber.php

/**
 * @file Drupal\coociec\EventSubscriber\PopupMessageSubscriber
 */
namespace Drupal\cookiec\EventSubscriber;

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


/**
 * Class PopupMessageSubscriber
 * @package Drupal\cookiec\EventSubscriber
 */
class CookiecSubscriber implements EventSubscriberInterface {

protected $config;
 /**
  * CookiecSubscriber constructor.
  */
 public function __construct() {
  $this->config = \Drupal::configFactory()->get('cookiec.settings');
 }

 public function showCookiecMessage(FilterResponseEvent $event) {
  // Check permissions to display message.
  $response = $event->getResponse();

  if (!$response instanceof AttachmentsInterface) {
   return;
  }
 }

 /**
  * {@inheritdoc}
  */
 public static function getSubscribedEvents() {
  $events[KernelEvents::RESPONSE][] = array('showCookiecMessage', 20);

  return $events;
 }
}

Load the module settings in our constructor, which will be later passed to the JavaScript.
In order for our event to work, we have to add the getSubscribedEvents() method, put in the name of the method (showCookiecMessage) which will be called and the weight (20). We can use weight to set up the order of the events.

 public static function getSubscribedEvents() {
  $events[KernelEvents::RESPONSE][] = array('showCookiecMessage', 20);

  return $events;
 }

Our next step will be transferring over our JS and CSS files – in our case they are going to be left almost without any significant changes. Instead, we are going to focus on loading them while executing our code.
If we want to add external JS or CSS files to our module, we can create a file named module.libraries.yml, in our case this is going to be cookiec.libraries.yml

cookiec_library:
 version: 1.x
 css:
  theme:
   css/cookiec.css: {}
 js:
  js/cookiec.js: {preprocess: false}

We added cookiec.css and cookiec.js files here. If we needed to load the existing libraries, we could add them using dependencies, for example:

 dependencies:
  – core/jquery

 
In order to load our libraries now, we can use for example hook_preprocess_HOOK. In this case we have to add the following to our variables:

$variables['#attached']['library'][] = 'cookiec/cookiec_library';

In our examples we add our files right as the event loads. We are going to use the following methods to achieve this:

  $response = $event->getResponse();
  $attachments = $response->getAttachments();
  $attachments['library'][] = 'cookiec/cookiec_library';
  $response->setAttachments($attachments);

Our module does the majority of its magic client-side. To work properly, our script requires sending several parameters. Settings such as height, width, the displayed text or position are sent to drupalSettings array in JS.

  $variables = array(
   'popup_enabled' => $config->get('popup_enabled'),
   'popup_agreed_enabled' => $config->get('popup_agreed_enabled'),
   'popup_hide_agreed' => $config->get('popup_hide_agreed'),
   'popup_height' => $config->get('popup_height'),
   'popup_width' => $config->get('popup_width'),
   'popup_delay' => $config->get('popup_delay')*1000,
   'popup_link' => $config->get($language."_link"),
   'popup_position' => $config->get('popup_position'),
   'popup_language' => $language,
   'popup_html_info' => $html_info,
   'popup_html_agreed' =>$html_agreed,
  );

The values of the variables are taken from the module settings – configs. We are going to discuss this in a bit.
This is how we send our PHP variables to JS.

  $attachments['drupalSettings']['cookiec'] = $variables;

$html_info and $html_agreed store html code, obtained by parsing TWIG templates and the variables:

  $variables = array(
   'title' => 'title',
   'message' => $config->get($language."_popup_info"),
  );

  $twig = \Drupal::service('twig');
  $template = $twig->loadTemplate(drupal_get_path('module', 'cookiec') . '/templates/cookiec_info.html.twig');
  $html_info = $template->render($variables);


  $variables = array(
   'title' => 'title',
   'message' => $config->get($language."_popup_info"),
   'more' => 't(more)',
   'hide' => 't(hide)',
  );
  $twig = \Drupal::service('twig');
  $template = $twig->loadTemplate(drupal_get_path('module', 'cookiec') . '/templates/cookiec_agreed.html.twig');
  $html_agreed = $template->render($variables);

We are going to discuss TWIG in a second.

 
The entire file with EventSubscriber looks like that:

<?php

/**
 * @file Drupal\coociec\EventSubscriber\PopupMessageSubscriber
 */
namespace Drupal\cookiec\EventSubscriber;

use Drupal\Core\Language\LanguageManager;
use Drupal\Core\Render\AttachmentsInterface;
use Drupal\Core\Render\Element;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;


/**
 * Class PopupMessageSubscriber
 * @package Drupal\popup_message\EventSubscriber
 */
class CookiecSubscriber implements EventSubscriberInterface {

 /**
  * @var \Drupal\Core\Config\ImmutableConfig
  */
 protected $config;

 /**
  * PopupMessageSubscriber constructor.
  */
 public function __construct() {
  $this->config = \Drupal::configFactory()->get('cookiec.settings');
 }

 /**
  * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
  */
 public function showCookiecMessage(FilterResponseEvent $event) {
  // Check permissions to display message.
  $response = $event->getResponse();

  if (!$response instanceof AttachmentsInterface) {
   return;
  }
  // Check module has enable popup
  $config = $this->config;
  $language = \Drupal::languageManager()->getCurrentLanguage()->getId();

  $variables = array(
   'title' => 'title',
   'message' => $config->get($language."_popup_info"),
  );

  $twig = \Drupal::service('twig');
  $template = $twig->loadTemplate(drupal_get_path('module', 'cookiec') . '/templates/cookiec_info.html.twig');
  $html_info = $template->render($variables);


  $variables = array(
   'title' => 'title',
   'message' => $config->get($language."_popup_info"),
   'more' => 'more',
   'hide' => 'hide',
  );
  $twig = \Drupal::service('twig');
  $template = $twig->loadTemplate(drupal_get_path('module', 'cookiec') . '/templates/cookiec_agreed.html.twig');
  $html_agreed = $template->render($variables);

  $variables = array(
   'popup_enabled' => $config->get('popup_enabled'),
   'popup_agreed_enabled' => $config->get('popup_agreed_enabled'),
   'popup_hide_agreed' => $config->get('popup_hide_agreed'),
   'popup_height' => $config->get('popup_height'),
   'popup_width' => $config->get('popup_width'),
   'popup_delay' => $config->get('popup_delay')*1000,
   'popup_link' => $config->get($language."_link"),
   'popup_position' => $config->get('popup_position'),
   'popup_language' => $language,
   'popup_html_info' => $html_info,
   'popup_html_agreed' =>$html_agreed,
  );

  $attachments = $response->getAttachments();
  $attachments['library'][] = 'cookiec/cookiec_library';
  $attachments['drupalSettings']['cookiec'] = $variables;
  $response->setAttachments($attachments);
 }

 /**
  * {@inheritdoc}
  */
 public static function getSubscribedEvents() {
  $events[KernelEvents::RESPONSE][] = array('showCookiecMessage', 20);

  return $events;
 }
}

Another big change in Drupal 8 is the use of config files. These are also YML files, the goal of which is to facilitate synchronisation of settings, variables, and other data saved in the database between environments.
You can read more about this subject here: https://www.drupal.org/docs/8/configuration-management/managing-your-sites-configuration
The D8-compatible version of our module uses configs to store the settings of our window and to load the default settings during installation. After placing the config file in config/install folder, it is going to be automatically loaded on module installation, so we are not going to use hook_install anymore.
Our config/install/cookiec.settings.yml file”

popup_enabled: 1
popup_agreed_enabled: 1
popup_hide_agreed: 1
popup_width: 100%
popup_delay: '1'
popup_height: '100'
en_popup_title: 'Cookie policy'
en_popup_info: 'This website uses cookies. By remaining on this website you agree to our <a href="http://www.droptica.com/cookiec">cookie policy</a>'
en_popup_agreed: 'I agree'
en_popup_p_private: " <p>This website does not automatical....</p>"
pl_popup_title: 'Polityka cookie'
pl_popup_info: 'Powiadomienie o plikach cookie. Ta strona korzysta z plików cookie. Pozostając na tej stronie, wyrażasz zgodę na korzystanie z plików cookie. <a href="http://www.droptica.com/cookiec">Dowiedz się więcej'
pl_popup_agreed: 'Zgadzam się'
pl_popup_p_private: "  <p>Serwis nie zbiera w sposób automatyczny żadnych informacji, z wyjątkiem informacji zawartych w plikach cookies.</p>\r\n  <p>Pliki cookies (tzw. „ciasteczka”) </p>"
en_popup_link: /cookiec
pl_popup_link: /cookiec

If you need to load the data in the website’s code, use configFactory() service with get method and provide the name of the config.

   $this->config = \Drupal::configFactory()->get('cookiec.settings');

This code was used in the CookiecSubscriber class constructor, giving us quick and easy access to all settings of the module.
We are going to assign them to $variables array

...
 'popup_hide_agreed' => $config->get('popup_hide_agreed'),
 'popup_height' => $config->get('popup_height'),
 'popup_width' => $config->get('popup_width'),
...
 

One of the most significant changes after moving from D7 to D8 is the fact that D8 did away with PHP templates in favour of TWIG (http://twig.sensiolabs.org/). This is quite an extensive topic in itself, so we are probably going to write a separate article just about it. Right now, the main takeaway for us is that we cannot use PHP functions anymore, and the logic is limited to simple loops and conditions.
Our Drupal 7 module has two templates:
cookiec-agreed.tpl.php
cookiec-info.tpl.php

​
<?php
/**
 * @file
 * This is a template file for a pop-up informing a user that he has already
 * agreed to cookies.
 *
 * When overriding this template, it is important to note that jQuery will use
 * the following classes to assign actions to buttons:
 *
 * hide-popup-button – destroy the pop-up
 * find-more-button – link to an information page
 *
 * Variables available:
 * – $message: Contains the text that will be display within the pop-up
 */
?>

<div>
 <div class ="popup-content agreed">
  <div id="popup-text">
   <?php print $message ?>
  </div>
  <div id="popup-buttons">
   <button type="button" class="hide-popup-button"><?php print t("Hide this message"); ?> </button>
   <button type="button" class="find-more-button" ><?php print t("More information on cookies"); ?></button>
  </div>
 </div>
</div>

​

We are going to start with changing the names by replacing the extension with xxx.html.twig.
PHP tags are not parsed in .twig files, so we will have to adapt all functions and comments to the TWIG format.

Comments:

If we want to preserve old or add new comments, we have to replace the PHP tags with {# .... #}.

<#
/**
 * @file
 * This is a template file for a pop-up informing a user that he has already
 * agreed to cookies.
 *
 * When overriding this template, it is important to note that jQuery will use
 * the following classes to assign actions to buttons:
 *
 *
 * Variables available:
 * message Contains the text that will be display within the pop-up
 * hide – destroy the pop-up
 * more – link to an information page
 */
#>

Printing the variable values

We can print the variable by placing our variable in brackets like this: {{ variable }}. Our module has three variables:
message, hide, more – they contain translated strings. Adding {{ message | raw }} will cause the html to be rendered in its pure form, without for example replacing . < > into &lt; &gt; .

​
<div>
 <div class ="popup-content agreed">
  <div id="popup-text">
   {{ message | raw}}
  </div>
  <div id="popup-buttons">
   <button type="button" class="hide-popup-button"> {{ hide }} </button>
   <button type="button" class="find-more-button" > {{ more }} </button>
  </div>
 </div>
</div>

​

Logic in TWIG

Our example is fairly simple; however, TWIG allows us to use simple logic. Logic operations are wrapped between {% %} tags.
We can use tags, variable filters and functions.
Here are some examples:

Example tags:

For each loop:

  {% for user in users %}
    <li>{{ user.username|e }}</li>
  {% endfor %}

IF condition:

{% if online == false %}
  <p>Our website is in maintenance mode. Please, come back later.</p>
{% endif %}

Variable operations:

{% set foo = 'bar' %}

 
Example filters:

We use filters by adding | in {{}} brackets with our variable.

Trim – removes whitespaces or given strings.

{{ ' I like Twig. '|trim }}
{# outputs 'I like Twig.' #}

{{ ' I like Twig.'|trim('.') }}
{# outputs ' I like Twig' #}

Date – date formatting

{{ "now"|date("m/d/Y") }}
{{ post.published_at|date("m/d/Y", "Europe/Paris") }}

Functions:

random() function

{{ random(['apple', 'orange', 'citrus']) }} {# example output: orange #}
{{ random('ABC') }}             {# example output: C #}
{{ random() }}               {# example output: 15386094 (works as the native PHP mt_rand function) #}
{{ random(5) }}               {# example output: 3 #}

Drupal also has a very useful AddClass method, allowing for adding CSS classes to an html element.

{%
 set classes = [
  'red',
  'green',
 ]
%}
<div{{ attributes.addClass(classes) }}></div>

These are only a few examples and use cases, for more you can read TWIG documentation available at http://twig.sensiolabs.org/documentation.
Additionally, for working with DRUPAL 8 and TWIG it is recommended to also read:
https://www.drupal.org/node/1903374 – Debugging compiled Twig templates
https://www.drupal.org/docs/8/theming/twig/working-with-twig-templates – Working With Twig Templates
https://www.drupal.org/docs/8/theming/twig/twig-template-naming-conventions – Twig Template naming conventions

Sending data to TWIG

As you can see, TWIG offers great capabilities. However, in order for our variables to be seen in our TWIG, we have to get them there.
In our example, we have to save the content of the parsed TWIG to the variable and send it to the JS array. We can do this like that:
First, we collect the variables to be used in our TWIG:
 

$variables = array(
   'title' => 'title',
   'message' => $config->get($language."_popup_info"),
   'more' => 'more',
   'hide' => 'hide',
  );

Parsing the template:

  $twig = \Drupal::service('twig');
  $template = $twig->loadTemplate(drupal_get_path('module', 'cookiec') . '/templates/cookiec_agreed.html.twig');
  $html_agreed = $template->render($variables);

However, you will rarely use this method while working with Drupal 8. Most often you will use other methods, like overwriting the standard templates using Twig Template naming conventions.
Blocks:
1. block--module--delta.html.twig
2. block--module.html.twig
3. block.html.twig
Nodes:
1. node--nodeid--viewmode.html.twig
2. node--nodeid.html.twig
3. node--type--viewmode.html.twig
4. node--type.html.twig
5. node--viewmode.html.twig
6. node.html.twig
etc.
Then put the custom templates to our theme/templates folder.
There is also a more advanced method to do the same thing – adding files directly to the modules using hook_theme,

/**
 * Implements hook_theme().
 */
function cookiec_theme() {
 return array(
  'cookiec_agreed' => array(
   'template' => 'cookiec_agreed',
   'variables' => array(
    'title' => NULL,
    'body' => NULL,
    'read_more' => NULL,
   ),
  ),
  'cookiec_info' => array(
   'template' => 'cookiec_info',
   'variables' => array(
    'title' => NULL,
    'body' => NULL,
    'read_more' => NULL,
   ),
  ),
 );
}

In order to use such a TWIG, our block or site needs to return an array with the #theme key and the variables defined in hook_theme().
Below you can see the example of a block using a custom TWIG

namespace Drupal\hello_world\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Provides a 'Hello' Block
 *
 * @Block(
 *  id = "hello_block",
 *  admin_label = @Translation("Hello block"),
 * )
 */
class HelloBlock extends BlockBase {
 /**
  * {@inheritdoc}
  */
 public function build() {

 $variables = array(
   'title' => 'title',
   'body' => 'body',
   'read_more' => 'more',
  );

  return array(
   '#theme' => 'cookiec_info',
   '#variables' => $variables,
  );
 }
}

All functionalities were ported and are now fully compatible with Drupal 8.x. The module works perfectly and is used by us in several projects.
You can download the project from GitHub:
https://github.com/droptica/cookiec/
Leave a comment below if you have any questions or issues.
Summing up our short article: The changes between D7 and D8 are significant, and this is only a small part of the vast scope of innovations and new capabilities offered by our new CMS. If you want to further expand your knowledge about D8 and other tools useful for designing web applications, give us a like on  Facebook, where we share our tutorials, guides, and various interesting stuff from the industry. You can also take part in Drupal Day and the Drupal Camp! New content is also coming soon to our blog!
 

Large D8 logo

Dec 01 2016
Dec 01

Drupal is a bit famous for the amount of database queries done against a database. When there are thousands of concurrent users to be served, the database can quickly turn into a major bottleneck. This was the case with http://kwestiasmaku.com - a very popular website with recipes. The website is visited by millions of enthusiasts of cooking.

When we started our cooperation with KwestiaSmaku, we initially focused on adding new features and functionalities to the website. Eventually though growing popularity forced us to look at the application from a performance point of view.

Analysis

To tackle the performance bottlenecks we first wanted to understand what causes the greatest load. Usually there are two possibilities:

  1. Websites code is inefficient (it can contain obvious errors which cause additional unneeded database queries, sometimes repeated in loops and iterations).
  2. There may be no direct errors. You can tick all the boxes of building the website the Drupal way following all the best practices but with certain user volume still hit a bottleneck (usually database related).

We did not build KwestiaSmaku but took over its maintenance, so firstly we wanted to make sure that custom modules did not contain any surprises that would fit in option number one above. We used x-debug profiler and blackfire for this. These tools are very similar in many aspects but also each gives some unique options. Both allow you to observe how the page is generated and how much time is spent at each function in the call stack.

One thing we found with the tools was browsercap module, which was installed but not used for anything. It did, however, query the database substantially and for each page request. Apart from this, we found some sub-optimal things we could fix but nothing so major enough to get us out of the database bottleneck. We had to move to phase 2 - performance optimization.

One of the best tools helping you understand what happens with your server in New Relic. Data gathered by it confirmed what we suspected from the beginning- the heaviest and most time-consuming queries were the ones generated by the views module. KwestiaSmaku used fairly complex views to display lists of recipes on the front page and in categories. Views module is great but it is a two-edged sword - you can quickly create complex lists of entries but you get big and heavy database queries with multiple JOINS and nested sub-queries. 

Search API Solr

Apart from setting a time-based cache or creating a slave database and using it to feed the view, there was not much we could do to optimize database queries built by views. To work around this we proposed moving the whole view to from a database query to an index based on Apache Solr. We already used Solr to power the website's search window so the only thing we needed to do was to create another index that would hold data we needed to display on the lists of recipes.

With Solr we removed the heavy database queries, substantially decreasing the load on the database. This is clearly visible on New Relic graphs from that period. We released the change on the night from 7th to 8th November and the following day the database was already under much less stress. 

Drupal database performance optimization
Next, on 8th November we disabled the browsercap module which was still executing an inefficient query (the blue color on the graph)

Drupal database performance optimization

Thanks to the change from database to Apache Solr index we completely eliminated the most inefficient and time-consuming database queries. The longest queries are now 5 times shorter than before the change (the sharp ticks on the graphs are nightly backups)

Drupal database performance optimization

Thanks to our optimizations, kwestiasmaku.com can grow further without the need for the server change or implementation of complex server infrastructure. 

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