Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Sep 29 2016
Sep 29

My fingers are trembling typing this. I can't believe it. This morning everyone in Annertech land is thinking "did that really just happen?" It appears it did, we are the web agency of the year!

Last night, to top off the other three awards we won - best arts and culture website, most beautiful website in Ireland, and best website (all for Ireland.ie) - we then went on to win Best Web Agency 2016.

Speaking to accept the award, Alan Burke thanked the great team we have in Annertech and our fantastic clients who trust us with such important work.

Afterwards, Stella Power had the following to say, "it's just amazing. I always knew we had a great team. We work so well together, we get on so well, we're not co-workers or colleagues, we're friends. And when working with your friends it's much easier to do great work. This award vindicates everything we've been doing to make Annertech the agency it is".

Please join me in congratulating Annertech on this fantastic news. Annertech: Web Agency of the Year 2016.

Sep 29 2016
Sep 29

We knew Ireland.ie (built by Annertech on Drupal) was a special website. The design is beautiful thanks to the amazing work of BigO Media, the content, media, and experience is second to none thanks to the the team in the Ireland.ie office at the Department of Arts, Heritage and the Gaeltacht. The implementation is without flaw (if we say so ourselves!).

Last night at the Realex Web Awards 2016 ireland.ie was nominated in two categories: "Best Arts and Culture" website and "Most Beautiful Website in Ireland". It won both. Were we happy? We were ecstatic but that was increased moments later when we won the Grand Prix, the overall winner for "Best Website in Ireland" 2016. Congratulations ireland.ie - winner of three awards!

As well as the above awards we (Annertech) won one more - WEB AGENCY OF THE YEAR 2016. That was just amazing!

Sep 27 2016
Sep 27

At DrupalCon Dublin 2016, Nikhil Sukul and Vidit Anjaria will discuss animation with Drupal.

Basics of animation

History

The first hints of 'animation' come from a pottery bowl in Iran, around 5000 years ago. Skip ahead to the 1500s, Leonardo Da Vinci had a few drawings depicting animations. And today, you might think of Walt Disney as the modern animation master.

Definition

To make sure we're on the same page: Animation is "the technique of photographing successive drawings or positions of puppets or models to create an illusion of movement." Our eyes cannot view individual objects moving faster than 60 frames per second, so web animation is a series of computer graphics shown in succession at a rate faster than 60 frames per second.

Principles

There are 12 basic principles in animations: Squash and Stretch, Anticipation, Staging, Straight Ahead Action and Pose-to-Pose, Follow Through and Overlapping Action, Slow In and Slow Out, Arc, Secondary Action, Timing, Exaggeration, Solid Drawing, and Appeal. Here's a bit more on four of them.

  1. Anticipation: The action predicted from the before action is known as Anticipation. For example, hitting a pile of wood with an axe requires an action of taking the axe back of our head and then hitting on the wood with tremendous force. Taking the axe back of our head is considered as Anticipation. Another example can be, body movements of a pitcher in a baseball game, just before the pitcher actually throws the ball. Based on the pitcher's body movements it is anticipated that the ball will be thrown.

  2. Secondary Action: The reaction of the action is known as secondary action. For example, when a ball touches the ground and kicks up the dust. In this case, ball touching the ground is a Primary action and dust is getting kicked up is Secondary action. Another example could be, spilling out of water while a person is diving in the swimming pool, is a Secondary action.

  3. Staging: When we need to show or highlight only one animated objects from the group of all, we use the staging method. For example, if we are creating a modal popup window which is stagedto show in the middle of the browser screen and disabling all other controls in the background.

  4. Slow-in Slow-out: In animation every object start slow and then reached its appropriate speed and then should slow down to finish the animation. Or it can be that it start fast but slow down at the end to finish. In CSS this is known as easing.

Using Flash

Animation on the web started in 1987 with the invention of the animated GIF, or Graphic Interface Format. GIFs were used mostly for advertisements on websites, but had some problems with the pixelation. Then, in the 1990s Adobe introduced Flash, a tool for animating with audio. This created a revolution and was the best way to do animation on websites for a very long time. But Flash has some issues.

  1. Closed source: Users must purchase Flash from Adobe and cannot make modifications to the software.

  2. Security: Flash allows writing and running complex scripts on websites and scripts can be written that directly access the memory of a computer.

  3. Performance: Flash websites can take a long time to load.

  4. Resource hog: Flash uses a high amount of computing resources and can actually hang or crash your system if multiple applications or flash sites are opened at the same time.

  5. Plugin dependency: You need to have flash plugin installed in your browser. And every month or more, you need to update it.

Using CSS and JavaScript

To achieve animation on a website, we can use open source technologies like CSS and JavaScript.

With CSS, we use animation, transition, and transform properties as parameters. When using animation property, the keyframe property must be used to divide the animation into small pieces. Then we apply necessary transition or transform properties to each piece.

With JavaScript and jQuery, we use the animate() function and apply transformation and transition properties. Other functions are available in jQuery, which we can use directly: they are fadein(), fadeout(), slidedown(), slideup(), as well as the show() and hide() function for adding little delay, which will help to achieve animation.

A key to web animation is to hit the property which has less impact on the browser render capability.

Performance of the website depends completely on the technology we choose for implementation. While implementing robust logic, CSS animations will always be lighter than JavaScript animations. Most of the browsers use position, scale, rotation and opacity very lightly. If we are maintaining 60 fps (frames per second), it will not impact the performance as much. The higher we start on the timeline waterfall, the more work the browser has to do to get pixels onto the screen.

From a business perspective, we can use animation almost anywhere, but mostly it is used to promote the features of a product, like online tutorials and courses, online games, e-commerce websites, interactive portfolios, and much more.

Sep 26 2016
Sep 26

We're all very helpful people in the Drupal community and so help should easily be available. But sometimes you get caught out and can't find people nearby - you get lost, you lose your phone, you're in an area of town and haven't a clue how to get back to your home, you are locked out of your AirBnB, you've gone to kiss the Blarney Stone not realising it was 350km away!

If you need help with anything while in Dublin, please get in contact with us. We have lots of local knowledge (and a team of 15 people here for DrupalCon) willing to help you. You can contact us via:

email: [email protected]
email: [email protected]
phone: +353 (0)1 524 0312
twitter: @annertech
 

We'll be keeping a good monitor on all of the above and will do whatever we can to help anyone that needs it.

Sep 23 2016
Sep 23

At the end of August I was in San José, Costa Rica where I presented both of the migrate talks my colleague Novella and I have worked on over the past year (unfortunately she could not make it as she moved to Detroit that week). It was fun to present talks I've worked with for so long... familiar. Low-stress. All the notes are now safely stored in markdown format on GitHub. Bliss. Since they are both in an accessible format I have posted them here for others to access. Of coruse, particularly with the project management talk, the real fun in the presentation is the examples we cite as we talk through each issue, so you'll have to live without that.

Here they are:

Migration Shotgun Tour

(Montréal 2016, Costa Rica 2016) - in markdown and as HTML/JS slides.

Project Planning a Migration Project

(Montréal 2016, Costa Rica 2016, Ottawa 2015) - in markdown and as HTML/JS slides. ...unfortunately there are no recordings of these talks. I tried to capture audio of one of them and did not realize the disk was full. :-/ Prior to these two talks I have done many different variations of these presentations at other camps and summits going back as far as 2013 when I presented commerce_migrate_ubercart to the Toronto Drupal community. It was my first-ever Drupal talk. Since then I became a maintainer of that module and done many talks and countless migrations since! I'm hoping to get back into Commerce migrations when 2.x hits beta, which I hear will be coming soon. My next upcoming migrate talk will be a full-day training at BadCamp 2016 in Berkeley, California. It is already sold out (sorry!).

See you at DrupalCon Dublin?

Before BadCamp 2016 I will be in Dublin for DrupalCon... sorta! Specifically I will be at the Business Summit on Monday and the Friday Sprints, but NOT at the conference itself (ie, Tuesday/Wednesday/Thursday). Obviously I don't have a talk at the conference this time around... but I will still be in Dublin for that time so I may still see some of you at the parties. If you want to get lunch outside the conference venue or join me for some sight seeing let me know! I'm on twitter (and yes DMs will ding my phone, even when I travel, so long as I'm paying attention to it). If it is work related, you can also reach out to me through the contact form at kafei.ca.

Sep 22 2016
Sep 22

DrupalCon Dublin is just around the corner (since I live in Ireland, I mean that literally!). DRUPALCON: HEAR ME ROAR! (or at least speak, along with some other Annertechies). At DrupalCon we'll be speaking on a number of topics (interesting aside: we're the only Irish agency with any speakers at this year's DrupalCon). Here's a quick roundup of our talks and why you won't want to miss them:

Speaker(s): Alan Burke and Aisling Furlong

Where: Liffey Meeting 2 | 10:45

Why come to this: You will learn what large organisations look for when selecting a CMS, how you can pitch Drupal as the CMS of choice, what competition Drupal has and how it fares against it. You do want insights from one of Ireland's largest multinationals don't you?

Speaker(s): Mark Conroy

Where: Wicklow Hall 2B | 14:15

Why come to this: Come get an overview of how to use Drupal as a decoupled system, how to use Ionic Framework (and AngularJS) to take the decoupled data to make a hybrid webapp that can run on iOS, Android, or the native web. Sorry Windows phone.

Speaker(s): Alan Burke

Where: Liffey Meeting 3 | 12:00

Why come to this: Learn from our insights gained building ireland.ie, where we built a co-lingual rather than multi-lingual website. In a co-lingual website all languages present are given equal importance. We made sure this was true on the frontend and the backend.

Speaker(s): Andrew Macpherson

Where: Liffey Meeting 4 | 10:45

Why come to this: Andrew, Drupal core maintainer for accessibility, is one of Drupal's most recent core maintainers. In this core conversation he will discuss the present state of accessibility of Drupal, where it might be improved, and how we can do so. Andrew is the only core maintainer working for an Irish agency.

Speaker(s): Anthony Lindsay

Where: Wicklow Meeting 1 | 10:45

Why come to this: Anthony, Annertech's lead support engineer, works from home (like the rest of us here at Annertech). Come listen to Anthony tell in his own inimitable style why remote working makes him happy.

That's our official speaking slots. Don't miss them, and don't forget to say hello to us at Booth 901.

Sep 22 2016
Sep 22

In Gizra, we run an unusual stack. Drupal, our bread and butter, serves as the backend and is complimented by Elm for the front end, and as of recently Yesod - a Haskell framework.
Before Yesod, we were running NodeJs as our proxy server for light tasks or real-time messages.

But ever since I came across Elm, Javascript and I are hardly friends. I respect it, but can no longer turn my eye from its shortcomings. Functional programming has caught my heart and mind.

In this post I’m not going to try and present strong points on why you should adapt this stack, but rather share with you the unique path we are paving.

Elm

Elm was my first dip into the functional programming (FP) world. I recommend starting from there. It’s way more gentle than Haskell, and it has, of course, one important advantage - it helps you build rock solid, crazily fast, joy-filling, web apps.

Maybe this [post and video]({{ site.url }}/content/faithful-elm-amazing-router/) will get you excited as well.

Gentle Intro to Haskell

A good way to start explaining what’s so special about Haskell is to dive directly into Haskell. While PHP is defined (by some) as a “productive” language, Haskell is often blamed (by some) as being an “academic language”. Both statements are probably wrong.

Often when mentioning Haskell, we talk about the compiler and the type system. They are truly marvelous tools. For the type system, I think the Elm post I lined above should be enough to get the hang of it. But I’d like to continue and reveal a bit more by highlighting mini examples on how Haskell makes us approach development tasks differently.

Lists

Below are examples from the REPL (the interactive shell for Haskell)

> [1, 2] ++ [3, 4]

[1, 2, 3, 4]

What we have here are two lists of integers that are appended to each other. A list of integers is represented as [Int] in Haskell. The ++ is the operation that causes those two lists to be grouped into a single one.

Haskell comes with some handy shortcuts.

> [1..5] ++ [6, 7]

[1, 2, 3, 4, 5, 6, 7]

And even ones that can save a few lines of foreach:

> [x * 2 | x <- [1..3]]

[2, 4, 6]

The above is asking Haskell to generate a list of Int from 1 to 3, and feed it into x * 2. We can also do fancier stuff here, like take a list from 1 to 10, but use only the even numbers:

> [x | x <- [1..10], rem x 2 == 0]

[2 ,4 ,6, 8, 10]

A String in Haskell is actually a list of Char ([Char] in Haskell talk). So this may seem a little surprising, but we can actually act on the list of chars in the same way we did with numbers.

> ['a'..'e']

"abcde"


> ['a'..'e'] ++ ['f'..'h']

"abcdefgh"

> "Hello " ++ ['w', 'o', 'r', 'l', 'd']

"Hello world"

Abstractions

So far, nothing here is overly complicated or life changing. When I gave this talk in Gizra, even the non-devs weren’t alarmed at this point. No glazing eyes (yet).

Now we can start looking at how Haskell brings a different approach to programming. One that, as Drupal developers, we are not too familiar with.

The fine folks of Haskell looked at the appending of the lists, and probably told themselves “Hey, there’s a pattern here, and it can be satisfied by a set of rules”. The pattern they recognized is the fact that we need to append variables of the same type. That is, two lists of integers can be added together and form a longer list of integers. The type doesn’t change, just the number of members inside of it.

The ++ operation we saw can be generalized and called mappend. All the following will have the same result:

> [1, 2] ++ [3, 4]
> mappend [1, 2] [3, 4]

-- The backtick sign (`) means we can use the mappend between both arguments.
> [1, 2] `mappend` [3, 4]

[1, 2, 3, 4]

So, trick question: with the above abstraction in mind, what would you expect the result of appending two integers be?

> 5 `mappend` 6`

Should it be 11 (5 + 6)? In that case why wouldn’t it be 30 (5 * 6)?
Or maybe even 56 (smashing the two digits together)?

It’s unclear. However, Haskell has a solution. We can use types to explain to the computer what our intention is. So we have two types Sum and Product:

> Sum 5 `mappend` Sum 6

11

> Product 5 `mappend` Product 6

30

Monoid

Hope you are not too afraid of the above title. Monoid is the name of the abstraction we just briefly went over. It should not be confused with the dreadful Monad term, which I have no intention to cover.

In PHP talk, a Monoid class is like an interface that has two methods: mappend and mempty.

The mempty defines an “empty” value. What is the empty value in the case of the above Sum?

Sum 5 `mappend` mempty = Sum 5

mempty would be Sum 0 (because 5 + 0 = 5).

And what would it be in the Product case?

Product 5 `mappend` mempty = Product 5

mempty would be Product 1 (because 5 * 1 = 5).

For completeness - the second and the last rule for a Monoid is that mappend x y should be equal to mappend y x (5 + 6 == 6 + 5).

That is it. You are on the path to Monoid zen. Now, let’s put our knowledge to use, and try to implement an example.

12 Hour Clock

Here’s a nice Monoid example I came across. Let’s say we have an old clock with 12 hours. No AM or PM. Something like this

In case you missed out life in the past century, this is a clock

So let’s say that time now is 10. What time will it be in 4 hours from now?

We cannot say 14, because inside the clock there are only 12 hours. We already know will happen - it’s simply going to pass the 12 hours and “reset”. That is, the answer is 2.

Inside this clock we can continue adding numbers, but our logic will never fail. Any number we add will never fall outside of the clock, thus causing the universe to collapse into itself.

Monoid can help us accomplish this behavior because we are able to define our own completely arbitrary new type, and have a standardized way to explain to the computer how numbers are to be appended.

data Clock12Hours = Clock12Hours Int
    deriving (Show)

instance Monoid Clock12Hours where
    mappend (Clock12Hours x) (Clock12Hours y) = Clock12Hours $ (x + y) `mod` 12
    mempty = Clock12Hours 12

Don’t bother too much with the above code’s syntax. What’s important here is to understand that after defining this Haskell instance - or in PHP talk say that Clock12Hours is implementing the Monoid interface - we can use the same mappend we used above with integers and chars.

> Clock12Hours 4 `mappend` Clock12Hours 10

Clock12Hours 2

So What?

How would we do this in PHP? That is, if we had something like:



$hour1 = new Clock12Hour(4);
$hour2 = new Clock12Hour(10);

How can we add 10 + 4 in this PHP example? The idea of appending items, as seen in this example, was not generalized in PHP, so we are bound to think about this task differently.

My point here is that the language we’re using for development is dictating the way we are able to articulate the problem, and the way we model the solution. I don’t think, necessarily, one is better than the other (well actually I do, but I’m not here for the flame wars), but rather looking to emphasize that Haskell is different enough from most other languages. Just by learning it - similar to learning Elm - can have a positive impact on our developers’ skills.

Yesod

Ok, back to web-development. That Haskell thingy we just saw? Yesod is built on top of it.

Haskell has a big learning curve. Admittedly, it took me more months than I’d be happy to share, to understand some of the basic concepts. And I still don’t understand many.

However, even though it’s based on Haskell, in the day to day tasks, you don’t really need to deal with all those abstractions. Your route will respond to some arguments, get data from the DB, massage the data, and send it to the templating system to be rendered.

It’s hard to explain without providing lots of points why a framework is great. So I won’t try, and instead I’ll give an anecdotal example that I love, because it illustrates to what degree of guarantees - that is, shifting run time errors to compilers errors - Yesod has reached.

In our Yesod website if we want to add Bootstrap CSS file, we write addStylesheet $ StaticR css_bootstrap_css.

We don’t have a static folder in Drupal, but it can be roughly translated into drupal_add_css('static/css/bootstrap.css'); which isn’t something to brag about. We’re just loading the CSS.

Well, not really. You see, in Yesod, if you will notice, we don’t write StaticR css/bootstrap.css but rather use css_bootstrap_css. That string, as the docs explain, is a reference to the actual file.

This means that if the CSS file doesn’t exist, the compiling will fail! You will get a big fat error message telling you to go and add the missing file because you probably don’t want to deploy your website without its CSS.

Pushing code to production without all the necessary assets isn’t something I’ve done many time, but it has happen in the past. I wouldn’t mind if it was guaranteed not to ever happen again, without me needing to put any cognitive effort into it.

Unfair Comparisons

Coming from a full blown CMS, frameworks tend to look appealing at times. They are so light, and so much faster.

Then, I find myself hand coding flag like functionality, which in Drupal is just a case of downloading a well tested module, enabling, and configuring.

In Yesod, I had to write it myself. There are some Yesod packages out there, but nowhere as near as what Drupal offers.

On the other hand, a lot of Drupal’s modules are of low quality or very specific, so quantity doesn’t necessarily mean much. We usually just need a tiny subset of it.

And that flag functionality I wrote - well, my local server spit the JSON response back within 6ms.

Flagging a user

6ms! The same JSON response took about 200ms on my local coming from Drupal.

“But that is not fair!", you may say, “the comparison isn’t right. Drupal does so much more out of the box!”

You are, of course, right. But on the other hand - 6ms. When I clicked the flag link, I didn’t need the other stuff Drupal brought (and bootstraps on each request). I just needed my item to be flagged. And it was. In 6ms.

Our users don’t care about the underlying technology. They just want it fast. But then again, it’s very hard to compete with Drupal’s community, maturity, eco-system, hosting providers, etc.

It’s up to us to select the right tool for the job, and that’s why I love web development and my job so much.

How to start

If I got you interested, here are some good resources:

Sep 20 2016
Sep 20

This day next week, as part of the Drupal Ireland Association, we will be delighted to welcome you to Dublin at the DrupalCon Welcome Party. It's on a boat, which is going to be deadly ("deadly" in this context means great, "lethal" would mean dodgy/dangerous!). The boat is just across the road from the convention centre, so that will be savage ("savage" of course means lots of fun). However, the ceiling inside the boat is only about 2 metres high, that's going to be a bit cat (let's just say "cat" doesn't mean brilliant).

So what is this hoolie (usually a loud party with lots of traditional instruments and improptu performances, but not in this case) all about? It's about the Drupal Ireland Association giving a céad míle fáilte (one hundred thousand welcomes) to the world when they arrive in Baile Átha Cliath (Dublin). It's about us showing gach duine (everyone) that we are a welcoming community of Drupalists in Ireland. That we are open to new people coming on board and helping out with what we do - we'd love to hear from Irish people using Drupal whom are not members of Drupal Ireland yet and also people from other tech scenes here.

The party is on the MV Cill Airne boat (Cill Airne is the Irish for Killarney - you won't be disappointed if you go there - and means the "church of the sloes"). It's starts at tea time (18:00) and goes on until serving time finishes (23:30 on a Tuesday). Come join mise (pronounced misha, means "me"), all the rest of the Annertech team, many others from the Drupal Ireland Association, and hundreds (sorry we can't fit thousands onto the boat) of other Drupalists at the DrupalCon Welcome Party to have a savage, deadly night of craic (fun).

Sep 19 2016
Sep 19

Ron Huber: It does go back to what Dries said earlier this year, about who adopts Drupal, right. I mean, they're truly ambitious web projects. We don't do a lot of medium or small size businesses -so I'm probably not the one to comment on this- but I'm not sure that even my company should be using Drupal, if it weren't that we were a Drupal company. Right? It is an investment that you really want to take if you're going to take on a big, ambitious project and do something spectacular on the web.

Jordan Ryan: It is. I think that something that we're going to see, at least at the crossroads of Drupal, is that there is going to be an opportunity to bring this very rich content architecture and interconnect it with more content services and more displays of that content across all of these different interfaces. That's, I think, the opportunity that Drupal has, as long as it keeps staying there. I mean, small businesses are going to say, "Ah, you know, if I do a WordPress site, is it going to hook up to my app? Is it going to hook up to point-of-sale system? Do I have to have all this stuff in all these separate locations? Or can I just ...?" You know, as a small business owner, can I just have that little turnkey app that connects with everything? I think that Drupal, especially with RESTful services and GraphQL is going to keep moving in that direction.

Ron Huber: True.

Chris Stauffer: Unless you're like a pure play company, though, that's specifically making a content play. I think Drupal might honestly be even a little bit overkill for some small businesses. Don't get me wrong. I've drunk the Drupal Kool-Aid, and I'm drunk on it. If you're a site that's a small business, I've actually had more success with WordPress. Like a $10K site or a $15K site, that's way more WordPressy. For me, I've kind of stopped selling Drupal to small businesses, because I can't figure out how to give them the ROI that they need. Whereas, a small business can get a good ROI on WordPress. I can't seem to get a $20K project done well in Drupal; whereas, 20K in WordPress, you'll get a $#@!-load of stuff. Whereas $20K in Drupal, you're not going to get as much cool stuff. You know what I mean? When you start moving ... You said earlier that you can plug into a lot of different things. I think that is where Drupal starts to become a lot better, when you start getting to that enterprise market that needs 80 different things hooked into it. Those larger enterprise organizations ... Yeah, Drupal is the greatest thing ever when it comes to that. I've got to be honest. I used to sell small businesses Drupal. I stopped, because I can't figure out how to make those projects profitable.

Jordan Ryan: And when we push marketing, we don't really push Drupal either. It's when there's an opportunity for some kind of stronger digital strategy that needs to have… either we say, "Okay, within a year you're doing XY&Z, and you're going to need to be there." If you're carrying around your website ... It's just a business card you pull out of your pocket and say, "Hey, check me out."

Chris Stauffer: That's WordPress.

Ron Huber: If you're looking for a platform, and you've got a lot of third-party integration. You have a lot of hooks, etc. We were talking earlier about other technologies, and I think this is where part of this conversation started. We're, as a company, branching off. Drupal is something that we do really well. We've been doing it for 10 years. We're going to continue doing it, but we're adding other technologies. We are looking, because we're now more of a market player. We do more in the healthcare business than we do in the Drupal business.

Jordan Ryan: Sell solutions.

Ron Huber: Solutions, right. We've added the JAVAs and the JSONs, and all these things that we have to add for our clients that are looking for more from a software developer than a Drupal developer. Right? I hear a lot of shops doing that.

Tom Friedhof: We've found ourselves getting off the island, as they say. We were primarily a Drupal shop when we started ActiveLAMP. Now, we're doing Symfony, Laravel, and Node. This is where I think it's super valuable with the direction that Drupal 8 is going, is the fact that now I can put my Symfony developers on Drupal projects, because they don't have to learn this ... I mean, Drupal 7 is great, but they don't have to learn this Drupal 7 thing.

Chris Stauffer: Do you have a lot of Symfony guys that hadn’t touched Drupal?

Tom Friedhof: That's correct, yeah. We have Symfony developers on staff that now we're comfortable putting on Drupal projects.

Jordan Ryan: Because Laravel?

Tom Friedhof: They come from Symfony and Laravel, that's correct. It's all the design patterns.

Ron Huber: That's good for us all, right? Now we're expanding, and we're offering other services, and it's going to help our clients, and we're going to use Drupal where Drupal should be used. That's the key.

Jordan Ryan: I think there's a strategy too ... For the Drupal community at least ... I heard in the keynote earlier today, presenting Drupal as this solution for content architecture, right. There are all these other rich applications that can key into it. Also with the enriched developer experience, you have many more opportunities to bring people in who are working in other frameworks, right. There's a general maturity of open source ecosystem now. I think Dries posted an article a few weeks ago from TechCrunch. It was talking about how all of these open source communities are starting to mature as professional services are developing around them. You see all these ... You know, MongoDB, Drupal, and there's this arc of adoption for the enterprises that kind of slowly have moved into this space. There's going to be a new wave of even more open-source softwares, based off of Symfony, Mautic, the open source marketing automation tool we use is based off of Symfony. It just reached version 2.0. I think it's just going to gain on the market share for marketing automation.

Ron Huber: I still see Drupal as being the Switzerland of it all, right. It sort of fits in the middle there and plays nice with everything. That's what makes it so powerful, right? You can write another application somewhere, and integrate it into Drupal very easily.

Jordan Ryan: Where else does it make sense to really invest a lot of processing power into a central location or to handle all your business operations?

Ron Huber: They want to own it all, right?

Jordan Ryan: Right.

Ron Huber: Every other piece wants to own it. They want to have all the access. They want to have all the control over the users. That's the one thing that allows Drupal to keep on expanding, is that we own some of it, we can do some of it. Maybe it's just Drupal sitting next to a Salesforce application, because we're just going to use it for content. We can make it look like Salesforce, we can integrate it no problem, and everybody on the internal project has no idea. They think they're in their application, because Drupal plays nice. That’s a powerful tool.

Sep 17 2016
Sep 17

DrupalCon Dublin is just around the corner. Earlier today I started my journey to Dublin. This week I’ll be in Mumbai for some work meetings before heading to Dublin.

On Tuesday 27 September at 1pm I will be presenting my session Let the Machines do the Work. This lighthearted presentation provides some practical examples of how teams can start to introduce automation into their Drupal workflows. All of the code used in the examples will be available after my session. You’ll need to attend my talk to get the link.

As part of my preparation for Dublin I’ve been road testing my session. Over the last few weeks I delivered early versions of the talk to the Drupal Sydney and Drupal Melbourne meetups. Last weekend I presented the talk at Global Training Days Chennai, DrupalCamp Ghent and DrupalCamp St Louis. It was exhausting presenting three times in less than 8 hours, but it was definitely worth the effort. The 3 sessions were presented using hangouts, so they were recorded. I gained valuable feedback from attendees and became aware of some bits of my talk needed some attention.

Just as I encourage teams to iterate on their automation, I’ve been iterating on my presentation. Over the next week or so I will be recutting my demos and polishing the presentation. If you have a spare 40 minutes I would really appreciate it if you watch one of the session recording below and leave a comment here with any feedback.

Global Training Days Chennai

DrupalCamp Ghent

Note: I recorded the audience not my slides.

DrupalCamp St Louis

Note: There was an issue with the mic in St Louis, so there is no audio from their side.

Sep 15 2016
Sep 15

Choosing proper hosting for your site shouldn't be a race to the bottom.

Hosting websites is hard. Websites themselves are complex, global traffic can mean huge numbers, big spikes in activity and always demanding users. Sites need to be served quickly, consistently and reliably. Downtime costs money, effort, and more than likely a few extra grey hairs too.

Choosing hosting for your website can be a daunting prospect. You've invested time, effort and money into developing your creation, of which you are justifiably proud. Now you need to find it somewhere to live. But where?

Hosts come in all shapes and sizes, from cheap shared hosting environments for about a euro a week, up to specialised infrastructure platforms catering to massive distributed applications.

Here at Annertech, we offer expert, Drupal-optimised, managed hosting.

  • Expert because we know Drupal inside out. Expert because the server administrators are at the top of their game, using best-in-class tools and technology to provide rock-solid and reliable infrastructure for your sites. Expert because our hosting utilises the power of version control and provides development environments identical to your live setup, to maximise confidence in any changes. Expert because we are the only agency in Ireland with a member on the Drupal security team.
  • Drupal-optimised because our hosting comes tuned to get the best out of Drupal, and is bundled with all the performance enhancing extras you can imagine such as caching layers and reverse-proxy engines.
  • Managed because you don't need to worry about server software updates, application layer updates, server configuration, or any of that jazz. Managed because, importantly, we take care of all your Drupal core and contributed module security updates for you.

Security updates alone make this arrangement make sense.

For example, take a site with, say, 100 contributed modules. You could reasonably expect to have to deal with around 20 security updates during a year. Monitoring for security releases, applying updates locally, deploying to a test environment (you have one of those, right?), testing, and then replicating those changes to the live environment all takes time. Then there's all the server level software updates and patches. That could turn out to be a lot of headache.

Maybe you have a support contract with some lovely developers (hi!) who do your security updates. That's a great way to handle it, but wouldn't it be even better if your developers spent their time improving the features of your site?

Simply by hosting your site with Annertech, security updates become a non-issue. Saving you stress, time and money.

Give your lovely new website a nice, secure place to live. Talk to us - you'll be glad you did.

If you'd like to discuss hosting face-to-face, we'll be at Booth 901 at DrupalCon in Dublin.

Sep 15 2016
Sep 15

Creating a plain text email with Drupal is a simple task. However, when you want to send a nicely designed message with a logo, an article, a linked button or any other unique design with dynamic content personalized for each user, it can get complicated.

The complication stems not from the dynamic content, but rather from the fact that the CSS that can be applied inside email templates is limited. In general, targeting multiple email clients can be worse then getting your CSS to work on IE9!

This post will walk you through a solution we use to address these requirements, but before jumping in, let me first explain Gizra’s approach to themes. We don’t use custom CSS in Drupal themes. When we start building a website, we divide our work into several milestones, the first is creating a clean and static markup, using Jekyll. At Gizra, we take pixel perfect very seriously, and by doing the markup first, we can concentrate on building our App pages exactly the way they are suppose to look, test their responsiveness, show our clients a first draft, and fix bugs before getting into the logic. We use gulp to compile the SASS files into one CSS file, and after doing that, we copy the CSS file to the themes folder. Then we take our static pages, cut them into pieces, and use them in Drupal themes and plugins.

By doing this, we can focus on our logic without worrying about how it may look with different dynamic content. Focusing on Frontend and Backend as separate tasks makes building websites easier and faster. Even fixing bugs discovered while implementing dynamic content can now be easily fixed. Our No more CSS in your Drupal Theme! blog post talks more extensively about the way we work with Drupal themes.

The same approach is implemented when we create an email template. We first build the email markup with static content, and then we use it to create dynamic content messages. Oh, and we cheat, because we don’t write a single line of HTML or CSS!

A demo email template created for this post

Creating an email template

When we build a website we need to take into consideration that our users use different browsers and adjust our CSS rules so that our website will look pretty much the same in all of them. Achieving this is more difficult when it comes to emails.
Our users use different email services and view their emails on different browsers. Each email may look a bit different on each browser or software. Some of the email services do not support all HTML tags and CSS designs. We can’t use everything we use in our website for example: Gmail and Outlook users have poor support for float, margin and padding. Also, some email services may overwrite our design and replace it with its defaults like links color, or image visibility. Another issue is the screen widths where mobile or tablet users view emails very differently.

Our way to overcome this problem is to design our emails with nested tables since they are supported by most email services. However, this is still not enough. To make sure that our email will look the way we want, we need to set a specific width for each table cell and that’s a lot of work. After creating our email template we need to find a way to test it and make sure that it looks the way we meant on every media or mail service.

This is when we decided to take advantage of Mailchimp’s wysiwyg editor. In the editor we can build the static version of the email, that will include links, images, videos, etc.

We use the editor to create the email friendly HTML and CSS for us, and later use the export functionality to grab it and move it into Drupal.

Mailchimp wysiwyg editorMailchimp content items

Behind the scenes, Mailchimp converted my design into nested tables with the most mail supported CSS rules. There is also an option to view the source on the Mailchimp editor and do my own adjustments. I upload my images to Mailchimp’s cloud, so I won’t have to worry about my users email software blocking images attached to the email.

Mailchimp also gives us the opportunity to test our email template on desktop, mobile, and inbox software such as different versions of Outlook, Gmail, and Yahoo on different browsers. After finishing the email template, I go to my templates list and export it as an HTML file, which is combined with the inline CSS. Next we need to wire it into Drupal.

From Static to Dynamic

The idea is now to take the static HTML and slowly introduce the dynamic content.

Instead of calling drupal_mail() directly we usually use the Message and Message notify modules to send the emails. It has the advantage that each mail is saved in the system, so it’s easier to track (and find bugs, if there are any).

One way to do this, is to create a theme function that has a tpl file, were we have our HTML. Then when creating the message we can replace a dynamic token with the content of theme('my_email_template', $variables)

But in order to convert the static parts to dynamic, we need to see the result. Sending an email on every change can be time consuming and make debugging harder, so we start by seeing the email inside our site, while we develop it. To do that, we can define in hook_menu() a debug path like message-email-debug/% where the argument will be the message ID.

However we’ll need to make sure to disable our site CSS before we view our message, because it might change the way we view the emails. We can safely remove all CSS, since the email’s CSS is inlined.



/**
 * Implements hook_css_alter().
 *
 * Remove all CSS
 */
function example_css_alter(&$css) {
  $item = menu_get_item();
  if ($item['path'] != 'message-email-debug/%') {
    return;
  }
  $css = array();
}

We can also go ahead and override page.tpl.php so on message-email-debug it will print out only without any other elements.

At this point, we can start converting our static into dynamic HTML, while being sure that the final HTML it guaranteed to work in email clients.

Sep 13 2016
Sep 13

Annertech will be descending upon DrupalCon with (nearly) our full team of "Annertechies". So much so that there will be more Annertechies in attendance than all other people from Irish agencies combined. With that kind of showing, we thought we'd introduce ourselves and let you get to know us.

Stella Power

Stella is Ireland's Drupal wunderkind. Founder of the Drupal Ireland Association, member of the Drupal security team (the only person from an Irish agency with that accolade), and managing director of Annertech, Stella is the kind of person that doesn't come along often enough. Stella has spoken at many European DrupalCons; this year she was track chair for the business track and is also the local liaison for DrupalCon.

Alan Burke

Alan is also a director of Annertech. When not keeping the invoices raised and paid, he's focussing on being a top-notch frontend developer. In this vein, his main passion is for website performance. Alan has spoken at a lot of DrupalCons over the years; this year he will be speaking about developing a co-lingual website for ireland.ie and why a multinational organisation might choose Drupal.

Dermot Frost

Poor Dermot has a tough life. He won't be able to make it to DrupalCon as he'll be preparing for a conference the following week in Boston. When not jet-setting, Dermot spends a lot of time building and maintaining server infrastructures.

Anthony Lindsay

Anthony is our lead support engineer. He makes sure that all our existing clients are happy. For Annertech, support often means on-going development of new features and enhancements to existing ones. If you have an existing website and would like us to support it, come talk to Anthony at Booth 901. This year he will give a presentation at DrupalCon about how remote working makes him happy.

Mike King

Mike keeps us all in check. He's our project manager. He makes sure we know what the client wants and deliver it to them on time, on budget, and with smiles on our faces. He was track chair for DrupalCon this year on the project management track.

Mark Conroy

Mark - me! - is a lead frontend developer with Annertech. He's very interested in maintainable code, design in the browser, component-based frontend, and how those three can be brought together. You can find him (too) often in the DrupalTwig slack. He'll be presenting at DrupalCon about getting started creating mobile/hybrid apps using Drupal as a backend and Ionic Framework as a frontend. Mark is presently chairperson of the Drupal Ireland Association.

Tommy Lynge Jørgensen

Tommy is one of our lead backend developers. He knows a lot about solr, and migrations, and backing up data. He comes from Denmark, lives in Ireland, and is the reason we have cake at Booth 901. Come for the code, stay for the cake!

Andrew Macpherson

Andrew is another lead backend developer in Annertech. He is the only core maintainer working for an Irish agency, having recently been made a core maintainer for accessibility. So, if you want an accessible Drupal website built by an Irish agency, get in contact with us. He will conduct a core conversation on the future of Drupal accessibility at DrupalCon.

Gavin Hughes

Gavin is one of our support engineers. Whilst Anthony makes sure that all our clients are happy, Gavin is the one beavering away in the background actually doing the work!!! (Sorry Anthony!) When not debugging issues and developing new features, he's probably kite surfing somewhere off the west coast of Ireland.

Bren Vaughan

Bren joined us recently as a project manager. Having trained as a developer, he is slowly recovering from his past life. He's also slowly recovering from participating in Iron Man competitions and other feats of endurance unknown to the rest of Annertech. He's got so much recovery to do, he won't make it to DrupalCon this year.

Ricardo Flores Galán

Ricardo, from Spain, is our in-house designer and UX expert. He checks the fine details of designs for consistency, brand adherence, vertical rhythm, and more. Oh, and his wife gave birth to a beautiful baby boy yesterday. CONGRATULATIONS. Ricardo is presently secretary of the Drupal Ireland Association.

Rob McCreary

Rob lives in Northern Ireland. He joined Annertech almost a year ago and has been doing some fantastic frontend work for us. Previously having worked in the non-profit sector he is a great compliment to many of the types of clients Annertech has historically serviced.

Adrien Sirjacques

Adrien is one of our backend developers, and has worked on a number of projects to add new features to existing sites and also some greenfields work. Though from France, he's very active in the Irish Drupal community and can be found each month at our Drupal Ireland meetup in Dublin.

Tom Bamford

Tom is English. He lives in France where he attends to the meadow, country walks, sunshine (which apparently is rare in Normandy) and frontend development. We're lucky to have him on board given his vast knowledge of Drupal, JavaScript, SASS and other complimentary items.

Karen Leech

Karen is also English. She also lives in France, and attends to the same things as Tom. Except, instead of frontend development she is a site builder and QA Analyst. You know when you miss out on a client request by just a tiny item? Karen is our backup to notice that and makes sure nothing gets to UAT without passing her exacting standards.

So that's it. A quick roundup of the Annertechies you'll (likely) meet at DrupalCon. We'll be at Booth 901 and here's some reasons why you should come talk to us.

Sep 09 2016
Sep 09

Tom: Hey guys, we're here at DrupalCamp LA 2016, at UC Irvine. We've got a few shop owners here. We just wanted to have a conversation and kind of give you a look at what we're doing at each of our shops. I think that first, let's go around the table and introduce ourselves.

Ron: Ron Huber from Achieve Internet. We're in San Diego and Los Angeles, do a lot of healthcare and entertainment. This is my tenth year at DrupalCamp LA; been sponsoring it forever and been at a number of these camps over the years.

Chris: My name is Chris Stauffer. I'm the CEO of Stauffer. We are a Los Angeles based development firm. We focus on Drupal as well as a bunch of other open-source technologies. We work with a lot of LA's usual suspects, specifically in the entertainment industry and a lot of stuff in higher ED lately, as well.

Tom: My name's Tom Friedhof. I work with ActiveLAMP. We also are LA based; we primarily work with higher education. We work with non-profits and enterprise organizations. Tinker around mostly in Drupal but we're also doing some Symfony, Laravel, and Node as well.

Jordan: My name's Jordan Ryan. I'm the CTO of Facet Interactive based out of Manhattan Beach. We've been doing a lot of enterprise solutions architecture for Drupal Development. We've started to move into marketing intelligence using some Symfony based applications with Mautic. Small shop, looking to grow.

Tom: Sweet. I think, here we are, it's August 2016, Drupal 8 is finally out, so I kind of want to start this conversation by asking the question, "Drupal 7 or Drupal 8? Where are you guys at?"

Ron: I tell you, this is really an interesting conversation. Of course, we want to do Drupal 8. Right? It's the new thing we want to get out there, but we just had a big entertainment company - and we're working on the site now - we pitched them Drupal 8. We really tried to get them to go and they said, "No."

It wasn't ready, the modules weren't ready. When it comes out, when it launches in early December, Drupal's going to take a hit for it because it's a big name. It should be in Drupal 8 and it's going to be recognized. People are going to say, "Why wasn't that in Drupal 8?"

We did our best to pitch them and they just wouldn't go. They were all pros. These are people that have been building Drupal sites for ten years for Disney and DC Comics. These guys knew what they were doing and decided not to go that route.

Now, we have four other projects that are Drupal 8 sites in-house that they said, "Okay, whatever you guys say is what we're going to do." It's still the debate of whether we should be doing that. I think that's the problem right now, is if the community doesn't feel that it's ready, then we have a marketing issue more than we have a technology issue.

Tom: Yeah, true.

Chris: Yeah. For me personally, I actually don't think that Drupal 8 is quite ready for prime time yet. The primary reason for that is, when I'm going out and gathering requirements and things like that, I know right now every single module that's out ... Well, I shouldn't say I know every module for Drupal 7. That would be a ridiculous statement to make.

Ron: You're a smart guy, but-

Chris: I know - let's just call it the majority of the Drupal modules that matter - so when I'm architecting a system, I know for a fact that I'm not going to step on any landmines. I know what Drupal 7 can do and I know what it can't do, and it's very easy for me to scope and frame projects using Drupal 7.

With Drupal 8, most of the projects that I've gone through, I've scoped it kind of with that same mindset of Drupal 7. Then I'll have the boys go check it out and see if this is a possible candidate for Drupal 8, and it keeps failing because basically there are specific contrib modules and things like that that simply aren't ready to hang.

In my mind, once all those contrib modules have caught up and I stop running into, "Oh, yeah, sorry Chris, we're not going to be able to do that because of X," that's when we'll start actively selling Drupal 8 projects. Right now, for me, the biggest one is making sure we can do features because I want all my code checked in-

Ron: I heard you say that earlier.

Chris: You know? When I can check all my code in, then in my mind I'm ready for big boy enterprise development, but if I can't check my code in, then it's not ready for prime time.

Tom: We're kind of in the same boat as you, Ron. Same boat as you as well, Chris. We've been developing our Drupal 8 since last year; we've been pitching Drupal 8 to our clients since late last year, and you know Drupal 8 was released in November, but we're running into that issue as well, where organizations just don't want to take that leap and develop on Drupal 8.

We have managed to be able to convince some organizations to take the leap, and this is where I'm kind of the fence, or I guess divided, with building on Drupal 7 or Drupal 8. I have a technical background, I'm a developer, and developing on Drupal 8 is just a much better experience.

It's like, why would you develop on this old system? It just doesn't feel good to develop on Drupal 7. I feel that it's our jobs as development agencies to encourage and push that innovation to our clients, our prospective clients and say, "You know what? If we build this on Drupal 7, yeah, it'll take maybe four, five, six months to develop this, but six months from now, when Drupal 7 is really being put on the shelf because Drupal 8 is the new thing, how are you going to feel?"

You know, it's a little bit more of an investment up front to develop on Drupal 8? Our team, we're engineered focused, we're all engineers on our team. Well, not all of us, but the majority of us are engineers, and so if something doesn't exist, we'll code it. We won't necessarily upgrade-

Ron: You're investing in it. I totally get where you're at, because we did that from 5 to 6, and 6 to 7, and got burned a few times where-

Chris: It screwed up my budgets on my projects when I did that.

Ron: Yeah, absolutely.

Chris: I ended up losing money when I did that, because I promised a client I'm going to do X, and then it doesn't do X, but I'm on the hook for X, so now I have to go build X, and not get paid for X.

Tom: The key word Ron used there was investing. That's an investment, you know?

Ron: You have to be in the right position to be able to do that, right? It has to be the right client; some clients are, "Hey, that deadline is September 1st, and you've got to make that." Well, you can't make that decision in Drupal 8, because you don't know what landmine you're going to come into.

Jordan: I think to that point, what minefield are you running through? If you can see where the mines are and you can say to the client, - this is something that we do when we do the architecture phase - if we can see where those mines are and say, "Do you want to tackle that, defuse that?"

If they say no, well then I say, "We either have to push this back a few months until it's ready to be taken on, or we need to talk about what's your horizon for upgrading this once we do this the first time?"

Ron: Sure.

Jordan: Then they kind of get a different framework to make the decision, because you don't just present them with the opportunity of this update, you have a future web project and that's a different paradigm. You have to use in order to sell, sell on the investment.

Ron: I don't think we've done a good job as Drupal is talking about what the cool things are coming out in 8. It's just the new version, right? There are some great technology that is in future releases, and if we start talking about how you're not going to get that in 7, and how in Drupal 8 if you make the investment or you take that, maybe we shrink down this initial project, but in six months or a year from now when this is released, then you're really going to be able to take advantage of mobile, you're really going to be able to take advantage, your SEO is going to improve.

Whatever that is? That's a different pitch that I haven't used yet, and it's something that I learned today.

Tom: Yeah.

Chris: I liked Tom what you said earlier, in something. It was an angle that I hadn't actually thought of until I just heard you say it, which is actually playing on the fact that there's not going to be a transition from 7 to 8, if you go with 8 now, because I know one of the Drupal pain points that I've had in the past is, I upgraded a client from Drupal 6 to 7, and proceeded to charge the client a $150,000 to do that.

They kind of looked at me like, "Oh my god, you are crazy. You're going to charge- wait, no. But Chris, I don't get anything new?" I'm like, "You get security patches now." They're like, "Dude, you literally just took me for a hundred and fifty grand, and I don't even get anything like new."

Ron: We just won't do that anymore. I don't need even pitch that.

Chris: It's getting to a point where I didn't even think about what you had brought up, to say like, "Okay, well, maybe if you did go all the way up to Drupal 8, then really, on a total cost of ownership, you're going to dodge that hundred and fifty large transition from 7 to 8.

Jordan: Yeah, and that's a great term, "total cost of ownership."

Chris: I hadn't thought of that angle, but that's a good one.

Tom: I think there's another piece of that as well. They may be dodging the hundred fifty thousand dollar upgrade, but if you’re going to early adopt, as modules come into the ecosystem, you know you're developing custom code to fill in the gaps where the contrib system hasn't caught up to date yet.

Chris: Sure.

Tom: As those modules come into the ecosystem, there will be some of that budget that probably should be allocated to actually getting those on to the new systems. For example, panels, or panelizer, those are just now coming into the Drupal 8 ecosystem.

You're not going to completely get away from that hundred fifty thousand dollar upgrade, you may have to use some of that budget to actually get your stuff up to snuff, because you're developing so early.

Ron: If you have a Drupal 6 site, your site is outdated. You're not running your business correctly; I don't care what- there's no way it's responsive, there's no way you're adopting mobile at all. You're way behind.

I think those companies that are just worried about whether the technology's ready or not, are looking at it wrong. Their websites are unproductive, whether they like it or not. I mean, if you're a small company, maybe it's not-

Jordan: I think that comes back to a shift in how enterprises and small businesses and medium sized businesses are looking at their digital strategy. You have a platform that you develop, how are you planning to sustain it, right? If you're not planning to sustain it and keep it up to date, then you're probably just thinking in the near term of, "Hey, there's this new thing called the web. I need to get up on it."

Ron: Works for some people.

Jordan: Which is how some people still think. They're like, "Oh, I need to put out a new print catalog," because that's the old regime of advertising: updating my brochure, not this active, organic application that has more exposure than things like that.

Ron: Those companies, they're doing their thing but that's where the marketing comes in. If they're not actively marketing or they're using their old ways, what are you going to do for them? Those aren't who we're talking about anyways, right? You're investing as much money into your website-

Jordan: It's an advocacy that you have to make, is going to the client and saying, "Hey, are you thinking about that upgrade strategy?" There is a support to this, right? You get a lot of people who will come to you and say, "I want a site. I'm starting my business." These are people who haven't thought about the long-term strategies sometimes.

Sep 08 2016
Sep 08

DrupalCon is big. It's got hundreds of sessions. A similar amount of BoFs. Approximately 2,000 attendees. Social events left, right, and centre. It's not hard to get confused, miss things that you promised not to, and leave thinking "damn, I could have done that better". At Annertech, we're Ireland's most seasoned DrupalCon attendees. Here's our guide to making the most of it.

Create a Schedule

You can add any session to your own personal schedule on the DrupalCon website. You can do this right now. Do so. With so many great sessions running concurrently, it's very hard to work out on the spot what to go to next. You can find your personal schedule here.

Attend BoFs

At my first DrupalCon (in Prague) I went to the all day media sprint on Friday. I can't explain how much I learned that day - amazing. It was then I realised that I had missed out (and it was too late) on great opportunities by only going to sessions during the week. BoFs are where you get down and dirty with the innards of Drupal and related technologies and theories - accessibility, Drupal for Museums, Open Data, etc were just some of the ones I attended in Barcelona last year.

What's a BoF? It's a "birds of a feather" meeting. Basically, people with a common interest book a room and sit around discussing it. It's usually someone with A LOT of knowledge about a topic that does so. The format is very informal and friendly, just like a tutorial in college, with usually less than 20 people in attendance. This year I'll end up at about 50% BoFs and 50% sessions (or less).

Go Easy on the Alcohol

Yes, we know, you're in Ireland and Irish people like to drink and party. That's true, but you're going to be here for a week. Please don't go overboard on Monday and be wiped out for the rest of the week (not least becuase my session is on Tuesday and I'd like to see you there!).

During the week there will be lots of social events. You are welcome to all of them. But do not feel pressured to drink alcohol or to buy drinks for others. Be respectful of yourself and others and when leaving venues please do so quietly - there are lots of people trying to sleep.

Attend the Keynotes

If you go easy on the alcohol, this one is easier to achieve. The keynotes are where you'll learn about the state of Drupal and the plans for the immediate future of it from Dries. This will be followed by a Q&A with Dries, moderated by a local volunteer, where you get to tweet questions to him.

The other two keynotes will be hugely relevant talks from very respected individuals - Emer Coleman and Eduardo Garcia.

Contribute to Drupal

There will be loads of opportunities to contribute to Drupal by sprinting and/or mentoring. There will be extended sprints each weekend before and after DrupalCon. The conference hotel will have a 24 hour sprint room. Contributing is how Drupal gets built. Please contribute.

Take Time Out

With all the talking and sessions and BoFs and keynotes and contributing, it's okay if your brain is feeling a little over-worked. We have a beautiful city in Dublin. Take some time out, go for a walk. Visit some our recommended things to see and do in Dublin. Talk to some locals. Enjoy yourself (DrupalCon is about more than just work).

And if all that fails to help you get the most out of DrupalCon, well, you could just go on the DrupalCon diet!

Sep 07 2016
Sep 07

As OG8 is steadily being built, I have noticed a certain pattern - or a mindset - we’ve been following which I think is worth sharing.

OG8 is the third time I’ve written OG for Drupal. The first OG7 version was a head jump into the Entity goodness that Drupal 7 brought along with Entity API. The second version was taking a small step back away from the Entity fiesta, but took two steps forward into the field API.

I think that as a developer I have matured since then. Edge cases are no longer my concern. I mean, I’m making sure that edge cases can be done and the API will cater to it, but I won’t go too far and implement them. It’s not that in OG7 we tried to tackle all of the edge cases, but in OG8 it’s even less.

In fact, although we write a lot of new code as part of the porting, as the way we write modules for Drupal 8 has changed considerably, writing OG8 feels like&mldr; Well, it feels like I’m mostly deleting files.

Removing lines of code is so much better than adding

Myths Debunked

It’s not too rare to hear rants about OG. Often they are not backed by actual data, or even refer to older versions.

I was even quite surprised to find out in one of DrupalCon BOFs that an “OG alternative” module (that now seems to be without any much activity for the past year) was created by an author that never bothered to check OG 7.x-2.x. They knew OG 6 and kind of knew OG 7.x-1.x, and yet they used to bash OG pretty badly.

(And just to prevent any mistake, but still not call out the module by name - I am not referring to the Group module. The above section is about another module. You can read about my positive and negative critique of Group here.)

Being in that BOF was both funny, and a little sad at the same time.

Now, don’t get me wrong. There’s nothing bad with alternatives. In fact Message and RESTful modules have grown as alternatives to existing solutions, but they all grew after a deep understanding of all the existing solutions.

So, just for the fun, here are the rants ordered by popularity:

OG is complicated

It is. After all, it’s dealing with a complicated problem. Just like many other important contrib modules, it does the heavy lifting so that you and I won’t have to do it when we build our sites. OG is dealing mostly with access - so no easy shortcuts can be taken.

With that said, the concept itself along with the implementation is quite easy to explain. In fact, in OG8 we’ve simplified it even more. That is, we’ve somewhat reduced the flexibility in order to reduce the complexity; but while doing so, made sure edge cases can still hook into the process.

I always find that doing sketches by hand, can show that ideas are actually easier then what they might seem. Here’s OG in free hand format:

Concepts should be expressed as easily as possible. Circles made with a small glass, and straight lines with a business card that was on my desk

Seriously, I can’t think of a simpler solution that will still allow a robust group site:

  1. The reference between a group content to a group is done by core’s entity reference.
  2. The reference between a user and a group is done by the OgMembership entity, that can hold aside from the association, also metadata such as the created time and the state of the membership (active, pending, or blocked).
  3. An OgMembership can also reference an OgRole, which is a role that applies inside the group.

OG adds a lot of overhead

I used Blackfire.io to check the performance of a clean Drupal 8 installation with 1000 users and 5000 nodes. Then I ran the same test on the nodes being also an OG “group” (i.e. OG uses it as the “container” of other “group content”). Profiling was done on an out of the box Basic page node view. When OG was enabled, it was tested with a user that had 15 groups (which is more than the typical use case).

Clean DrupalDrupal with OGDifferenceTime440 ms468 ms+28.3 ms (+6.43%)I/O Wait21.1 ms21.1 ms+44.2 µs (+0.21%)CPU Time419 ms447 ms+28.2 ms (+6.74%)Memory36.5 MB39.5 MB+2.98 MB (+8.16%)

The gist of it: OG added merely 28 ms to the request, and 3 MB more in memory. And for the record, we have not started doing optimizations yet!

Module X is much simpler/ faster/ betterer/ awesomer

Does that module work for you, and you are happy with it? Is it well tested and the maintainer does a good job?

Awesome, stay with that module. OG is just a tool - not a life choice :)

Correctness

I have a healthy obsession over quality and the idea of “correctness.” How can you move forward quickly with your software, but have enough guarantees that you are not breaking existing code. Since PHP is lacking a compiler, it leaves us with a few other good options.

Data integrity

Here’s one of my favorite images, a Drupal 8 developer sees on a daily basis.

Better have an error than wrong data

It’s an exception thrown by code that was not satisfied with the data it received. It’s not a notice, appearing in a red box on top of your page, which your brain has learned to ignore. It’s an “in your face” error message that makes sure you stop being lazy, and go fix your code.

OG8 is applying this same approach. Are you trying to create an OG permission with illegal value? Sorry, this won’t work, and we make sure you know about it. Silent errors are risky and can be easily overlooked and pushed to production.
Are you trying to save an OG membership for an anonymous user? Once again, we will throw an exception. This will make sure you won’t have a security issue, where suddenly anonymous users might get too much access on your site.

Automatic Testing

As good as exceptions are, they are just safeguards. Tests are what will make you and I sleep better at night. But of course, this really depends on the quality and quantity of your tests.

If I would tell you that OG8 has about 50 files, you might refer me to the “OG is complicated” section above, and gently imply that it sounds like a lot of files.

But sorry, I lied, as in fact OG8 has currently 120 files. However, 50 of those files are under the tests folder.

You see, OG, like any other good module out there has the life above the surface and below the surface. As a site builder or a dev you interact with that part. But the side below is responsible for asserting that we are not breaking the existing functionality or open up security holes. That’s the side we - the OG developers - interact with locally or on Travis-CI.

As you can imagine, this is very time consuming. In fact, it’s not rare that developing the tests can take more time than the actual code. Just Look at this example: the unsubscribe controller, responsible for checking if a user can unsubscribe from a group is about 15 LOC (lines of code). The unit test that covers this method has 230 LOC. In fact it’s even not the only test that covers this functionality, as there is also a Functional test to assert it.

That’s a lot of tests! And even though it’s time consuming, it actually allows us to move fast and save time in the long run. Because when you have the confidence that the system is well tested, you are not afraid to continuously iterate, rewrite, and polish existing work.

I think there is another hidden merit in tests. By taking the time to carefully go over your own code - and using it - you give yourself some pause to think about the necessity of your recently added code. Do you really need it? If you are not afraid of writing code and then throwing it out the window, and you are true to yourself, you can create a better, less complex, and polished module.

Simplifying and hiding advanced features

One of the mistakes that I feel made in OG7 was exposing a lot of the advanced functionality in the UI. It’s not a terrible mistake (ponder on the amount of complex stuff Views UI allows you to do), but I think that it contributed to feeling people had that things are complex.

This notorious administration page allowed you to add OG related fields to different entities. It also allowed you to add different field instances of the same type, as for example you can have multiple OG audience fields on the same bundle.

Don't worry kids, the beast is gone.

But these are all advanced use cases. When thinking about how to port them to OG8, I think found the perfect solution: we did’t port it. It might sound a bit funny, but I think there are important advantages in doing so:

  1. Less code to write and maintain.
  2. Less complexity in the system.
  3. Lower the barrier for site builders. They will have just a single page to set a bundle as related to OG.
Adding any OG related field will be done via a simple UI

Obviously, the more advanced features (such as the above-mentioned multiple OG audience fields) remain in the code, so advanced developers can use them when needed via code:


// Make bundle a "group".
\Drupal\og\Og::addGroup('node', 'page');

// Add OG audience field to a "group content"
\Drupal\og\Og::createField(\Drupal\og\OgGroupAudienceHelper::DEFAULT_FIELD, 'node', 'article');

Excited? So are we! Come and join us, we have low-hanging-fruit issues you can start with, and you’ll find yourself writing features and tests in no time!

Aug 25 2016
Aug 25

You guys asked so here we are. In my last video I answered the question, "Should I build on Drupal 7 or Drupal 8?" I mentioned in that video that we have a site currently in production on both Drupal 7 and Drupal 8." To the end user browsing the site it's completely transparent, they have no idea they're hitting two different Drupal instances. Today I'm going to show you how we're pulling this off.

How are we doing this? The quick answer is we've got an Nginx server sitting in front our two Drupal sites, proxying traffic based on URL. It's either Drupal 7 or Drupal 8. In a nutshell, basically what is happening is the user makes a request to your website URL which is pointed at our proxy server, the Nginx server, which has a list of rules of specific paths to push to Drupal 8 or otherwise push to Drupal 7. Let me show you a quick and dirty demo so you can see this in action. We're going to get in the weeds so put your Dev Ops hat on. I'm going to do this all on my local host using docker and a nice little utility called ngrok which is used basically to tunnel back into my local system from the public internet. This is not how we're doing it in production but the idea is the same.

All right, so I'm going to get two environments set up here. I'm going to use Drush Quick Drupal to get my Drupal 8 environment set up. Basically, this will get me a running version of Drupal 8.1.7 on my local machine. While that's doing that over here I'm going to get our activelamp.com site set up locally as well. This is a Jekyll site and so basically all we have to do is type in grant serve to see that site locally. All right, so there's our Active Lamp website running on our local host port 8080 and our Drupal 8 site is coming up and so now we have our Drupal 8 site hosting on port 888.  What's nice about Drush Quick Drupal if you're not familiar with it is it actually builds you a Drupal 8 site, downloads all the dependencies, and then launches this browser as you can see here on port 8888. It's using the internal php server to actually serve this.

We're going to go ahead and log in. Don't need to set a password because we're not really going to be using this site. For demonstration purposes I'm going to set up a piece of content here and I'm going to call this the what we do page. I'm going to give it a URL path of what we do. If I save and publish this we'll see the what we do page on our Drupal 8 installation. Basically, what we're going to do is we're going to set it up so that when you click on what we do on our Drupal 7 site it'll actually route to the Drupal 8 site with an Nginx proxy that we talked about.

If you haven't used Docker there's a utility called Docker Machine that basically will spit up a machine for you to run Docker on since you can't run it natively on the MAC yet. You can just type in Docker Machine Create, I'm going to do this in Virtual Box, and this is going to be our defaults machine. Okay, so our Virtual Box Docker Machine is set up and so now it asks us to run this command Docker Machine environment default and so we're going to go ahead and run that command. That basically exported some environment variables and then it says to run this eval code right here and so we're going to run that in our prompt as well. Now we should be able to use the Docker command and see what is on that Docker Machine, and so we have no containers currently running on that Docker Machine.

Okay, so we're going to create our Nginx proxy now and let me just go to where I have it pre-configured.  All right, so let's look at what this pre-configured proxy looks like. In this directory I have a Docker file and that Docker file basically reads from the Nginx image that's on Docker hub and then we have one step in there which is basically copying this activelamp.conf file into the conf.d directory for Nginx so that it gets read when Nginx has started. Let's look at the activelamp.conf file.

Basically, I have some paths set up here. Basically, what we're saying is when you hit the root path we're going to go to some URL, when we hit the what we do path we're going to go to some URL, basically pass to this URL. Then I have a couple Drupal paths, the core and the sites path. Basically anything that hits core or sites or anything underneath that will go to some URL.  The way we're going to actually do this is we're going to set up this Docker file to ... Or this configuration file to point at these local installations that I have set up. This is where ngrok comes into play. You can basically Google ngrok and install that. Go here, download ngrok, and then you'll be able to have tunnels coming back to your local host.

I'm going to show you guys how to actually use this once you have this installed. I'm going to go back to my home directory and type in ngrok http, and I want ... This is running on port 8080 and I want to map port 8080 back to my machine. This is basically updating or creating a tunnel out on the internet so that if I hit this URL right here it'll hit port 8080 on my local host. Then the Drupal 8 site that we want is on port 8888 and so let's open up another tab, ngrok8888. Okay, so now I have two URLs exposed to the internet that are coming back to my local machine. This is my Drupal 7 URL. In this case it's actually going to be the Jekyll URL because we would be migrating from Jekyll up to Drupal 8. We'll come back into here and we're going to say anything ... Or everything is going to come to this URL, but the what we do page we want to actually put on Drupal 8.

Let's come over here to our Drupal 8 URL, which is the other tunnel that we opened up, and grab that. Then we also need to redirect the core in the sites directory to Drupal 8. Those paths don't exist in the Jekyll site so we're safe by just directing all traffic underneath these paths, so the Drupal 8 site so let's go ahead and save this. All right, now let's go ahead and start up our proxy. If we come back here to our D8 proxy we have a command to actually build this image, and that is Docker build. We're going to call this thid D8 proxy under My name space and the Docker file is in this directory. This is going through the built process pulling down the Nginx image and then it's going to be to add in our one little command and create an image for us that we can then use and run with Docker.

All right, so now our Docker image is created, we're going to actually run this. The way you do that is Dockerrun. We're going to expose a port to our machine and that's going to be 8787 and we're going to map that to port 80 within the Docker container which is what Nginx is listening on. The image that we want to run is the image that we just built which is called Tomfriedhof/d8proxy. All right, so now our image is running, let's see if this actually works.

If we hit ... Oh, one thing is this is running in a Docker Machine, we need to know what the Docker Machine IP address is. I'm going to open up another tab here and I'm going to type in Docker Machine IP. The default Docker Machine is running on this IP address so if I hit that IP address on port 8787 which is what we exposed we can see that it is actually hitting our local installation, all of the styles aren't there. Then if I hit the what we do you can see that what we do is hitting the Drupal 8 path that we specified in our proxy so that's the proxy in action.

The reason why we had to use ngrok here is we couldn't access these containers directly from within our Docker container and so this is actually going out through the ngrok service and coming back into our local machine. Typically what you would do is the IP address of the proxy is what you would set up in DNS. We're going to mimic that right now by basically creating a host record for this IP address. Let's go back to our terminal, open up a new window, get into our hosts file, and we're going to say this IP address is activelamp.com.  Let's save that.  Now if I hit activelamp.com, let's just go to the root path, we'll see that we're hitting our web server internally that's running on this tab right here. And then if we were to click on what we do our Nginx proxy should forward us to Drupal 8.  There you can see that the what we do path that we clicked on in the menu does in fact go to the Drupal 8 site.

Let's go back to the home page. Basically, as you build out your site on Drupal 8 you can update these paths and just point different paths pointing to Drupal 8 so that you can update incrementally. That's how you do it. An Nginx proxy server sitting in front of two installations directing traffic. In production we actually host the proxy in AWS managed by Ansible. I hope you found this information helpful, talk to you next time.

Aug 23 2016
Aug 23

GSoC is almost over and I’m now submitting the project which I started with my awesome mentors Dick Olsson, Andrei Jechiu and Tim Millwood nearly 4 months ago. I knew it’d be a really great journey but I had no idea it’d be this awesome. Everything related to GSoC was perfect. The organisation, my mentors, the project itself was enough challenging as well as interesting at the same time. Weekly blogs, daily updates and communication with mentors over Slack made sure we’re on track. First part was easy but I struggled a bit in second half but my mentors were always right here to help me with all the issues I had. I used to feel a bit embarrassed as I was not getting things done as easily as any other student could have but they never felt the same way. They always had a smile at their face and a solution for me to work on. I’m really glad I got such supportive mentors.  Thanks a lot Drupal.

Drupal makes me happy

Project Description: The task was to solve the conflicts which may occur when two users try to push the same content with modifications in same piece of content/entity on their respective end. Initially it looked like a very difficult task and I was really afraid when I chose the project but when Dick Olsson told me that this is a very interesting project and something like this has not been done in Drupal like this from a long time, it may also get a lot of attention as well as support from other people in community as well, I was more than just happy in going with this project. It took me some time to actually understand how we would solve the problem and to be very honest, I had no clear idea for the community bonding period about if I still understand it clearly or not. I decided to go on step by step and knew what I had to do at one time. Once we started coding, I could see the future and the parts where the code I was writing at that moment would be used. Soon, I could see a very clear picture of our project and the path we had to follow to make it a success. All thanks to my mentors again for their constant guidance.

How we solved it: I started by understand what actually happens at the backend of Drupal When a node is updated. I learnt that a revision is created every time a node is updated. Multiple revisions forms a graph with actual entity as root node. In the image below, you can see a graph with multiple nodes. All these nodes are revision and root is actual entity. In simpler words, when we create a new entity, we are starting a graph and when we update that entity, we are adding a node in that graph. It should be noted that even when we remove an entity, we’re adding a node in the graph and not removing.

The complete solution was depending on two steps:

  1. Find Lowest common ancestor of 2 revisions.

  2. Implement recursive 3-way merge algorithm on them.

I will start by explaining the 2nd step and It’d pretty much cover the 1st one itself. Recursive 3-way merge Algorithm takes 3 parameters as input which are 3 entities (local, remote and base) and compares two of them (local and remote) with base entity.

It then makes sure that none of the content which is changed in Local/Remote is changed in Remote/Local as well. For example:  If some changes are made in Local on line number 19, there should not be any changes on line number 19 of remote and It should be identical to line number 19 of base entity. There can be changes on any other line of remote entity but not those which are changed/modified in local. Vice versa is true as well. If it is made sure that no changes in local and remote overlaps, there’d not be any merge conflicts otherwise there would be conflicts.

Let’s take another example: In the image below, we see that line 51 is changed by both the developers and content is different from the base entity. In this scenario, the system can not decide on it’s own if we want the loops to run 10 times as per Remote Entity or 20 times as per local entity or just 5 times as Base entity says. So we’ll let users manually decide what they want. In our case, developer wanted it to run for 25 times.

Figure 1 : Explaining how merge conflicts occursFigure 1 : Explaining how merge conflicts occurs
                                                                                                                                                                     IMAGE BY : DR. DROBBS (FOR INFORMATIONAL USE ONLY)

For further information on how it all works, you can also have a look at the 3rd week blog post at my blog.

Now coming back to the first step: “Finding LCA”, the base entity we use in recursive 3-way merge is the LCA of two revisions. It is considered as base as it contains all the latest changes which are reckoned to be in the two revisions we will be comparing. So, we find a common parent of both the revisions which is closest to both of them and compare these revisions with that parent only. That parent or LCA acts as base entity.

Example: Below is a graph of revisions with revision ID and status. As we can see there are multiple revisions. Now let’s suppose someone (Developer A) starts editing revision with revision_id 4-8B10006… and at the very same time, another person (Developer B) starts editing 4-82460F0…. When both the developers try to save their edits, we don’t know which changes should be kept in the final revision (new revision which would be created after the merge). So for that purpose, we need to develop a system which could compare the revisions content and make sure that there is no conflict.

As discussed above, first we would find Lowest common ancestor of both the revisions developers have modified. As we can see Revision 3-6F7F875…  is closest to both of them, it is the Lowest Common Ancestor. Relaxedws/lca library does this task of finding LCA of two revisions. Now we have three important parts we can use from the graph:

  • Revision 1 (4-8B10006…) which was modified by developer A.

  • Revision 2 (4-82460F0…)  which was modified by developer B.

  • Lowest Common Ancestor of both the revisions (3-6F7F875…). 

Figure 2: Revision Graph created by workspace module.Figure 2: Revision Graph created by workspace module.

 The next step is to find if there are any merge conflicts or not. For that purpose, we will compare contents of revision 4-8B10006… with revision 3-6F7F875… and inspect all the changes made in revisions 4-8B10006…. We’ll do the same for revision 4-82460F0….. Once we have compared both revisions with their LCA (revision 3-6F7F875…), we will compare the changes made in both revisions. If the changes contains some common content in both revisions, we know there is a merge conflict as the system can not decide which changes are more important. So at that time, we’ll have to show a 3 pane window to the developer and let him/her decide whether he wants. He would be shown content of all three parts i.e, revision 1, revision 2 and LCA. The manually chosen content will then create a new revision. The tree pane window would look like this.

Figure 3 : 3-Pane window to resolve merge conflicts manually (containing content from Local, Base and Remote entities).Figure 3 : 3-Pane window to resolve merge conflicts manually (containing content from Local, Base and Remote entities).
                                                                                                                                                       IMAGE BY : CODEMIRROR DEMO (FOR INFORMATIONAL USE ONLY)

And once the conflicts and either resolved or there wasn't any conflict, the graph would look something like the following image:          

Expected Graph after conficts are resolved.Expected Graph after conflicts are resolved.

Initially the biggest concern was to get my system set up and running properly. I had to install Drupal 8 locally and get an IDE with a good debugger to start working. As per my mentor’s suggestion, I used PhpStorm IDE from JetBrains and Xdebug for debugging purposes. Also, my mentors kept telling me to learn how to test the code I will write as they wanted to “Write tests first, code later” approach. It was one of the most challenging tasks as I had no exposure to testing and was totally new to it. So, with a little knowledge of everything, I started my journey and I’m really happy we got it going till the end.

Once the problem was clear, we started coding our way into it. We divided the whole process in sub tasks and completed one at a time which in the end was integrated together for a complete success of project.

Let’s take a look at the all the subtasks and how we implemented them.

Task 1: First task was to create a PHP Library which could return Lowest Common Ancestor from a Directed Acyclic Graph.

Implementation: We used clue/graph library and ran a Breadth First Search on the graph for both the revisions and then found the common nodes and returned the one closest to both the nodes.

Code: The code is pushed over github and packagist as well.

List of all my commits : Commits made by Rakesh Verma in Relaxedws/lca Library.

 A Pull commit may contain multiple commits.

Task 2: Once we’re done with the relaxedws/lca library, we needed another library which could use the LCA returned by relaxedws/lca for implementing recursive 3-way merge algorithm as described above. For this purpose, we created relaxedws/merge library which takes 3 arrays as input and merge them according to 3-way merge algorithm.

Implementation: We implemented all the algorithm by ourselves for this library. We converted the contents of file into array and then compared each line of these array with array from other revision. If there was any change in values of the arrays at same index, we made sure it doesn’t exist in 3rd array as well otherwise we returned a custom exception alerting user about merge conflict.

List of all commits: Commits made by Rakesh Verma in Relaxedws/merge Library.

Task 3: After the successful completion of both these libraries, we’re ready to implement these libraries in Multiversion module but then we realized we need one module which won’t use these libraries but use simple terminology to find LCA and perform merge algorithm in Drupal as not all Drupal sites would use Multiversion and hence these libraries won’t be used by all.

Implementation: As we discussed earlier how revisions are created in a linear graph by default in drupal, we created a module named “Conflict” which would take 2 node id as input and would return the parent of the node_id which was created first.

For ex: LCA(4,5) would be 3 and LCA(12,16) would be 11 and LCA(1,8) would be 1 as it’s the root node and it doesn’t have any parent.

Similarly it takes 3 node ids to perform merge and return the last created node id out of those 3 as the last created node is the latest one and it contains all the latest changes in linear graph. So, Merge(3,4,5) would return contents of node with id = 5 and Merge(4,6,9) would return the contents of node with id = 9.

We created a pluggable pattern with services in the container which could be used by other drupal modules as well. The services we created in the conflict module were used in Multiversion module as well to detect and solve merge issues in the complex graphs where a node can have multiple branches (nonlinear graph).

Code: The code is available at Drupaldeploy/drupal-conflict.

List of commits made by me can is available here: Commits made by Rakesh Verma.

Task 4: After implementing the simple LCA resolver and simple Merge resolver in Conflict module, we’re ready to start integrating the relaxedws/lca library into the Multiversion module. All the websites which uses Multiversion module can use these libraries to find Lowest common ancestor from the graph of revisions and use that as an input to merge library.

The feature is already completed and merged in Multiversion module.

List of all the commits made by me is present : Commits made by Rakesh Verma to integrate relaxedws/lca with multiversion module.

Task 5: Now we’re left with the integration of relaxedws/merge library with the multiversion module. We’ve implemented the functionality and writing tests for it. Some tests are failing because revision ID is different for each revision and hence, merge library is returning an exception because the revision ID is changed in all three revisions and library can not decide on it’s own which results are to be kept in final revision. We’re trying to solve this issue.

Implementation: We created a method to convert the tree returned by multiversion module into a graph and later, we used that graph and it’s contents in PHP libraries we created in first phase. We integrated those libraries with Multiversion module and accessed them via services defined in Conflict module.

Code: All the commits made by me can be seen here: Link to pull request for integrating relaxedws/merge into multiversion module.

Task 6: The last task of the project is to integrate Codemirror with the multiversion module so that if in any case, there is a merge conflict, A user would be shown all 3 nodes (Local, remote and Base) and would be allowed to decide what changes are to be kept in final revision. This is where Codemirror comes in. This is the last part of the project and we ran out of time.

Weekly Breakdown: The work we did weekly is mentioned below:

  • Community Bonding period:  Familiarize myself with the organizations, mentors and the codebase.

  • Coding Phase Week 1: Finished the PHP library to find LCA. (Blog Post)

  • Week 2: Wrote tests for the PHP library. (Blog Post)

  • Week 3: Finished the code for PHP library to perform recursive 3-way merge (Blog Post)

  • Week 4: Wrote tests for the PHP library to ensure it performs the algorithms correctly (Blog post)

  • Week 5: Started code to create module to find LCA in linear graph (Blog post).

  • Week 6: Wrote tests for module and Finished the LCA part of the Conflict module (Blog Post).

  • Week 7: Implemented Simple Merge Resolver in Conflict Module (Blog Post).

  • Week 8: Extensive tests written for Simple Merge Resolver (Blog Post).

  • Week 9: Finished the Conflict module (Blog Post).

  • Week 10: Started Integration of PHP library which finds LCA from a graph into Multiversion module. (Blog Post)

  • Week 11: Wrote tests to ensure integration has been done correctly in multiversion module (Blog post).

  • Week 12: Finished Integration of PHP library to perform recursive 3-way merge with multiversion module (Blog Post).

  • Week 13: Wrote Tests for the integration part of the PHP library with multiversion Module.

  • Week 14: Fixing Bugs, added documentation and fixed other issues.

Future Work:  I’d keep contributing to the organisation as much as possible and I’d finish the tasks which I couldn’t complete in given time. I’ll also try to mentor students in Google Code In. This was such a great experience and learning curve grew exponentially for me. I would be really fortunate if I could experience something like this ever again or if I could get another chance to work full time with my mentors.

Conclusion: Participating in Google Summer of Code has brought me closer to the Drupal community members which comprises of an amazing group of developers. The experience in working with them taught me essential soft skills like effective communication, extensive testing and much more, than just writing code. Not only I learnt about full scale development but also about writing Industrial level code as well which I believe I couldn’t have learnt on my own. Every single time I tried to write code with as few mistakes as possible but there were always some. In order to not make new mistakes, I sometimes made same mistakes multiple times but my mentors (specially Andrei) always informed me about these mistakes and why I shouldn’t repeat them. Writing tests was one of the major learning. I never thought they were this important. After writing code, when I thought now the work is done, it was always the start. Solving errors took twice the time than writing code. Initially when my mentor Dick told me that ideally writing code takes 1/3rd of the total time, I really didn’t take him very seriously until I experienced it myself. Other than this, I learnt the importance of having a good and working debugger. A few hours tasks could take more than a week if you don’t have a debugger working fine at your end as you just simply can not identify the problems sometimes with your code. No matter how fine code you’ve written or how obvious it seems that it should work, there will always be an issue at your end if tests are failing and only a debugger can help you detecting the issue. There were many other little things which I got to learn like working under given time and not sticking to a wrong method if that’s not working rather than spending time with it to make it work. These all things will help me a lot shaping my future as a software developer. I will be forever indebted to them for providing such a nurturing environment.

I would sincerely thank my mentors Dick Olsson, Andrei Jechiu and Tim Millwood, My C0-mentor Matthew Lechleider and whole Drupal community for the support over IRC. A big thank to Drupalize.me for giving us a chance to learn about drupal through their website for free. Thanks a lot Google for providing us the opportunity and thanks Drupal for choosing me . I am really grateful.

Aug 21 2016
Aug 21
TL;DR The Google Summer of Code period ends, and am glad that I am able to meet all the goals and develop something productive for the Drupal community. In this blog post, I will be sharing the details of the project, the functionality of the module and its current status.

I am glad that I was one of the lucky students who were selected to be a part of the Google Summer of Code 2016 program for the project “Integrate Google Cloud Vision API to Drupal 8”. The project was under the mentorship of Naveen Valecha, Christian López Espínola and Eugene Ilyin. Under their mentoring and guidance, I am able meet all the goals and develop something productive for the Drupal community.



Google Cloud Vision API bring to picture the automated content analysis of the images. The API can not only detect objects ranging from animals to famous monuments, but also detects faces on emotions. In addition, the API can also help censor images, extract text from images, detect logos and landmarks, and even the attributes of the image itself, for instance the dominant color in the image. Thus, it can serve as a powerful content analysis tool for images.

Now let us see how can we put the module to use, i.e. what are its use cases. To start with, the Google Vision API module allows Taxonomy tagging of image files using Label Detection. Label Detection classifies the images into a number of general purpose categories. For example, classifying a war scenario to war, troop, soldiers, transport, etc. based on the surroundings in the images. This feature of the module is especially important to filter the images based on some tags.

Second feature listing our use case is the Safe Search Detection. It quickly identifies and detects the presence of any explicit or violent contents in an image which are not fit for display. When this feature is enabled in the module, the Safe Search technique validates any image for explicit/violent contents. If found, these images are asked for moderation, and are not allowed to be uploaded on the site, thus keeping the site clean.

Please click here for video demonstration of the two above-mentioned use cases.

Continuing with the other use cases, the third one is Filling the Alternate Text field of an image file. Label, Logo, Landmark and Optical Character Detection feature of the Google Cloud Vision API have been used to implement this use case. Based on the choice entered by the end user, he/she can have the Alternate Text for any image auto filled by one of the four above-mentioned options. The choice “Label Detection” would fill the field with the first value returned in the API response. “Logo Detection” identifies the logos of famous brands, and can be used to fill the field accordingly. Likewise, “Landmark Detection” identifies the monuments and structures, ranging from natural to man-made; and “Optical Character Detection” detects and identifies the texts within an image, and fills the Alternate Text field accordingly.

Next comes the User Emotion Detection feature. This feature is especially important in cases of new account creation. On enabling this feature, it would detect the emotion of the user in the profile picture and notify the new user if he/she seems to be unhappy in the image, prompting them to upload a happy one.

Lastly, the module also allows Displaying the similar image files. Based on the dominant color component (Red, Green or Blue), the module quickly groups all the images which share the same color component, and display them under the “Similar Content” tab in the form of a list. Each item links itself to the image file itself, and is named as per the filename saved by the user. Users should note here that by “similar contents”, we do not mean that the images would resemble each other always. Instead we mean here the same dominant color components.

All the details of my work, the interesting facts and features have been shared on the Drupal Planet.

Please watch this video to know more on how to use the above-mentioned use cases in proper way.

[embedded content]


This is the complete picture of the Google Vision API module developed during the Google Summer of Code phase (May 23, 2016- August 23, 2016).


I would put to use these concepts in best possible way, and try to contribute to the Drupal community with my best efforts.
Aug 20 2016
Aug 20
Driesnote where GraphQL was featured. Picture from Josef Jerabek

After some time contributing to the Drupal project in different ways, I finally decided to step up and get involved in one of the Core Initiatives. I was on IRC when I saw an announcement about the JSON API / GraphQL initiative weekly meeting and it seemed like a great chance to join. So, this blog post is about how you can get involved in a Core Initiative and more specifically, how can you get involved in the JSON API / GraphQL Initiative.

The JSON API / GraphQL Initiative

This initiative appears as part of a larger one: the API First Initiative. The goal is to fully integrate the JSON API and the GraphQL specifications into Drupal Core. This fits perfectly into the API First Initiative as the of the parent issues is to make the data stored and managed by Drupal available for other software.

What happens if I’m still stuck with Drupal 7? While these initiatives are focused on Drupal 8 and will not have a direct backport to Drupal 7, there are a few solutions done on contrib that implement most of this functionality, like the RESTful module.

Why is this initiative important?

All the improvements on web services are a big step forward for Drupal when it is used as a backend for other applications like mobile apps, or for architectures like a Headless Drupal (Drupal used as backend and a totally decoupled frontend done in a different technology). It also helps to better connect with other services or applications, resulting in a more powerful tool.

The initiatives also uses common standards, which will help people who have less knowledge of Drupal to still use its advantages.

Now you know where you want to work so, where should you start?

Getting info

Before diving into the issue queue or the code, you should know well what is involved in the chosen initiative. The different initiatives usually have a central point where all the related information and issues are gathered. This can be a meta issue or a drupal.org project.

For the API First Core Initiative there is an issue you can find here. This gives us a general overview of the whole initiative and where fits within the JSON API and GraphQL initiative. In that issue, we can find the links to the specific projects of JSON API and GraphQL. Those pages and their respective issues queues are where the development of the initiatives is being held. You should read them carefully.

Mateu, maintainer of the JSON API project has also prepared a very useful set of videos explaining the features of the JSON API module and the different changes that are occurring during the development.

In addition, you can also get the most updated news on the meetings that are happening related to the core initiatives. There is a public Google Calendar with all the meetings. Some initiatives meet weekly, others are every two weeks or even monthly. My first contact with the initiative was in one of these meetings. I wasn’t able to participate a lot, but at the end of the meeting, I could get some helpful hints on where to start, and I had the idea of what could be my first contribution: this post!

I also learned that this initiative hangs out on the #drupal-wscci IRC channel, where you can ask for help or get the meeting hangout link. Just ping the people involved in the initiative, like Mateu Aguilo (e0ipso) from the Json API initiative, Daniel Wehner (dawehner) and Wim Leers (WimLeers) maintainers of the REST module on core or Sebastian Siemssen (fubhy), from the GraphQL Initiative.

Next steps

Get used to the code! Download and set up the Drupal 8 environment with the modules from the initiatives. Test them, and play a bit with them to know how they work. Subscribe to some issues to see how the development goes. Talk to the people involved in the initiatives and don’t be afraid to ask them.

And let’s start contributing!

Aug 17 2016
Aug 17

Woah!! We're in last week of Google Summer of Code. Hard to believe that the journey we started from 22nd April is about to come to an end. Soon I’ll be publishing a post summarizing all my experience, development and other great achievements during this time. It was a really awesome journey but I’m really happy that the bond we share with the community and open source is not tied to GSoC only. The thought that I would be able to contribute after GSoC as well gives me  a really good motivation. There are many things that I learned during this time and would be happy if I could ever teach any of it to someone. My mentors were the best part of this journey. I’m really happy I got mentors like them and they played a huge role in keeping this journey interesting and really enjoying. I feel really very lucky to have 3 mentors and each of them is really a master in their fields. On the top of that, what I really liked about them is their behaviour, nature and the respect they give me irrespective of the fact that I make mistakes almost all the time and they have to find the mistakes in my code every single week in every task. I always feel embarrassing but they always tell me that they wouldn’t have signed up for being a mentor if they had any problem with this. My words can not define a bit of their awesomeness. I’d really recommend you guys to do at least a single (even small) project under their guidance and write to me if you don’t fall in love with them. You can contact them or IRC or through their drupal profiles (Dick Olsson, Andrei Jechiu and Tim Millwood) No matter how busy they are, they will definitely make some time for you and you’ll often see them working almost every time. No matter what time you message them, they are like always online to solve your issues.

Coming back to the Project details,

Project Details: The task is to solve the conflicts which may occur when two users try to push the same content with modifications in same piece of content/entity on their respective end. So far, we've a way to detect conflicts but not any to solve them.

Solution we're working on: When a node is updated, a revision is created. Multiple revisions forms a graph with actual entity as root node. In the image below, you can see a graph with multiple nodes. All these nodes are revision and root is actual entity.

We detect conflicts in 2 steps:

  1. Find Lowest common ancestor of 2 revisions.

  2. Implement recursive 3-way merge algorithm on them.

I will start by explaining the 2nd step and It’d pretty much cover the 1st one itself. Recursive 3-way merge Algorithm takes 3 parameters as input which represents 3 entities (Local, remote and base) and compares two of them (Local and Remote) with base entitiy.

It then makes sure that none of the content which is changed in Local/Remote is changed in Remote/Local as well. For example:  If some changes are made in Local on line number 19, there should not be any changes on line number 19 of remote and It should be identical to line number 19 of base entity. There can be changes on any other line of remote entity but not those which are changed/modified in local. Vice Versace is true as well. If it is made sure that no changes in local and remote overlaps, there’d not be any merge conflicts otherwise there would be conflicts.

Let’s take another example: In the image below, we see that line 51 is changed by both the deveopers and content is different from the base entity. In this scenario, the system can not decide on it’s own if we want the loops to run 10 times as per Remote Entity or 20 times as per local entity or just 5 times as Base entity says. So we’ll let users manually decide what they want. In our case, developer wanted it to run for 25 times. ;)

Explaining how merge conflicts occursExplaining how merge conflicts occurs
                                                                                                                                                              Image by : Dr. Drobbs (For informational use only)
 

For further information on how it all works, you can also have a look at the 3rd week blog post at my blog.


Now coming back to the first step: “Finding LCA”, the base entity we use in recursive 3-way merge is the LCA of two revisions. It is considered as base as it contains all the latest changes which are reckoned to be in the two revisions we will be comparing. So, we find a common parent of both the revisions which is closest to both of them and compare these revisions with that parent only. That parent or LCA acts as base entity.

Example: Below is a graph of revisions with revision ID and status. As we can see there are multiple revisions. Now let’s suppose someone (Developer A) starts editing revision with revision_id 4-8B10006… and at the very same time, another person( Developer B) starts editing 4-82460F0… . When both the developers tries to save their edits, we don’t know which changes should be kept in the final revision ( new revision which would be created after the merge). So for that purpose, we need to develop a system which could compare the revisions content and make sure that there is no conflict.

As discussed above, first we would find Lowest common ancestor of both the revisions developers have modified. As we can see Revision 3-6F7F875…  is closest to both of them, it is the Lowest Common Ancestor. Relaxedws/lca library does this task of finding LCA of two revisions. Now we have three important parts we can use from the graph:

  • Revision 1 (4-8B10006…) which was modified by developer A.

  • Revision 2 (4-82460F0…)  which was modified by developer B.

  • Lowest Common Ancestor of both the revisions (3-6F7F875…) .                                         

Revisions Graph created by workspace moduleRevision Graph created by workspace module.

The next step is to find if there are any merge conflicts or not. For that purpose, we will compare contents of revision 4-8B10006… with revision 3-6F7F875… and inspect all the changes made in revisions 4-8B10006…. We’ll do same for revision 4-82460F0…  as well. Once we have compared both revisions with their LCA (revision 3-6F7F875…), we will compare the changes made in both the revisions. If the changes contains some common content in both the revisions, we know there is a merge conflict as system can not decided which changes are more important. So at that time, we’ll have to show a 3 pane window to the developer and let him/her decide whether he wants. He would be shown content of all three parts i.e, revision1, revision2 and LCA. The manually chosen content will then create a new revision. The tree pane window would look like this.

3 pane window to resolve conflicts manually.3 Pane window to resolve Merge conflicts manually (Containing content from Local, Base and Remote Entities).
                                                                                                                                                              Image by : CodeMirror Demo (For informational use only)

And once the conflicts and either resolver or there wasn't any conflict, the graph would look something like:

                                                                                            3-6F7F875…

                                                                                         /                  \

Just a prototype:                                           4-8B10006…    4-82460F0…

                                                                                        \                   /

                                                                                        5-XXXXXX......

Progress so far: We have created two php libraries. One to find LCA from a directed acyclic graph and other one to perform a recursive 3-way merge algorithm. We have also created a module named "Conflict" which would find LCA and perform the merge algorithm on Drupal entities. The Conflict modules doesn’t use the libraries we created in first phase of GSoC as by default Drupal 8 uses linear graph of Revisions. For example:

                                                                      1-----> 2 ------> 3 ------> 4 ------> 5

Where “1” is the actual nodes and rest all numbers are to be considered as its revisions. Now, finding Lowest common ancestor in such linear graph is easy. For example, LCA(2,3) is 1 and LCA(4,5) is 3. Also LCA(1,3) is 1. So we just checked if either one of nodes weren’t root, we returned the parent of the revision which was first created otherwise we returned the root ( Actual entity). Similarly for merge method, we just found the revision last created out of 3 and returned it as result the last created revision is the latest one in linear graph. For ex: Merge(3,4,5) would return 5 as result. This module doesn't use these libraries we've created.

However, those websites which uses Multiversion module will not use such approach as the graph of revision would be pretty different as defined above.

Now we are writing code in Multiversion module which would use these library. We'd be able to detect LCA from complex graphs and resolve merge conflicts using Multiversion module once we've integrated these APIs with the module. Of course these features would be available to sites using Multiversion module. At the moment, we have successfully integrated LCA Library with Multiversion module.

Work we did last week: We finished our work with ComplexLcaResolver.php which implements relaxedws/lca Library and returns lowest common ancestor from a directed acyclic graph. After we got that merged, we were all set for developing ComplexMergeResolver.php which would use relaxedws/merge to merge 2 arrays into one after comparing them with a third array. The whole merging process follows 3-way merge algorithm. You can read it on Dr. Drobss website for more information about it. You can also read this blog if you want to have a clear picture of how we are using it in Drupal 8 and Multiversion.

Work we did this week: We started our work with ComplexMergeResolver and have successfully implemented the functionality. We have successfully converted entity objects into arrays using serialization API and then we have used relaxedws/merge  library to detect any merge conflicts and merge them otherwise. The functionality is implemented and now we are writing tests to ensure it’s correct working. I’m really happy that we’re on the verge of completing our last development task. All the code we've written so far can be found here and the tests we've written are availiable here.

Aim for the next week: AAhhhhhhh!!!! Unfortunately, this is the last week. The only Aim for next week would be to plan how can I keep contributing to what I have created so far and other parts of this module.

I’d really like to thanks Matthew Lechleider. He talks to us once every week but has taught us one of the most important things i.e, to think thoroughly and define our tasks in very simple language. As a developer, we know what we have developed but most of the times, we’re not really able to make non-devs understand what our code is doing and what is the actual project. From the very starting where we started writing proposals to the very end, he used to tell me to “explain it in detail”. All of a sudden, it all makes sense now. Thanks a lot Drupal Community. Thanks a lot. You've given me an experience I'd never forget. 

Aug 17 2016
Aug 17

It’s been more than 13 warm weeks since I’ve started to work on my Google Summer of Code 2016 - Mailhandler project. During the past few weeks, I finished the coding and worked on latest improvements related to documentation.

In the past week, the project documentation has been updated which was the last step before merging Github repository and Sandbox project into Mailhandler. Drupal 8 release section was updated and it summarizes the features of D8 version. If you are wondering where you can use the code I developed this summer, feel free to read about a real-life Mailhandler use-cases.

This week, I am doing the latest cleanups and preparing the project for the final evaluation. It is the second evaluation after I submitted the midterm evaluation. In case you missed the previous posts from Google Summer of Code series, I am providing the project retrospect below.
 

Project Retrospect

In early February, in an ordinary conversation, a friend of mine told me about this year’s Google Summer of Code program. I got interested in it since I took part in GHOP (The Google Highly Open Participation Contest; This program was replaced with Google Code-In) during high-school.

In March, I’ve found out that Drupal will be one of the participating organizations and since I did a Drupal internship last year, this seemed to be a perfect opportunity to continue open-source contribution.

Among many interesting project ideas, I decided for “Port Mailhandler to Drupal 8”. Miro Dietiker proposed the project and during the proposal discussions, Primoz Hmeljak joined the mentoring team too.

The great news came in April. I was one of the 11 students chosen to contribute Drupal this summer! First Yay moment!

The project progress could have been followed on this blog, so I’m will not go into great details about this.

3 months of work passed quickly and at this point, I can confirm that I learned a ton of new things. I improved not only my coding skills but communication and project management skills too.

In my opinion, we reached all the goals we put on the paper in April. All the features defined in the proposal were developed, tested and documented.

Google Summer of Code is a great program and I would sincerely recommend all the students to consider participating in it.

Future plans

The future plans about the module are related to its maintenance. Inmail is still under development and it seems it will be ready for an alpha release very soon. I created an issue about nice-to-have features of Mailhandler. This issue could serve as a place for Drupal community to discuss the possible ways of the future Mailhandler development.


Thank you note

Last but not least, I would like to give huge thanks to my mentors (Miro Dietiker and Primoz Hmeljak) for being so supportive, helpful and flexible during this summer. Their mentoring helped me in many ways - from the proposal re-definition in April/May, endless code iterations, discussions of different ideas to blog post reviews, including this one :).

I would like to thank my company too for allowing me to contribute Drupal via this program and Google for giving me an opportunity to participate in this great program.

 

 

Aug 16 2016
Aug 16
TL;DR Last week I had worked moving the helper functions for filling Alt Text of image file to a new service; and moving the reused/supporting functions of the tests to an abstract parent class, GoogleVisionTestBase. This week I have worked on improving the documentation of the module and making the label detection results configurable.

With all major issues and features committed to the module, this week I worked on few minor issues, including the documentation and cleanup in the project..

It is an immense pleasure for me that I am getting the feedbacks from the community on the Google Vision API module. An issue Improve documentation for helper functions was created to develop more on documentation and provide the minute details on the code. I have worked on it, and added more documentation to the helper functions so that they can be understood better.

In addition, a need was felt to let the number of results obtained from the Vision API for each of the feature as configurable, and allow the end user to take the control on that. The corresponding issue is Make max results for Label Detection configurable. In my humble opinion, most of the feature implementations and requests to the Google Cloud Vision API have nothing to do with allowing the end user to configure the number of results. For instance, the Safe Search Detection feature detects and avoids the explicit contents to be uploaded, and does not need the number of results to be configurable. However, the taxonomy tagging using Label Detection should be user dependent, and hence, I worked on the issue to make the value configurable only for Label Detection purpose. This value can be configured from the Google Vision settings page, where we set the API key. I have also developed simple web tests to verify that the value is configurable. Presently, the issue is under review.

I have also worked on standard coding fixes and pa-reviews and assisted my mentor, Naveen Valecha to develop interfaces for the services. I assisted him on access rights of the functions, and fixing the documentation issues which clashed with the present one.

Lastly, I worked on improving the README and the module page to include all the new information and instructions implemented during the Google Summer of Code phase.

With all these works done, and all the minor issues resolved, I believe that the module is ready for usage with all the features and end user cases implemented.
Next Week, I’ll work on creating a video demonstration on how to use Google Vision API to fill the Alt Text attribute of an image file, detect the emotion in the user profile pictures and to group the similar images which share the same dominant color.
Aug 10 2016
Aug 10

This year’s Google Summer of Code is slowly coming to an end. I am working on latest steps to complete the project as planned. In the previous blog post, I was writing about the final code polishing of Mailhandler, while the focus of last week (#11) was to improve the overall project documentation. Before the project wrap-up blog post, I am going to write about the real use-cases for Mailhandler.

5 steps to create secured user-content-driven Drupal website

One of the best use-cases for Mailhandler would be for media publishing Drupal-based websites. Those websites usually have different user roles for content creators, publishers, editors, administrators… That means a very different set of permissions for each role. For instance, one website could allow its users to create site content. Users could submit it either through a website or by sending a signed email using Mailhandler.

In order to enable users to create content by sending an email, an administrator would need to follow these simple 5 steps:

  1. Enable authenticated users to post nodes for a specific content type (e.g. Users posts).

  2. Set-up an email address that users will send content to.

  3. Enable Mailhandler module and make sure gnu_pg PHP extension is enabled on the web server.

  4. Create a new deliverer in Inmail to fetch new emails. This can be done by using an IMAP deliverer.

  5. Set a content type in the (MailhandlerNode) handler configuration that will be used to create content in.

By completing all the steps, a Drupal website is ready to accept users submissions. Since we are going to use PGP-signed emails which add an additional layer of security, the following steps are needed on the user side:

  1. Log in to the account and update your GPG public key. PGP-signed messages are signed with a private key of a user and verified on the Drupal website with the corresponding public key. PGP method of authentication is briefly explained in this blog post.

  2. The email address in the user account needs to match to the address user wants to send emails from.

  3. The subject needs to begin with [node] part. This is a technical term and tells our plugins about the referenced entity type.

  4. The final step is to write your article and send the email!

Voila! The user created content is available on the website. Since it was digitally signed, it is guaranteed the message was not changed in transmission and the user can not deny sending and signing the message.

Some web hosting services don’t support gnu_pg PHP extension by default. However, you can still benefit from Mailhandler by using a less secure From email address method of user identification. In order to use it, you will need to enable Message Sender Analyzer.

The above use-case represents one part of the Mailhandler features. The module can be used in a similar way to post comments via email, create ads or to make any other email integration with “node” entities out-of-the-box.

To allow end-users and developers an easy start with the module, we have been improving project documentation a lot. A Github pull request has been submitted and passed for the review to my mentors. All Inmail analyzers and handler plugins provided by Mailhandler will be documented and described in details. Also, the project will get a ReadMe.MD file that will consist of the module description, installation, configuration and how-to sections.

Also, I would like to inform you that lead maintainer of the Mailhandler, Dane Powell recognized the efforts we made this summer and gave us write access to the original repository. Thanks to him, we will be able to merge our Github repository and a sandbox project to the main module. This is one step forward to releasing a stable version of Mailhandler and a duty to keep contributing to Mailhandler in the future too.

The plan for the following week is to merge the documentation pull request and work on remaining Inmail issues that we started earlier. Additionally, the final project evaluation starts in less than a week and I will spend some time to prepare for it as well.

Drupal 8 module demo: Mailhandler from Milos Bovan on Vimeo.

Aug 10 2016
Aug 10

Project Details: The task is to solve the conflicts which may occur when two users try to push the same content with modifications in same piece of content/entity on their respective end. So far, we've a way to detect conflicts but not any to solve them. 

Solution we're working on: When a node is updated, a revision is created. Multiple revisions forms a graph with actual entity as root node. The simplest way to detect a merge conflict is to compare entities with their parent entity and figure out if both users have modified the same content or not. In case both of them have modified same content from an entity, there'd be a merge conflict otherwise we can simply merge their updates which would result in a new entity. Now, to compare these entities, we need a base entity as well with which these two updated revisions can be compared. For this purpose, we find lowest common ancestor from the graph (Aka LCA). After finding LCA, we can compare both of them with their common parent revision one by one. This process is known as  3-way merge algorithm. According to this algorithm, we shall compare two entities/revisions with another entity/revision to detect the modifications. While comparing, we just make sure that the same content is not modified from an entity in both the new revisions. If this happens, there'd be a merge conflict. To solve this merge conflict, a 3-pane window would be shown to user and let him decide which code he wants to keep and the other code (from other developer) would be discarded. You can find more about the project and the approach in the 3rd week blog post at my blog.

Progress so far: We have created two php libraries. One to find LCA from a directed acyclic graph and other one to perform a recursive 3-way merge algorithm. We have also created a module named "Conflict" which would find LCA and perform the merge algorithm on drupal entities. This module doesn't use these libraries we've created. Now we are writing code in Multiversion module which would use these library. We'd be able to detect LCA from complex graphs and resolve merge conflicts using Multiversion module once we've integrated these APIs with the module. Of course these features would be available to sites using Multiversion module. At the moment, we have successfully integrated LCA Library with Multiversion module. The next task would be to integrate Merge Library with the multiversion module as well.

Work we did last week: We implemented the basic functionality for finding lowest common ancestor from a graph of revision last week in multiversion module. The first task was to implement a method which could return a graph of revision Id's from the tree containing all information of an entity and it's revisions. We implemented `getGraph()` in multiversion module for this purpose. It takes uuid as input and returns a graph containing nodes keyed with revision ids. Once we had the graph of revision ID, we were able to use the relaxedws/lca library to find nearest common parent of two revisions in this graph of revision ids. We also implemented basic tests for the ComplexLcaResolver class to ensure that it was returning the correct LCA.

Work we did this week: Some tests were failing last week because the graph multiple nodes were having same revision Ids in the graph returned by the code we wrote last week in the ComplexLcaResolver.php .  This week, we tested our code in ComplexLcaResolver.php for multiple graphs and made sure that all the tests were passing. Because of some issues with my debugger, I was not able to debug the programme and despite of everything working fine, tests were failing. I spent almost 4 days trying to solve the issue but in the end, I was unable to solve the issue on my own. A big thanks to my super awesome mentors Dick Olsson, Andrei Jechiu and Tim Millwood, they pointed me in the right direction and the issue was resolved in next hour. However, the issue this time was not caused because of a silly mistake in my code. The most important thing I learnt this week was the importance of a working debugger. I learnt how a debugger can make life of a software developer much easier. The other thing I learnt is to follow the standards, even in documentation. Although it is said that a good code should be able to explain itself but for other cases, we must add proper documentation. Documentation standards are different for Drupal modules than the ones we used in PHP Library. I got to know about this after we're done with the tests issue.

Aim for the next week: The next step is to implement code which can use relaxedws/merge library to detect merge conflicts or to merge updates from multiple revisions into one. We've started our work with it already. We would have to convert entity objects into array first and then the merge library would loop over them to detect merge conflicts. After we're sure that there are no merge conflicts, we'd update (merge) the entities and convert them back to object. We would be using Serialization API for this. We'd be implementing tests for this class as well this week to make sure it's working fine.

Aug 09 2016
Aug 09
TL;DR Last week I had worked on modifying the tests for “Fill Alt Text”, “Emotion Detection” and “Image Properties” features of the Google Vision API module. The only tasks left are moving the supporting functions to a separate service, in addition to, creating an abstract parent class for tests and moving the functions there.



There are few supporting functions, namely, google_vision_set_alt_text() and google_vision_edit_alt_text() to fill the Alt Text in accordance to the feature requested from the Vision API, and also to manipulate the value, if needed. I moved these functions to a separate service, namely, FillAltText, and have altered the code to use the functions from there instead of directly accessing them.

In addition, there are a number of supporting functions used in the simple web tests of the module, to create users, contents and fields, which were placed in the test file itself, which in one way, is a kind of redundancy. Hence, I moved all these supporting functions to abstract parent class named GoogleVisionTestBase, and altered the test classes to extend the parent class instead and in place of WebTestBase. This removed the redundant code, as well as, gave a proper structure and orientation to the web tests.
These minor changes would be committed to the module directly, once the major issues are reviewed by my mentors and committed to the module.
Aug 05 2016
Aug 05

Project Details: With the introduction of Multiversion module in Drupal 8, we have a very powerful content revision API that can handle branching and conflict DETECTION. But there is not yet a way to SOLVE revision conflicts.

Proposed Solution: We store a graph of all the updated revisions from an entity and find a base revision from this graph with which two entities can be compared. This process is based on 3-way merge algorithm. According to this algorithm, we shall compare two revisions of an entity with another revision or actual node to detect what has been modified in those revisions. If the new revisions has modified content over different lines, the updated content shall be merged in the new revision along with the unchanged data from previous revisions. This is why we compare two entities with a base entity, to find out which part has been modified in the new revisions. If both the new revisions has modified the same data, a merge conflict would occur and user would be allowed to solve the conflict in a 3-pane window. You can find more about the project and the approach in the 3rd week blog post at my blog.

By last week, we had already implemented the `GetGraph()` function in Multiversion module. The tree of revision is passed to the function and a graph is returned containing vertices keyed with the revision ID. After multiple tests, we made sure that the getGraph() method was returning the correct output. After this, the next task was to implement the feature to find Lowest Common Ancestor of 2 nodes from the Graph returned by getGraph() method.

We’ve created a class ‘ComplexLcaResolver’ in the Multiversion module which uses relaxedws/lca to find the LCA. This feature of finding LCA from a tree of revisions will be available only in those sites which uses multiversion module. We have implemented the functionality and now we’re in test phase. For now, there are bugs in this implementation and we are working on them. My mentors Andrei Jechiu, Dick Olsson and Tim millwood have been a real support and source of motivation for me so far. Not only do they assist me with the implementation ideas but also teaches me a lot when I am making silly mistakes or don’t know about any feature of Drupal. All the code we’ve written can be found here.

Now I’ve been working with Automation Testing for quite sometime and the most important thing that I’ve learnt is no matter how confident you are about your code, it’d fail under certain circumstances. It matters the most when your code would be used by many people out there. So, it’s better to test your programme thoroughly before pushing it. It’s time consuming and sometimes you have no idea where and why the tests are failing. This is one of the best things GSoC and my mentors have taught me. Running one test at my end takes nearly 45-60 minutes which makes the development process a lot slower. We can not work on multiple parts of the project as we are in last stage and every next part uses the results from the previous part. For example: Merge Library uses results from LCA library to perform 3-way merge algorithm. Once you are done with testing, you are pretty sure that there will be very few bugs in the program which will be discovered when the code goes live.

This week, we’d be done with ComplexLcaResolver implementation after few bug fixes and more tests. After that, we shall start ComplexMergeResolver implementation which will use relaxedws/merge library which we created in the first phase of GSoC16. This class would be used to detect merge conflicts and to merge the updated entities. It would also use Serialization module to normalize the given revisions into arrays and then, we can loop over those array to find any merge conflicts or to find where an entity has been updated and we’ll merge those changes into the main branch.

Also, I’d like to announce that we’ve launched relaxedws/lca library on packagist.org and it is ready to be implemented into any project. It can be found here: https://packagist.org/packages/relaxedws/lca

Aug 03 2016
Aug 03
TL;DR Last week, I had worked on and developed tests to ensure that the Alt Text field of an image file gets filled in accordance to the various detection features of the Vision API, namely Label Detection, Landmark Detection, Logo Detection and Optical Character Detection. This week I have worked to modify and add tests to various features of the Google Vision module, namely filling of Alt Text field, emotion detection of user pictures and grouping the image files on the basis of their dominant color component.

My mentors reviewed the code and the tests which I had put for review to get them committed to the Google Vision API module. However, the code needs some amendment pointed out by my mentors, which was to be corrected before commit. Hence, I spent this week working on the issues and resolving the flaws, rather than starting with a new feature. Let me start discussing my work in detail.

I had submitted the code and the tests which ensure that the Alt Text field gets properly filled using various detection features according to the end user choice. However, as was pointed out by my mentor, it had one drawback- the user would not be able to manipulate or change the value of the field if he wishes to. Amidst the different options available to the end user to fill the alt text field of the image file, there was a small bug- once an option is selected, it was possible to switch between the options, however, disabling it was not working. After, been pointed out, I worked on modifying the feature and introducing the end user ability to manipulate the value of the field as and when required. Also, I worked on the second bug, and resolved the issues of disabling the feature.

Regarding the Emotion Detection(Face Detection) feature of the Vision API, I was guided to use injections instead of using the static methods directly, and to modify variables. For example, the use of get(‘entity_type.manager’) over the static call \Drupal::entityTypeManager(). Apart from these minor changes, a major issue was the feature was being called whenever an image file is associated with. However, I need to direct it to focus only when the user uploads an image, and not on its removal (as both the actions involves an image file, hence the bug).

In the issue, Implementation of Image Properties feature in the Vision API, I had queried multiple times to the database in the cycle to fetch results and build the routed page using the controllers. However, my mentor instructed me that its really a bad way of implementing the database queries to fetch the results. Hence, I modified the code and changed them to single queries to fetch the result and use them to build the page. In addition, I was asked to build the list using ‘item_list’ instead of using the conventional ‘#prefix’ and ‘#suffix’ to generate the list. Another important change in my approach towards my code was the use of db_query(), the use of which is deprecated. Hence, I switched to use addExpressions() instead of db_query().
Presently, the code is under review by the mentors. I will work further on them, once they get reviewed and I get further instructions on it.
Aug 03 2016
Aug 03

This blog post summarizes week #11 of the Google Summer of Code 2016 project - Mailhandler. Time flies and it is already the last phase of this year’s Google Summer of Code 2016. The project is not over yet and I would like to update you on the progress I made last week. In the last blog post I was writing about the problems I faced in week 10 and how we decided to do code refactoring instead of UI/UX work. The plan for the last week was to update Mailhandler with the newly introduced changes in Inmail as well as work on new user-interface related issues. Since this was the last week of issues work before doing the project documentation, I used the time to polish the code as much as possible.

As you may know, Inmail got new features on the default analyzer result. Since this change was suggested by Mailhandler, the idea was to remove Mailhandler specific analyzer result and use the default one instead. It allows the core module (and any other Inmail-based module) to use the standardized result across all enabled analyzers. The main benefit of this is to support better collaboration between analyzer plugins.
Even though Mailhandler updates were not planned to take a lot of time, it turned to be opposite. Hopefully, the long patch passed all the tests and was fixed in Use DefaultAnalyzerResult instead of Mailhandler specific one issue.
It was needed to not only replace the Mailhandler-specific analyzer result but to use user context and context concept in general as well. Each of the 5 Mailhandler analyzers were updated to “share” their result. Also, non-standard features of each of the analyzers are available as contexts. Later on, in the handler processing phase, handler plugins can access those contexts and extract the needed information.

The second part of the available work time was spent on user interface issues, mostly on improving Inmail. Mailhandler as a module is set of Inmail plugins and configuration files and in discussion with mentors, we agreed that improving the user interface of Inmail is actually an improvement to Mailhandler too.
IMAP (Internet Message Access Protocol) as a standard message protocol is supported by Inmail. It is the main Inmail deliverer and UI/UX improvements were really needed there. In order to use it, valid credentials are requested. One of the DX validation patterns is to validate those credentials via a separate “Test connection” button.
 

IMAP test connection buttonIMAP test connection button

In the previous blog posts, I mentioned a power of Monitoring module. It provides an overall monitoring of a Drupal website via nice UI. Since it is highly extensible, making Inmail support it would be a nice feature. Among the most important things to monitor was a quota of an IMAP plugin. This allows an administrator to see the "health state" of this plugin and to react timely. The relevant issue needs a few corrections, but it is close to be finished too.

Seeing that some of the issues mentioned above are still in “Needs review” or “Needs work” state, I will spend additional time this week in order to finish them. The plan for the following week is to finish the remaining issues we started and focus on the module documentation. The module documentation consist of improving plugin documentation (similary to api.drupal.org), Drupal.org project page, adding a Github read me, installation manuals, code comments, demo article updates and most likely everything related to describing the features of the module.

Jul 30 2016
Jul 30

On a recent project, we had to create multiple sitemaps for each of the domains that we have setup on the site. We came across some problems that we had to resolve because of the nature of our pURL setup.

Goals

  • We want all of the front pages from each subdomain to be added to the sitemap and we are able to set the rules for them on the XMLSitemap settings page.
  • We want to make sure that the URLs that we are adding to the other pages no longer show up in the main domain's sitemap.

Problems

1) Only On The Primary Domain

The XML sitemap module only creates one sitemap based on the primary domain.

2) Prefixes not Distinguished

Our URLs for nodes are setup so that nodes can be prefixed with our subdomain (pURL modifier) and XMLSitemap doesn't see our prefixes as being different sites. At this point, all nodes are added to every single domain's sitemap.

3) URL Formats

Our URLs are not in the correct format when being added to the sitemap. Our URLs should look like http://subdomain.domain.org/*, however, because we are prefixing them, they show up as http://domain.org/subdomain/*. We want our URLs to look like they are from the right sub-domain and not all coming from the base domain.

Solution

We were able to add the ability to create sitemaps for each of the 15 domains by adding the XMLSitemap domain module. The XLMSitemap domain module allows us to define a domain for each sitemap, generate a sitemap and serve it on the correct domain.

We added xmlsitemap-dont-write-empty-element-in-xml-sitemap-file-2545050-3.patch to prevent empty elements from being added to the sitemap.

Then we used a xmlsitemap_element_alter inside of our own custom module that looks something like this:




function hook_xmlsitemap_element_alter(array &$element, array $link, $sitemap) {
  $domain = $sitemap->uri['options']['base_url'];
  $url_parts = explode('//', $domain);
  $parts = explode('.', $url_parts[1]);
  $subdomain = array_shift($parts);

  $current_parts = explode('/', $link['loc']);
  $current_prefix = array_shift($current_parts);

  $modifiers = _get_core_modifiers();

  
  if (in_array($subdomain, array_keys($modifiers))) {
    
    
    if ($current_prefix != $subdomain && $current_prefix != '') {
      
      $element = array();
        return $element;
      }
    else {
      
      $pattern = $current_prefix . '/';
      $element['loc'] = $domain . str_replace($pattern, '', $link['loc']);
    }
  }
  else {
    
    
    if (in_array($current_prefix, array_keys($modifiers))) {
      $element = array();
      return $element;
    }
  }
}


function _get_core_modifiers() {
  if (!$cache = cache_get('subdomains')) {
    $result = db_query("SELECT id, value FROM {purl} WHERE provider = 'og_purl_provider'")->fetchAllAssoc('value');
    cache_set('subdomains', $result, 'cache', time() + 86400);
    return $result;
  }
  else {
    return $cache->data;
  }
?>

If you have any questions, suggestions, feel free to drop a comment below!

Jul 27 2016
Jul 27
TL;DR Last week, I had worked on and developed tests to ensure that the similar images are grouped in accordance to the Image Properties feature of the Vision API. The code is under review by the mentors, and I would continue on it once the review is done. Meanwhile, they also reviewed the “Fill Alt Text” feature issue, and approved it is good to go. This week, I have worked on developing tests for this issue.

An important feature that I have implemented in the Google Vision API module is the filling of Alt Text field of an image file entity by any of the four choices- Label Detection, Landmark Detection, Logo Detection and Optical Character Detection. My mentor suggested me to check the availability of the response and then fill the field, as we can not fully rely on the third party responses. With this minor suggestion being implemented, now its time to develop tests to ensure the functionality of this feature.

I started developing simple web tests for this feature, to ensure that the Alt Text field is properly filled in accordance to the choice of the user. It requires the selection of the four choices one by one and verify that the field is filled correctly. Thus we require four tests to test the entire functionality. I have added an extra test to ensure that if none of the options are selected then the field remains empty.

I created the image files using the images available in the simpletests. The images can be accessed through drupalGetTestFiles(). The filling, however, requires call to the Google Cloud Vision API, thus inducing dependency on the API key. To remove the dependency, I mocked the function in the test module, returning the custom data to implement the feature.

The first test ensures that the Label Detection feature returns correct response and the Alt Text field is filled correctly. The simpletest provides a list of assertions to verify it, however, I found assertFieldByName() to be most suitable for the purpose. It asserts the value of a field based on the field name. The second test ensures that the Landmark Detection feature works correctly. Similarly, the third and fourth test ensures the correct functionality of the Logo and the Optical Character Detection feature.

The fifth test which I have included perform tests when none of the options are selected. It ensures that under this case, the Alt Text field remains empty, and does not contain any unwanted values.
I have posted the patch covering the suggestions and tests on the issue queue Fill the Alt Text of the Image File using Google Vision API to be reviewed by my mentors. Once they review it, I would work on it further, if required.
Jul 27 2016
Jul 27

It's been 3 months now and we're finally approaching the last steps of our project - "Solving Merge conflict in Drupal 8" with Multiversion module. So far, we have launched two Open source Libraries, Implemented Simple LCA resolver and a simple merge resolver in the Conflict  module to find lowest common ancestor and merge the updates respectively. Now all development phase is almost done and the integration part starts where we have to integrate the Libraries we created in the first phase of Google Summer of Code16. The libraries we created were relaxed/lca and relaxed/merge

Let's take a look at the project's target and the solution we are implemeting:

Project Details: With the introduction of Multiversion module in Drupal 8, we have a very powerful content revision API that can handle branching and conflict DETECTION. But there is not yet a way to SOLVE revision conflicts.

Proposed Solution: We store a graph of all the updated revisions from an entity and find a base revision from this graph with which two entities can be compared. This process is based on 3-way merge algorithm. According to this algorithm, we shall compare two revisions of an entity with another revision or actual node to detect what has been modified in those revisions. If the new revisions has modified content over different lines, the updated content shall be merged in the new revision along with the unchanged data from previous revisions. This is why we compare two entities with a base entity, to find out which part has been modified in the new revisions. If both the new revisions has modified the same data, a merge conflict would occur and user would be allowed to solve the conflict in a 3-pane window. You can find more about the project and the approach in the 3rd week blog post at my blog.

Work we did last week: The multiversion module stores the revision status and other data in form of trees. To detect and solve conflicts, we need to convert this data in graphs. Last week, we worked on writing code which could create a graph from a given tree.

We wrote a recursive function to store all revision Ids from the tree in an array. Then we created nodes from those revision IDs. After the recursive function extracted the revision ID correctly, we wrote a function which creates edges between these nodes in the exact same manner in which they were connected in the tree. The code is pushed here.

Work we did this week: We tested the code we developed last week for the Conflict Module to convert the tree returned by getTree method of Multiversion module. After we made sure it’s returning the expected output, we merged the code into Multiversion module as a new method named getGraph. Other than that, we have written tests for it in the multiversion module as well to ensure it’s functionality with the module. We also implemented Travis CI integration for the conflict module. We’re also making sure that our code is working on other versions of drupal than 8.2. All the code is pushed here.

Target for the next week: We will start with creating a complex LCA resolver which will use the relaxedws/lca library for finding LCA. This resolver will be available to only those sites which uses multiversion module and so we will implement this resolver in multiversion module only. We’d also be writing tests for the complex LCA resolver this week only.

Jul 27 2016
Jul 27

This blog post summarizes week #10 of the Google Summer of Code 2016 project - Mailhandler.

In the last blog post, I was writing about the comment and demo module improvements. This blog post will provide an overview of the work done in the past 7 days. Even though the plan was to work mostly on UI/UX issues we ended up in code refactoring.

During the last meeting with my mentors we identified 3 key Inmail issues to work on: Lack of standard result in collaboration of analyzers, Support switching the user context and Provide a hook_requirements fed by plugin instances. We agreed those issues will provide better overall value in the integration of Mailhandler and Inmail modules. It will allow Inmail to implement ideas from Mailhandler, make them generic in a way both modules can benefit from.

Lack of standard result in collaboration of analyzers was identified as the main blocker to achieve analyzer collaboration. After a long discussion and 7 patches, it was finally committed. As a result, Inmail will have a default analyzer result which can be extended sequentially by all enabled analyzers. As this was a big change in core Inmail module, there are several follow-ups created.

Another Inmail issue Support switching the user context was dependent on the default analyzer issue. It uses AccountSwitcher service which completely switches the user context to the given user/account. That is done after the handlers run. In case the account switching mechanism was activated, we make sure it is switched back after the handlers-processing. On a handler level, we can use \Drupal::currentUser() and be sure it represents the identified user sender or an anonymous user otherwise.

Last but not least, I have been working on Provide a hook_requirements fed by plugin instances. The goal of this issue is to create a way for each of the Inmail plugins (analyzers, deliverers, handlers) to provide information about its runtime requirements. They can be PHP extension requirements, valid credentials etc. This information is displayed on “Status report” page (admin/reports/status) or processed by contrib modules like Monitoring.

Image removed.PGP Analyzer requirements

Inmail plugins can produce several issues with unmet requirements. As displayed in the picture above, PGP Analyzer needs gnupg PHP extension in order to work with signed messages. On the other side, an IMAP deliverer needs valid credentials to be functional.

Since the most of the Inmail issues mentioned above were committed, Mailhandler module will need adaption which is going to be my focus for this week. Also, I will analyze the code of the module and try to simplify it. Besides the mentioned, I will work on Inmail UI/UX issues which will be described in the next blog post.

Jul 26 2016
Jul 26
TL;DR In the past two weeks I had worked on using the Image Properties feature offered by the Google Cloud Vision API to group the image files together on the basis of the dominant color components filling them. In addition, I had also worked on detecting the image files and filling the Alternate Text field based on the results of Label/Landmark/Logo/Optical Character Detection, based on the demand of the end user. This week, I have worked on and developed tests to ensure that the similar images are grouped in accordance to the Image Properties feature of the Vision API.

At present, the Google Vision API module supports the Label Detection feature to be used as taxonomy terms, the Safe Search Detection feature to avoid displaying any explicit contents or violence and the User Emotion detection to detect the emotions of the users in their profile pictures and notify them about it.

I had worked on grouping the images on the basis of the dominant color component(Red, Green or Blue) which they are comprised of. I got the code reviewed by my mentors, and they approved it with minor suggestions on injecting the constructors wherever possible. Following their suggestions, I injected the Connection object instead of accessing the database via \Drupal::database().

After making changes as per the suggestions, I started developing simple web tests for this feature, to ensure that the similar images gets displayed under the SImilarContents tab. It requires the creation of new taxonomy vocabulary and adding an entity reference field to the image file entity. After the creation of the new Vocabulary and addition of the new field to the image file, I created the image files using the images available in the simpletests. The images can be accessed through drupalGetTestFiles(). The first test ensures that if the Vocabulary named ‘Dominant Color’ is selected, the similar images gets displayed under the file/{file_id}/similarcontent link.

The grouping, however, requires call to the Google Cloud Vision API, thus inducing dependency on the API key. To remove the dependency, I mocked the function in the test module, returning the custom data to implement the grouping.

To cover the negative aspect, i.e. the case when the Dominant Color option is not selected, I have developed another test which creates a demo vocabulary to simply store the labels, instead of the dominant color component. In this case, the file/{file_id}/similarcontent link displays the message “No items found”.
I have posted the patch covering the suggestions and tests on the issue queue to be reviewed by my mentors. Once they review it, I would work on it further, if required.
Jul 25 2016
Jul 25

Project Details: With the introduction of Multiversion module in Drupal 8, we have a very powerful content revision API that can handle branching and conflict DETECTION. But there is not yet a way to SOLVE revision conflicts.

Proposed Solution: We store a graph of all the updated revisions from an entity and find a base revision from this graph with which two entities can be compared. This process is based on 3-way merge algorithm. According to this algorithm, we shall compare two revisions of an entity with another revision or actual node to detect what has been modified in those revisions. If the new revisions has modified content over different lines, the updated content shall be merged in the new revision along with the unchanged data from previous revisions. This is why we compare two entities with a base entity, to find out which part has been modified in the new revisions. If both the new revisions has modified the same data, a merge conflict would occur and user would be allowed to solve the conflict in a 3-pane window. You can find more about the project and the approach in the 3rd week blog post at my blog.

Work we did last week: We are done with the simple merge resolver as well now. The task was to resolve merge conflicts in linear entities which drupal implements by default. The approach we took for this was to return the entity last created in the revision. This way, the entity which was created last would be returned as it is the latest entity. We have also written tests for it. The code for the library can be found on the github repository.

Work we did this week: The multiversion module stores the revision status and other data in form of trees. To detect and solve conflicts, we need to convert this data in graphs. This week, we have been working on writing code which could create a graph from a given array.

We wrote a recursive function to create an array to store all revision Ids from the array and then we created nodes from those revision IDs. Next we are working on a function which creates edges between these nodes. The code is pushed here in the getGraphTest.php file.

We are done with the code and testing it to make sure it’s returning the expected output. Once we are sure it’s returning the correct data, we can implement the code into the multiversion module.

Task for the next week: We will complete the tests, get the code implemented in the multiversion module to return graph from the tree and will also try to complete the complex LCA resolver code as much as possible. We need to complete the graph creating code first as it’d be used in all next steps i.e, to find LCA using relaxedws/lca Library and to resolve merge conflicts using relaxedws/merge library.

Jul 25 2016
Jul 25

Yesterday all the accepted sessions for DrupalCon Dublin were announced, and we are delighted to report that 5 of our 8 session proposals were accepted! With Acquia being the only company receiving more acceptances, we are extremely proud of our achievement.

Testament to our high standing in the Drupal community, we are the only Irish company speaking at DrupalCon Dublin. Our accepted sessions this year span a number of different tracks, namely Business, Horizons, Site Building, Being Human and Core Conversations, and cover topics from accessibility to remote working to building mobile apps with the Ionic framework. Congratulations to all our speakers!

Here's a quick run down of each session.

Building a co-lingual website - lessons learned from ireland.ie

Speaker: Alan Burke
Track: Site Building

2016 marks the centenary of the 1916 rising in Dublin, a pivotal year in Irish history, and is marked with a series of high-profile events commemorating the rising. ireland.ie is the official state website for the 1916 commemoration and runs on Drupal 7.

While English is the main language in Ireland, Irish is the first official language. A decision was taken to present both languages side by side wherever possible for the 1916 commemorations - including on the website. This session will focus on the unusual co-lingual [2 languages side-by-side] approach, and how Drupal made it possible. 

Choosing Drupal - insider advice from an Irish multinational

Speaker: Alan Burke & Aisling Furlong from Glanbia
Track: Business

Struggling to sell Drupal to clients? Ever wondered what goes into the decision making process when choosing a CMS?
In 2014, Glanbia selected Drupal as the CMS of choice for marketing sites. This session will outline the decision-making process used, and what Drupal agencies can learn when pitching Drupal. This is a joint session proposal between Annertech and Glanbia.

Bridging the PhoneGap: Getting Started Creating Hybrid Mobile Apps with Drupal and Ionic Framework

Speaker: Mark Conroy
Track: Horizons

With the advent of hybrid mobile apps, you can continue being a Drupal frontend developer and also build apps without needing to learn new technologies. The mobile web is quickly catching up with native apps. The mobile web is free, and open, and available to all of us right now and doesn't bind us to proprietary systems. With the many advances being made in this area, we can create great mobile experiences for users.

Future Directions for Drupal Accessibility

Speaker: Andrew Macpherson
Track: Core Conversations

Drupal has made great advances in accessibility over several major releases, and nowadays ranks as a leading implementation of web accessibility standards.  This session will encourage contributors to look ahead at future challenges and opportunities for accessibility during the faster 8.x (and 9.x) release cycle. 

Happiness is... remote working

Speaker: Anthony Lindsay
Track: Being Human

Many Drupal agencies have remote workers. Some are entirely distributed. Whilst remote working is beneficial to all concerned in so many ways, it does come with its own challenges. This talk will cover the journey I took when I moved from a typical 9-5 office job and joined Annertech, which is an entirely distributed Drupal agency. It will highlight the challenges I found: the good, the bad, the funny and the downright surprising, and offer as examples, my experiences for staying happy and healthy in what has the potential to be an isolating environment. 

Congratulations to Alan, Anthony, Andrew and Mark on their great achievement. We look forward to seeing these and all the other great sessions at DrupalCon Dublin in September. Hope to see you there!

Jul 23 2016
Jul 23

Ever since Andrew joined Annertech, he's been a champion of accessible web design and has ensured that accessibility has remained a key focus area in everything we do. That combined with his dedication to open source and contributing back to the community, meant that we were not surprised when he was asked if he'd be interested in becoming a Drupal core accessibility maintainer.

Andrew is truly passionate about accessibility and has increased the knowledge and awareness of issues encountered by people with disabilities for all members of our team. We can not think of a better candidate for a new Drupal core accessibility maintainer.

His response when asked to be a Drupal Core maintainer?

I was really stoked when Mike asked if I'd consider becoming a core maintainer. I have barely stopped bouncing around my home.

Congratulations from everyone in Annertech Andrew!

Jul 20 2016
Jul 20

During the 8th week of Google Summer of Code 2016, we have started with adding support for posting comments via email. After getting the feedback from my mentors, there was some space to improve proposed solution. The suggestions were accepted and briefly explained below.

Comments in a submodule

As comments are supported through new handler plugin (MailhandlerComment), we decided to move it into a submodule - mailhandler_d8_comment. Following this approach, we can avoid too many dependencies on the main module. The submodule features: Inmail config entity that represents the handler, the plugin class and the related test coverage.

Configurable referenced entity type

With configurable referenced entity type of processed comments, we can support not only node entities but all the other “commentable” entities. In my opinion, this is a nice feature for site administrators in case they want to allow posting comments (for their articles or custom entities) as easy enough as sending an email.

Strict validation

Validation is the important topic in software development in general. In Drupal 8, there is an API made specifically for entity validation - Entity Validation API. It is recommended to use it before saving an entity. However, entity validation does not work as expected in a case of creating comments via API. The referenced entity ID and its bundle were not validated which required us to find a different approach. To accomplish this, we had to implement custom validation checks. They consist of:

  • Entity type validation - entity type is “commentable”

  • Referenced entity ID validation - referenced entity with provided ID actually exists

  • Bundle validation - identified entity bundle supports comments


Last week, besides the improvements made on the comment feature, I was working on the demo module improvements. The pull request has been submitted on Github and available for review. This module serves as an example module to show features of Mailhandler. It creates a sample “Mailhandler” content type (with a body field) and a new user with permissions to add content for “Mailhandler” content type and post comments. The GPG key field of this user was populated  with a sample key (both public and private GPG keys were added to the module) as well. Since last week, the example messages - sample comment and PGP clear-signed, MIME and MIME HTML emails are part of the demo module too. By enabling mailhandler_d8_demo, exploring Mailhandler features becomes very straightforward.

[embedded content]

Drupal 8 module demo: Mailhandler from Milos Bovan on Vimeo.

Also, the demo module adds a sample article attached to the front page. The idea is to have a descriptive article about Mailhandler features. Its content will be extended during the “documentation week”. Next week, I will be working on improving overall user experience and user interface of Mailhandler.

 

 

Jul 19 2016
Jul 19

Project Details: With the introduction of Multiversion module in Drupal 8, we have a very powerful content revision API that can handle branching and conflict DETECTION. But there is not yet a way to SOLVE revision conflicts.

Proposed Solution: We store a graph of all the updated revisions from an entity and find a base revision from this graph with which two entities can be compared. This process is based on 3-way merge algorithm. According to this algorithm, we shall compare two revisions of an entity with another revision or actual node to detect what has been modified in those revisions. If the new revisions has modified content over different lines, the updated content shall be merged in the new revision along with the unchanged data from previous revisions. This is why we compare two entities with a base entity, to find out which part has been modified in the new revisions. If both the new revisions has modified the same data, a merge conflict would occur and user would be allowed to solve the conflict in a 3-pane window. You can find more about the project and the approach in the 3rd week blog post at my blog.

Work we did last week: We finished writing code for simple LCA resolver along with tests and after that we started our work to implement a simple merge resolver for linear entities in drupal. We started by writing basic services, creating containers and I spent lot more time in reading about Symfony framework and Drupal8 module development.

Work we did this week: We are done with the simple merge resolver as well now. The task was to resolve merge conflicts in linear entities which drupal implements by default. The approach we took for this was to return the entity last created in the revision. This way, the entity which was created last would be returned as it is the latest entity. We have also written tests for it. The code for the library can be found on the github repository.

Next week’s task: After we’re done with the extensive testing of this simple merge resolver, we will start our major task with the complicated lca resolver where we’d integrate the library we created in coding phase 1 to find LCA with Drupal8 Conflict module. Our approach will be the same - write tests first and then code.

My mentors Dick Olsson, Andrei Jechiu and Tim Millwood have been really very supportive. Not only they have taught me how to code in a better way but they also help me understanding why it is important to test a software extensively. It’s only because of them I have came this far. All the credits to them only. I know my project is very interesting but the have made the whole journey interesting.

Jul 18 2016
Jul 18
Drupal Component Composer Console default avatar

Thought byRay Saltini

July 18, 2016

When we said we'd introduce you to the ABC's of Drupal we didn't just mean the easy stuff. Here are three C's that will help you understand the power behind Drupal 8.

Component: In Drupal 8 the word component is often used to identify one of the libraries managed by the Symfony project used by Drupal. Visit this link for a full list. https://ffwagency.com/blog/what-symfony-components-are-going-drupal-8 While Twig is often cited as a Symfony component, strictly speaking it is a PHP theming engine created by the same individuals who founded and maintain the Symfony project.

Composer: Composer is a dependency manager tool for PHP, Drupal’s core scripting language. If you are familiar with a package manager it is similar but not the same. Practically speaking Composer will help you download, install and manage specific code libraries and any additional code libraries they in turn may be dependent on for a given project. It’s important to understand that Composer is project centric - it defaults to managing code and dependencies within projects (like websites) rather than globally across projects. Composer’s use in the Drupal space is growing with the adoption of Drupal 8 and has begun to be used as an alternative to .make files which have been used to help manage Drupal installs and distributions.

Console: Console is a component of the Symfony project. Most often when a Drupal developer refers to using Console they are talking about using Drupal Console, a suite of tools run from a command line interface (CLI) to generate boilerplate code and interact with a Drupal 8 installation. In 2014 FFW hired Drupal Console’s lead project developer Jesus Olivas to develop the project and contribute the tool back to the Drupal community to strengthen Drupal 8 adoption. Drupal Console is used as a learning tool, module and theming scaffolding, debugger and configuration tool for Drupal 8. For more information on Drupal console visit https://ffwagency.com/blog/drupal-console-overview-new-drupal-cli

Pages

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