Aug 28 2015
Aug 28

The success of a project depends on a good development team. How to build and maintain such a good team?

As, a software developer for many years, I believed a good dev team is one of the pillars for a successful business. Here, I want to discuss how to build a dream developer team. Building a high productive, super innovative and proactive team is like cooking a meal. It needs a good ingredient, right source, and good timing in each step of cooking.

A good developer has a good academy score in math. Software developing needs the strongest logic thinking and self-validation skill. Building a software project like taking a mathematics test. The higher score in the test means fewer bugs in the code. A person who is capable of getting full scores on math tests is likely to build a project with least bugs. Finding right persons is the first step toward a great team.

A good academy score will not automatically make a good developer. Building software projects are team workings. Developing software is very detail oriented. We may not be able to avoid nitpicking on something. Soft skill is important too. A good developer is willing to learn, easy to collaborate and detail oriented. A good developer will always focus on the matters but never escalate matters to a personal level. A good developer can accept criticism and change for a greater good of the team.

After we have gathered a group of talented developers, it is time to "cook". Every person can be in different states. Software developers can be in the peak productivity state or the bottom of the productivity. An encouraging and rewarding environment with a strong leadership is the key to motivating developers to reach the peak of their productivity. Reward developers with self-fulfillment and let them achieve something with their work. A leading developer with an extraordinary fellowship will help it a lot.

We might ignore the physical environment. Nice, clean, quiet offices help developers focusing on their job. Some start-up companies put a lot of effort to finding talents but did not let them work comfortably. Sometimes, offices are crowded and stuffy. What they can do is just stop looking for a smarter developer and put a little bit more effort to improve the current working condition. In such a company, even the best developer is not able to concentrate on his job. Software developing is a mind activity. The brain requires a lot of blood circulation with plenty of oxygen and energy. The importance of clean, quiet, natural and toxic-free environment will never be overestimated. A healthy environment is a basic requirement for a strong software product.

The next one is an a study oriented and encouraging setting; A company has a respectful culture and a group of open minded developers. It is where developers are very closely collaborating with each other. Developers are not afraid to make a mistake and willing to share their latest trick and newly mastered programming tactics.

Aug 28 2015
Aug 28

28 Aug 2015

The benefits of online publishing are enormous no doubt and with the outreach of technology it only makes the written word easily accessible to target audiences. e-Publishing has gained immense popularity over traditional forms of publishing. However, such ground-breaking innovative solutions may be accompanied with a string of shortcomings that need to be addressed. In case of e-publishing, where some of its challenges could have disastrous ramifications on businesses, Drupal comes as a rescue to fix the unfixed.

drupal epublishing

The very term e-publishing means, publishing reading material online. The written word in the form of research, journalistic periodicals, books etc. is now being easily published online that has a far wider reach too. Today online e-publishing has many advantages over the traditional forms of publishing and it is evident from its various advantages.

  1. Lower publisher cost as compared to the traditional means
  2. Fast turn-around time in the publishing life cycle, easily made corrections or edits 
  3. Creation of a web of information via provision of links to reference materials

With every opportunity there comes a challenge and the revolutionary shift in publishing industry to online publishing, faces some tough hurdles. The availability of all the written material online has its own disadvantages at various levels.

  • Unauthorized copying of material 
  • Need to master content distribution
  • Pricing that can be a deterrent to sales
  • Complete lack of collaboration on a platform level

The requirement of a platform to publish online; one that essentially streamlines the efficacy of online publishing and minimizes problems and issues is really the need of the time. Drupal is poised to not only address these issues but also meet these challenges efficiently. While enterprises deal with scaling up and maintaining an even content distribution, there are many advantages that Drupal for e-publishing confer upon businesses are enormous and adapted by one and all.

  • Being a CMS, Drupal offers the basic structure of creating and maintaining a website. Its inherent Open-Source nature and several unique functionalities allow Drupal to reduce the deployment costs radically. Naturally the costs saved can be passed on to the end user
  • Drupal can help in automating workflow thorough contributed modules such Workbench, Revisioning and Workbench Moderating. Drupal or its more sophisticated Disqus module’s simple comments, allows the user to comment on the site
  • Google analytics can seamlessly integrate in Drupal. This comes as huge advantage to Drupal for e-publishing, because it allows tracking various data points that can harness marketing efforts of online publishing companies
  • Drupal e-publishing facilitates much needed tools such as Stackly that allow collaboration between researchers and writers in a such a way that the power of the online community is enhanced and harnessed for achieving peer based reviews
  • A permission based access control that is built in Drupal, allows only authorized users, thus eliminating piracy
  • With Drupal Commerce integration, users can now buy site resources such as articles for any online usage

Thus, e-publishing being one of the most lucrative businesses today, modern day publishers needs to have a robust and versatile CMS. Drupal for e-publishing with its repository of contributed modules can easily cater to all the needs and challenges present in the e-publishing world today. Also, since Drupal supports custom coding it is possible to extend any of the modules present or write one that is customized and exclusive. 

Aug 28 2015
Aug 28

We met again today to discuss critical issues blocking Drupal 8's release (candidate). (See all prior recordings). Here is the recording of the meeting video and chat from today in the hope that it helps more than just those who were on the meeting:

[embedded content]

If you also have significant time to work on critical issues in Drupal 8 and we did not include you, let me know as soon as possible.

The meeting log is as follows (all times are CEST real time at the meeting):


[11:08am] GaborHojtsy: https://www.drupal.org/node/2555183
[11:08am] Druplicon: https://www.drupal.org/node/2555183 => Fix the filled update tests, they are broken [#2555183] => 60 comments, 10 IRC mentions
[11:08am] GaborHojtsy: https://www.drupal.org/node/2555665
[11:08am] Druplicon: https://www.drupal.org/node/2555665 => When index is added for content_translation_uid, the corresponding stored schema definition is not updated [#2555665] => 30 comments, 7 IRC mentions
[11:09am] plach: https://www.drupal.org/node/2542748
[11:09am] Druplicon: https://www.drupal.org/node/2542748 => Automatic entity updates can fail when there is existing content, leaving the site's schema in an unpredictable state [#2542748] => 184 comments, 38 IRC mentions
[11:10am] plach: https://www.drupal.org/node/2558905
[11:10am] Druplicon: https://www.drupal.org/node/2558905 => Content translation module - Information disclosure by insufficient access checking [#2558905] => 9 comments, 3 IRC mentions
[11:11am] plach: https://www.drupal.org/node/2555665
[11:11am] Druplicon: https://www.drupal.org/node/2555665 => When index is added for content_translation_uid, the corresponding stored schema definition is not updated [#2555665] => 30 comments, 8 IRC mentions
[11:13am] WimLeers: https://www.drupal.org/node/2429617#comment-10256775
[11:13am] Druplicon: https://www.drupal.org/node/2429617 => Make D8 2x as fast: SmartCache: context-dependent page caching (for *all* users!) [#2429617] => 265 comments, 34 IRC mentions
[11:13am] WimLeers: https://www.drupal.org/node/2556889
[11:13am] Druplicon: https://www.drupal.org/node/2556889 => [policy, no patch] Decide if SmartCache is still in scope for 8.0 and whether remaining risks require additional mitigation [#2556889] => 62 comments, 4 IRC mentions
[11:19am] alexpott: xjm: https://www.drupal.org/node/2558791
[11:19am] Druplicon: https://www.drupal.org/node/2558791 => !placeholder should Xss::adminFilter but not affect safeness [#2558791] => 11 comments, 1 IRC mention
[11:20am] alexpott: xjm: your issue might be a duplicate
[11:26am] WimLeers: plach: https://www.drupal.org/node/2558905#comment-10267715
[11:26am] Druplicon: https://www.drupal.org/node/2558905 => Content translation module - Information disclosure by insufficient access checking [#2558905] => 9 comments, 4 IRC mentions
[11:28am] plach: WimLeers: replied
[11:33am] jibran: https://www.drupal.org/node/2538108
[11:33am] Druplicon: https://www.drupal.org/node/2538108 => Add an API for data value updates to reliably run after data format updates [#2538108] => 19 comments, 4 IRC mentions
[11:46am] WimLeers: https://www.drupal.org/node/2557815#comment-10266477
[11:46am] Druplicon: https://www.drupal.org/node/2557815 => Automatically assign node grants cache context in node_query_node_access_alter() [#2557815] => 17 comments, 2 IRC mentions
[11:53am] jibran: https://www.drupal.org/node/2538108
[11:53am] Druplicon: https://www.drupal.org/node/2538108 => Add an API for data value updates to reliably run after data format updates [#2538108] => 19 comments, 5 IRC mentions
[11:55am] WimLeers: https://www.drupal.org/node/2464427
[11:55am] Druplicon: https://www.drupal.org/node/2464427 => Replace CacheablePluginInterface with CacheableDependencyInterface [#2464427] => 176 comments, 27 IRC mentions
[11:55am] jibran: https://www.drupal.org/node/2538108
[11:55am] Druplicon: https://www.drupal.org/node/2538108 => Add an API for data value updates to reliably run after data format updates [#2538108] => 19 comments, 6 IRC mentions
[11:56am] xjm: Is that another update path test we need? a test contrib module?
[12:05pm] • xjm finds herself wondering if plach hears churchbells again :)
[12:05pm] plach: xjm: I'm doing right now :)
[12:05pm] xjm: :D
[12:13pm] xjm: Given the complexity here, I find myself wondering how on earth it was we ever expected this to work for major version upgrades :) Thank goodness for migrate

Aug 28 2015
Aug 28

We met again last Friday to discuss critical issues blocking Drupal 8's release (candidate). (See all prior recordings). Here is the recording of the meeting video and chat from last Friday in the hope that it helps more than just those who were on the meeting:

[embedded content]

If you also have significant time to work on critical issues in Drupal 8 and we did not include you, let me know as soon as possible.

The meeting log is as follows (all times are GMT real time at the meeting):


10:12 plach entity updates issue: https://www.drupal.org/node/2542748
10:12 Druplicon https://www.drupal.org/node/2542748 => Automatic entity updates can fail when there is existing content, leaving the site's schema in an unpredictable state [ #2542748] => 152 comments, 31 IRC mentions

10:25 alexpott https://www.drupal.org/node/2554151
10:25 Druplicon https://www.drupal.org/node/2554151 => Test content/configuration in update database dump [#2554151] => 23 comments, 2 IRC mentions

10:32 WimLeers https://www.drupal.org/node/2554233
10:32 Druplicon https://www.drupal.org/node/2554233 => Port Cross-site Request Forgery - Form API fixes from SA-CORE-2015-003 to Drupal 8 [#2554233] => 26 comments, 1 IRC mention

10:33 larowlan plach: https://www.drupal.org/node/2542748#comment-10244733 point 2 - I think that's a c/p error
10:33 Druplicon https://www.drupal.org/node/2542748 => Automatic entity updates can fail when there is existing content, leaving the site's schema in an unpredictable state [#2542748] => 152 comments, 33 IRC mentions

10:34 plach larowlan: definitely :)
10:34 plach thanks for catching that

10:42 alexpott https://www.drupal.org/node/2497243
10:42 Druplicon https://www.drupal.org/node/2497243 => Replace Symfony container with a Drupal one, stored in cache [#2497243] => 245 comments, 53 IRC mentions

10:44 WimLeers dawehner: "we're in the middle of nowhere of the DrupalKernel" — that sounds bizarre :D

10:53 alexpott https://www.drupal.org/node/2464427
10:53 Druplicon https://www.drupal.org/node/2464427 => Replace CacheablePluginInterface with CacheableDependencyInterface [#2464427] => 175 comments, 25 IRC mentions

10:59 dawehner jibran: new \Drupal\views\Entity\View();
11:03 jibran UpgradePath--
11:03 jibran UpgradePath--
11:03 jibran UpgradePath--
11:03 jibran UpgradePath--
11:09 WimLeers jibran: hahahaha
11:09 WimLeers jibran++
11:09 pfrenssen jibran: lol :D
11:10 WimLeers alexpott: amazingly, *during* our call, pretty much every SafeMarkup issue has been updated!
11:10 WimLeers stefan_r++

Aug 28 2015
Aug 28

Let’s talk about Drupal web development with love :) Check out the blog post from our guest blogger Daniel Mattei about why Google loves Drupal.

Drupal is an open source content management platform, which makes the framework of websites around the world. It is free and constantly under development to make sure that its technology is cutting-edge. The websites supported on Drupal make up about 2.1% of the total online site arena. These sites range from blogs, corporate sites, business and even government sites. They experience increased traffic on a daily basis propelled by the excellent features on Drupal.

Drupal came online in 2001 after which the number of users increased drastically. It has since maintained and even grown that pace over the years. The sites supported by Drupal have risen to 1,000,000 and counting.

Search engines like Google prefer this framework since it is easy to index the keywords in articles posted on different sites. Combined with the high quality SEO content, the rankings for Drupal sites are generally higher in the search results. With that said, most sites using it achieve and maintain the major objective of improving traffic.

Here are 6 reasons why you’ll love Drupal:

1. Powerful framework

Drupal is a safe way to save site templates for web designers and has the potential for top ranking search results for site owners. The framework is strong enough to handle virtually any site and enables the user to manage content effectively. The high performance is credited to its built-in, scalable databases and InnoDB. It even incorporates third party applications.

2. Flexible themes

The themes available on Drupal look and feel solid and secure. One can easily update the features with ease. The themes are completely responsive on different devices, like mobile phones, tablets, and desktops. For most internet users, the look of the site and flexibility on different devices is a key determinant to whether they stay on the site or leave. Having this feature work is crucial to the success of any modern site.

Site customization

Customizing a site is crucial for an owner to make their content stand out. This task is easy to accomplish on Drupal sites since it has numerous customizations. You can make changes through modules or plug-ins and even change the entire template if necessary. The customization tools provided are fully functional.

3. Search engine friendly

The Drupal CMS works very well with all search engines, and that is why it is one of the most loved site platforms available. It has a URL structure that allows you to build your URL the way you want it. When you upload articles to your site, you can allocate a folder for each article and link it to a selected URL; it is easier to find specific articles in a folder of so many. It may seem irrelevant but most users see the URL on the search as an orientation tool in the site.

The rankings on search results change daily, but sites supported by Drupal manage to stay on the top 10 on the search results. This makes it one of the most effective marketing software available. Google may not have stated this but it should be one of the reasons Google loves Drupal.

4. Trustworthy

Numerous sites run on Drupal both small and large, but notably, it supports sites to some of the largest names like MTV UK, The Grammy Awards and even the US White House. It’s safe to trust Drupal with your clients’ sites, your company’s website, or even your personal blog. All the facts considered it’s proven to be a reliable platform.

5. Free, safe and secure

Drupal is an open source system and it is free. The open source aspect would normally mean that CMS’s are an open book where users can view each other’s codes and assess the security of the codes. Drupal has a very secure system, actively scanned for vulnerabilities by its team of experts. The fact that it is an open source also means that it is free to download and use it with the web designer you pick. There is no maintenance or licensing fees when using Drupal or getting updates of the latest version.

6. Drupal is innovative

Bi-annually, there are conferences organized by Drupal to help assemble new ideas and innovations to make the system better. Discussing new ways to fix the flaws of a product are crucial in advancing the user experience and in return the ratings. These conferences also bring together great minds that share information hence providing a networking forum for the users. The upgrades are made by a team of experts that are located worldwide.

Running your website through Drupal is a great choice for e-commerce. You can access the latest version of Drupal on its website and upload your information into folders. In a matter of minutes it is up and ready.

Authoured by: Daniel Mattei (@mattedt) is a web Marketing Coordinator at Dynamic Search and a filmmaker and founder of Shotlight Productions. He lives with his wife, Grace, and Pomeranian, Couscous in Phoenix, Arizona.

Aug 28 2015
Aug 28

In my previous post I outlined how to build a Sass directory within a custom Drupal theme including Bourbon and Neat.

At this point, we’re ready to write some SCSS within the base, components, and layouts directories. In this post I’ll demonstrate how Savas applies SMACSS principles to organize our custom SCSS. As a reminder, I’ll be linking to our Drupal 8 mapping site as an example throughout, but none of this is Drupal-8-specific.

Drupal-flavored SMACSS

When we left off, our sass directory looked like this:

# Inside the custom theme directory
sass
??? _init.scss
??? base
??? components
??? layouts
??? lib
?   ??? bourbon
?   ??? font-awesome
?   ??? neat
??? styles.scss

At this point we’re ready to start styling. Let’s take a look at the three folders that will hold our custom .scss files, which are loosely based on SMACSS. Acquia has a nice writeup of how SMACSS principles can be applied to Drupal, but I like to simplify it even further.

Base

I personally only have three files in the sass/base directory. Don’t forget that we already imported these three partials in styles.scss.

For full examples of each of these files, check out our base directory.

_normalize.scss

This is simply normalize.css renamed as _normalize.scss - remember that CSS is valid SCSS. Thoughtbot recommends using normalize.css as your CSS reset along with Neat. Regardless of which reset you use, include it in base.

_base.scss

This is for HTML element styles only. No layout, no classes, nothing else. In here I’ll apply font styles to the body and headings, link styles to the anchor element, and possibly a few other site-wide styles.

_variables.scss

This is where I house all of my Sass variables and custom mixins. I typically have sections for colors, fonts, other useful stuff like a standard border radius or spacing between elements, variables for any Refills I’m using, and custom mixins.

I’d definitely recommend including _normalize.scss in base if you’re using Neat, but other than that do what works for you! If you’re following my method, your sass folder should be looking like this:

# Inside the custom theme directory
sass
??? _init.scss
??? base
?   ??? _base.scss
?   ??? _normalize.scss
?   ??? _variables.scss
??? components
??? layouts
??? lib
?   ??? bourbon
?   ??? font-awesome
?   ??? neat
??? styles.scss

Layouts

This directory holds page-wide layout styles, which means we’ll be making heavy use of the Neat grid here. This is flexible, but I recommend a single .scss partial for each unique template file that represents an entire page. Think about what works best for your site. For the sake of our example, let’s say we’re creating _front-page.scss and _node-page.scss. I like to also create _base.scss for layout styles that apply to all pages.

Remember that these styles only apply to the page’s layout! I occasionally find myself moving styles from the layouts directory to base or components when I realize they don’t only define layout. In these partials, you should be doing a lot of grid work and spacing. This is the entirety of my sass/layouts/_base.scss file on our mapping site:

/**
 * @file
 *
 * Site-wide layout styles.
 */

body {
  @include outer-container();

  main {
    @include span-columns(10);
    @include shift(1);
    @include clearfix;

    h1 {
      margin-top: em($navigation-height) + $general-spacing;
    }
  }
}

We’re almost there:

# Inside the custom theme directory
sass
??? _init.scss
??? base
?   ??? _base.scss
?   ??? _normalize.scss
?   ??? _variables.scss
??? components
??? layouts
?   ??? _base.scss
?   ??? _front-page.scss
?   ??? _node-page.scss
??? lib
?   ??? bourbon
?   ??? font-awesome
?   ??? neat
??? styles.scss

Components

In SMACSS this is called “modules,” but that gets a little confusing in Drupal Land. This is for applying layout and theme styles to smaller chunks of your site, which in Drupal typically means regions. Create a separate partial for each region, or if you have several distinct components within a region, consider a separate partial for each of them.

Let’s say we created partials for the header, footer, and sidebar regions, plus one for non-layout node page styles. At this point, our sass directory is looking like this:

# Inside the custom theme directory
sass
??? _init.scss
??? base
?   ??? _base.scss
?   ??? _normalize.scss
?   ??? _variables.scss
??? components
?   ??? _node-page.scss
?   ??? regions
?       ??? _footer.scss
?       ??? _header.scss
?       ??? _sidebar.scss
??? layouts
?   ??? _base.scss
?   ??? _front-page.scss
?   ??? _node-page.scss
??? lib
?   ??? bourbon
?   ??? font-awesome
?   ??? neat
??? styles.scss

Now we’ve got a nicely organized, easy to navigate Sass directory, ready to hold your styles and compile them into one beautiful CSS file!

But how do we ensure that our one CSS file really is beautiful? Check in next week when I talk about best practices for writing Sass that you can easily maintain or pass off to another developer.

About the author

Anne Tomasevich

Recent posts by Savas

Drupalcamp Asheville - an all around success!

A step-by-step tutorial on setting up Bourbon and Neat and compiling it all with Compass.

We’re giving two presentations at Drupalcamp Asheville!

Aug 27 2015
Aug 27

Security is very hard to bolt on to any software or product after it has been built. Building it into the core of the code helps to avoid mistakes, and thus the upcoming release of Drupal 8 tries to build in more security by default, while still being usable for developers and site builders. This list of 10 security improvements is not exhaustive - some are just a line or two to handle an edge case, and there are others I may have overlooked. I've contributed to a number of these improvements, but they reflect overall the community consensus as well as reactions to problems that required security releases for Drupal core or contributed modules in the past. For each point I've tried to include a link or two, such as the Drupal core change record, a documentation page, or a presentation that provides more information. Some of these may also be possible to back-port to Drupal 7, to benefit you even sooner. A "7.x back-port" link indicates that.

For context on why these 10 improvements are important, I looked at past security advisories (SAs) as well as considering the kind of questions we get here at Acquia from companies considering adopting Drupal. In terms of past SAs, cross-site scripting (XSS) is the most commonly found vulnerability in Drupal core and contributed modules and themes.

  • Twig templates used for html generation

    This is probably first on the list of anyone you ask about Drupal 8 security. This is also one of the most popular features with themers.??

    One security gain from this is that it enforces much stricter separation of business logic and presentation – this makes it easier to validate 3rd party themes or delegate pure presentation work. You can't run SQL queries or access the Drupal API from Twig. ???

    ??In addition, Drupal 8 enables Twig auto-escaping, which means that any string that has not specifically flagged as safe will be escaped using the PHP function htmlspecialchars() (e.g. the same as Drupal 7 check_plain()). Auto-escaping of variables will prevent many XSS vulnerabilities that are accidentally introduced in custom site themes and custom and contributed modules. That fact is why I ranked this as number one. XSS is the most frequent security vulnerability found in Drupal code. We don't have a lot of hard data, but based on past site audits we generally assume that 90% of site-specific vulnerabilities are in the custom theme.?

    To see why themers love Twig, compare the Drupal 7 block.tpl.php code to the Drupal 8 Twig version.

    Drupal 7 block.tpl.php:

    Drupal 7 block.tpl.php

    Drupal 8 block.html.twig:

    Drupal 8 block.html.twig

  • Removed PHP input filter and the use of PHP as a configuration import format

    OK, maybe this should have been number one. Drupal 8 does not include the PHP input format in core. In addition to encouraging best practices (managing code in a revision control system like git), this means that Drupal no longer makes it trivial to escalate an administrator login to being able to execute arbitrary PHP code or shell commands on the server. ?

    For Drupal 7, importing something like a View required importing executable PHP code, and for certain custom block visibility settings, etc. you would need to enter a PHP snippet. These uses of evaluated PHP (exposing possible code execution vulnerabilities) are all gone – see the next point about configuration management.?

    Now that we have covered the top two, the rest of the 10 are in rather arbitrary order.

  • Site configuration exportable, manageable as code, and versionable

    The Configuration Management Initiative (CMI) transformed how Drupal 8 manages things that would have been represented in Drupal 7 as PHP code. Things like Drupal variables or ctools exportables (e.g. exported Views).??

    CMI uses YAML as the export and import format and the YAML files can be managed together with your code and checked into a revision control system (like git). ?

    Why is this a security enhancement? Well, in addition to removing the use of PHP code as an import format (and hence possible code execution vulnerability), tracking configuration in code makes it much easier to have an auditable history of configuration changes. This will make Drupal more appealing and suitable for enterprises that need strict controls on configuration changes in place. In addition, configuration can be fully tested in development and then exactly replicated to production at the same time as any corresponding code changes (avoiding mistakes during manual configuration).? Finally, it is possible to completely block configuration changes in production to force deployment of changes as code.?

  • User content entry and filtering improved

    While the integration of a WYSIWYG editor with Drupal core is a big usability improvement, extra care was taken that to mitigate poor practices that adding a WYSIWYG editor encouraged in past Drupal versions. In particular, users with access to the editor were often granted access to the full html text format, which effectively allowed them to execute XSS attacks on any other site user.??

    To encourage the best practice of only allowing the use of the filtered HTML format, the Drupal 8 WYSIWYG editor configuration is integrated with the corresponding text filter. When a button is added to the active configuration, the corresponding HTML tag is added to the allowed list for the text filter.?

    Drag a new button from the available to enabled section in the editor configuration:

    WYSIWYG editor configuration adding underline button

    The corresponding HTML tag (the U tag) is added to the allowed list:

    U tag is allowed in the filter

    An additional security improvement is that the core text filtering supports limiting users to using only images local to the site which helps prevent cross-site request forgery (CSRF) and other attacks or abuses using images.

  • Hardened user session and session ID handling

    There are three distinct improvements to session and session cookie handling.

    First, the security of session IDs has been greatly improved against exposure via database backups or SQL injection (7.x back-port ). Previously in Drupal, the session ID is stored and checked directly against the incoming session cookie from the browser. The risk from this is that the value from the database can be used to populate the cookie in the browser and thus assume the session and identity of any user who has a valid session in the database. In Drupal 8, the ID is hashed before storage, which prevents the database value from being used to assume a user's session, but the incoming value from the value is simply hashed in order to verify the value.?

    Next, mixed-mode SSL session support was added to core to support sites that, for example, used contributed modules to serve the login page over SSL while other pages unencrypted. You will have to replace the session handling service if you really need this. This encourages serving your entire site over SSL (which is also a search engine ranking boost).??

    The final change is that the leading “www.” is no longer stripped from the session cookie domain since that causes the session cookie to be sent to all subdomains (7.x back-port)

  • Automated CSRF token protection in route definitions

    Links (GET requests) that cause some destructive action or configuration change need to be protected from CSRF, usually with a user-specific token in the query string that is checked before carrying out the action.

    ??This change improves the developer experience and security by automating a process frequently forgotten or done incorrectly in contributed modules. In addition, centralizing the code makes it easier to audit and provide test coverage.

    Drupal 8 makes it easy. A developer merely needs to specify that a route (a system path in Drupal 7 terms) require a CSRF token. Here is an example of the YAML route definition for a protected link in Drupal 8 entity.

    entity.shortcut.link_delete_inline:
      path: '/admin/config/user-interface/shortcut/link/{shortcut}/delete-inline'
      defaults:
        _controller: 'Drupal\shortcut\Controller\ShortcutController::deleteShortcutLinkInline'
      requirements:
        _entity_access: 'shortcut.delete'
        _csrf_token: 'TRUE'
    

    Only the one line in the requirements: section needs to be added to protect shortcut deletion from CSRF.

    Shortcut inline delete link and corresponding URL with a token in the query string:

    Drupal page showing shortcut

  • Trusted host patterns enforced for requests

    Many Drupal sites will respond to a page request using an arbitrary host header sent to the correct IP address. This can lead to cache poisoning, bogus site emails, bogus password recovery links, and other problems with security implications.

    For earlier versions of Drupal, it can be a challenge to correctly configure the webserver for a single site that uses sites/default as its site directory to prevent these host header spoofing attacks. Drupal 8 ships with a simple facility to configure expected host patterns in settings.php and warns you in the site status report if it's not configured.

  • PDO MySQL limited to executing single statements

    If available, Drupal 8 will set a flag that limits PHP to sending only a single SQL statement at a time when using MySQL. This change would have reduced the severity of SA-CORE-2014-005 (a SQL injection vulnerability that was easily exploited by anonymous users) (7.x back-port)?. Getting this change into Drupal 8 meant I first had to contribute a small upstream change to the PHP language itself, and to the PDO MySQL library that is available in PHP versions 5.5.21 or 5.6.5 and greater.

    There is also a patch in progress to try to enforce this protection regardless of which specific database driver is being used.

  • Clickjacking protection enabled by default

    A small change, but Drupal 8 sends the X-Frame-Options: SAMEORIGIN header in all responses by default. This header is respected by most browsers and prevents the site from being served inside an iframe on another domain. This blocks so-called click-jacking attacks (e.g. forms or links on the site being presented in a disguised fashion on an attacker's site inside an iframe), as well as blocking the unauthorized re-use of site content via iframes. (7.x back-port).

  • Core JavaScript API Compatible with CSP

    Support for inline JavaScript was removed from the #attached property in the Drupal render API. In addition, the Drupal javascript settings variables are now added to the page as JSON data and loaded into a variable instead of being rendered as inline JavaScript. This was the last use of inline JavaScript by Drupal 8 core, and means that site builders can much more easily enable a strict content security policy (CSP) – a new web standard for communicating per-site restrictions to browsers and mitigating XSS and other vulnerabilities.

  • A final note of caution: The substantial code reorganization and refactoring in Drupal 8 as well as the dependence on third party PHP components does present a certain added risk. The code reorganization may have introduced bugs that were missed by the existing core tests. The third party components themselves may have security vulnerabilities that affect Drupal, and at the very least, we need to track and stay up to date with them and fix our integration for any corresponding API changes. In order to try to mitigate the risk, the Drupal Association has been conducting the first Drupal security bug bounty that has been run for any version of Drupal core. This has uncovered several security bugs and means they will be fixed before Drupal 8 is released.

    I am excited that we've added more “security by default” to Drupal 8, and I hope you download and try it out so you are ready to start using it for new projects as soon as it's released.

    Aug 27 2015
    Aug 27

    I've spent most of this summer working on the Drupal module called Security Review. My project was porting it to Drupal 8 as part of Google Summer of Code 2015. I'm happy to say that the requirements have been met long before the end of the programme, so there was no rush at the end of the coding period.

    How it all started

    It all started with a simple Facebook post in my faculty's FB group. I didn't even notice it as I was too busy learning for a midterm, but thankfully my friends were kind enough to procrastinate at the time and showed me the link to GSoC. It didn't take long until I found that Drupal would be a perfect candidate for me, even without any experience related to it. So I took a leap of faith and started writing a proposal for the project that I liked most, "Port security_review to Drupal 8". I liked the cause (eliminate security vulnerabilites from misconfiguration), the freedom of designing a new architecture from scratch and the GSoC t-shirt I hope I will soon receive.

    Preparation for GSoC

    Drupal requires GSoC student candidates to complete the ladder called Getting Started with Drupal for GSoC Students. This is really a necessity as it teaches the basics which students will need numerous times during working on Drupal.

    Finishing the ladder, I've tried to get a mentor for my project as it didn't have one, and who could be better than the module's owner!? So I went ahead and contacted coltrane, who then shortly accepted to be the mentor of the project. He is pretty awesome and helpful, I really enjoyed working with him.

    Writing a good proposal might have been the hardest part of the whole project, so I advise every future student to take their time to work out a really good one. There are links to a lot of resources in the Google Summer of Code Drupal group that were really helpful, so I highly recommend future students to read everything they can find there.

    After the proposal

    Days went by and finally the accepted projects were announced and I could see my name in the list. Of course I celebrated the event properly, but soon I had to realize that all of this won't be easy. Finals here in Hungary started on 25th May... yes, the same as the coding period. So I went ahead and did a little work on the module before finals so that I would be able to concentrate on my studies on the first week. I was soon ready with some parts of the module that meant 1-2 weeks worth of work according to my proposal, so all I had to focus on were my finals. Writing 4 exams in 1 week and passing all of them is very hard and I don't recommend it to anyone as the stress levels get way too high, but I somehow managed to do it.

    Starting the work on the second week I was so relieved that my summer had finally started and I could do what I was waiting for: coding. Of course GSoC is not just programming, there are meetings students have to attend: one every week with the organization admins (we could choose from 2 meetings, whichever worked best in our timezone) and one or more with our mentor(s). I've had all my meetings on tuesdays so that I could work more flexibly on the other days. Another thing that is required that does not involve coding is maintaining a blog. Students have to write a blog post every week about their progress in a way that anyone who is not familiar with their project or GSoC will be able to understand it, also it should be written in a Drupal Planet compatible way, so the word about GSoC can be spread.

    My task was mostly doing what I wrote in the proposal's timeline, but sometimes I had to solve issues posted on my GitHub (by my mentor) and also in the Drupal.org issue queue (by the community). In the first couple of weeks I did 10-12 hours of work a day and needless to say that got me ahead of my schedule fast. Soon came the midterm evaluation and I was about 75% done with the project. The evaluation itself didn't require much interaction from my part, I just had to fill a short questionnaire about my progress and my thoughts about the project and my mentor.

    The second coding period went much slower. On average I think it's safe to say that I did no more 20-30 hours of work per week. Slow weeks may sound nice at first, but aren't actually enjoyable. Still, the module got finished around week 9 or 10 and the last few weeks were spent with polishing it and looking for ways to improve it.

    The results

    What I learnt

    Before GSoC I had, let's say, pretty limited knowledge about Drupal. All I knew is that it exists. Now I'm familiar with how to operate a Drupal website, how to write modules for Drupal 7 and 8 that don't just work, but also use the technologies provided by Drupal. By learning Drupal 8 one can learn a bit about Symfony 2 too, as D8 uses a lot of S2 components.

    After GSoC 2015

    I have plans for Security Review 8.x-2.x, I also wish to have time to make a Drupal based website for myself to get familiar with site building using Drupal. So in conclusion I will definitely keep working with and on Drupal in the future.

    Thanks

    I would like to thank Slurpee and cs_shadow for dedicating their valuable times for the weekly check-in meetings that sometimes took hours and a huge thanks for Ben Jeavons (coltrane) for providing fast and valuable help and an amazing summer! Also I would like to thank drupalize.me for the free membership, it was pretty useful, I wish I started to use it sooner. And last but not least I would like to thank the Google Summer of Code organizers for the opportunity and the amazing experience.

    Aug 27 2015
    Aug 27

    Global Training Days last weekend was a great success. There were 33 hosts from 21 countries who stepped up to introduce new people to Drupal in both half and full day sessions.

    [embedded content]

    Drupal Global Training Day, Drupak, Peshawar Pakistan from Azmat Shah on Vimeo.

    Thank you to the training companies, local groups, and site hosts who made the event possible. We were particularly excited to host a training at the Drupal Association office and we have to thank Gregory Boggs of ThinkShout for leading the full day training. Thanks to Gregory's good work, I started my week with a note from an attendee that said "I learned a lot, all while having a wonderful time!" It doesn't get much better than that.

    Check out the photos and updates at #DrupalGTD on Twitter. See the full list on our GTD 2015 page along with reports from the trainers as they come in.

    We have one more GTD weekend this year: November 14th-15th. Join the 17 hosts who have already committed to train new Drupalers at https://assoc.drupal.org/sign-participate-drupal-global-training-days. Give a training in your community to get everyone started off in the right direction with Drupal.

    Aug 27 2015
    Aug 27

    Photo by Myles Brawer

    As it says on the t-shirt, I’M NOT HIM.

    Okay, I know I look a lot like Howard Stern.

    And yes, I spent a pleasant hour chatting with him and Robin on his show that one time. (The video is somewhere on YouTube, but don’t ask.)

    And yes, I auditioned for America’s Got Talent. (Three thumbs-up votes, one thumbs-down.)

    And okay, yes, I’ve obligingly posed for thousands of selfies with Stern-fans.

    But I’M NOT HIM! I’m not leading a double-life as Drupal Watchdog editor and the King of All Media.

    Yes, but what if...?

    So here’s a spoof Bob Williams and I made during DrupalCon Los Angeles. Yeah, I know, the audio on the elevator kinda sucks, but the acting!

    The acting – and Ronnie Ray’s Drupal expertise.

    (Photo by Myles Brawer)

    Aug 27 2015
    Aug 27

    Drupal project lead and Acquia co-founder Dries Buytaert recently blogged about the one-year anniversary of Acquia’s certification program, which seeks to validate skills and knowledge that focus on open source Web development and Acquia products and services.

    The topic of certification has long been a controversial one within the Drupal community. As an open source project that primarily measures achievement by one's contributions, some have questioned the need for developers with an established track record in the community to prove themselves through certification. Others are skeptical that the quality or skills of a developer can be judged by the results of a sixty-question multiple choice test.

    Certification blog post image

    Those arguments, while completely valid, miss the larger point.

    Over the last few years, Drupal has become one of the leading content management platforms for high-traffic sites, powering nearly 15% of the top ten thousand CMS-backed sites on the Web. Large companies and organizations are increasingly evaluating Drupal against commercial and proprietary options like Adobe Experience Manager and SiteCore.

    And for those enterprise evaluators, as well as influential research analysts like Forrester and Gartner, the presence of a robust commercial ecosystem surrounding a software platform is a strong indicator of its strength. One of the ways that those ecosystems are evaluated is by the presence of well-regarded and widely adopted certification programs, like the one that Acquia is working to build.

    Those of us who have been involved with the Drupal project and community for years understand that the strength of open source software has less to do with its commercial ecosystem than it does with the level of engagement of its contributor community. We know this because we work with and alongside those contributors every single day. But that’s not the experience that most of our customers have; their perspective is more likely to be informed by the companies with whom they work.

    And because Drupal is now increasingly competing against large commercial entities instead of other open source projects, those companies can no longer rely solely on their community experience and contributions to make the case for an open source solution. That experience can and should be an important factor in the evaluation process, but all too often other qualifications are necessary.

    The value that open source software brings to the table isn't always apparent to those used to proprietary solutions. Acquia's certification program aims to surface that value by leveling the playing field and offering evaluators more of an apples-to-apples comparison. From that perspective, certification is less about the knowledge and skills of individual developers than it is about the investment made by companies into competing for large projects against other enterprise vendors.

    Acquia's Certified Developer exam tests developers’ base level of familiarity with Drupal’s features and functionality, but in our experience that has little to do with their skills as developers, which is something that no multiple choice test can measure. Developers get better by working alongside other talented developers in an environment that promotes professional growth and development, which is what we try to build every day at Palantir. We demonstrate those skills to prospective customers both through our past experience and by demonstrating the approaches we take to solving our customers’ problems.

    We don't need our developers to pass certification exams to know that they're awesome, and no matter how good a certification program might be, it’s still incumbent on evaluators to do their due diligence when picking who they want to work on their next project.

    So if all that’s true, why have certified developers at all? The answer is going to be different for different people, but for us, it’s about making sure that customers understand that Palantir is willing and able to tackle large projects that might otherwise go to proprietary vendors by default. Some prospective customers have existing relationships with Acquia, and in addition to being an Acquia partner, having Acquia Certified developers on our team provides them with the justification they need to know that we're familiar with the products and services that they offer.

    At the end of the day, the rise of certification programs like the one offered by Acquia are yet another example of Drupal’s growth as a project and as a community. Very few open source projects are strong enough to compete against proprietary enterprise solutions, but Drupal does it every day, delivering value to customers of all sizes and shapes. We're proud to be a part of it.

    I’ll be talking more about Drupal certification and related topics next month in my DrupalCon Barcelona session, Architecting Drupal Business that are Built to Last. I’ve also proposed a session titled Building Tech Companies That Last for next year’s South by Southwest Interactive; voting is open through September 4.

    Aug 27 2015
    Aug 27

    In our last episode, we talked about the various ways of storing data in Drupal 8. One important point we noted was that "in the database" is not an option. All of Drupal's storage systems are abstractions above the actual data store. In fact, I will go as far as saying that if you ever write an SQL query yourself in Drupal 8, you're probably doing it wrong.

    There are two key reasons for that stance. One, there's no reason that any of those storage systems, conceptually, need to be in SQL. In fact, for Configuration, Key/Value, and the Cache, it's not even the best tool available. Any of them could be backed by MongoDB, Cassandra or Redis, instead. In fact, many sites will use one of those tools instead of SQL for some (but not all) data storage systems. If your module is hard-coded to SQL, you've now hard-coded all of your users to SQL only. And there's a good chance you've also hard-coded a specific SQL server (generally MySQL) without even intending to.

    D8FTW: Customizing your back-end blog post image

    The second reason is that as a module developer, you should be thinking at a higher level than rows and columns. Most of those systems offer a lot of automation and abstraction tools that provide more power with an easier syntax than SQL, and if you write your own SQL you are bypassing all of that. Most especially, if you have any module configuration not stored in the Configuration system it will not work with any staging and deployment tools. Don't do that to your users.

    If for some reason you must write a custom query, say for performance, there is a supported, flexible way to do so. First, ensure that your query is contained within a service, and that service conforms to a declared interface. (You should be doing that anyway, but it's especially important here.) For example, let's say we're creating a service that finds nodes by some highly complex logic that normal Entity Queries don't support. We'll call the class DatabaseComplexNodeFinder, with a ComplexNodeFinderInterface. When we register that service in the container, we should also tag it as one that allows its backend to be overridden, like so:

    mymodule.services.yml:

    services:
    mymodule.nodefinder:
      class: Drupal\mymodule\DatabaseComplexNodeFinder
      arguments: ['@database']
      tags:
       - { name: backend_overridable }

    And then we use that service wherever we need to use that logic. The "backend_overridable" tag tells Drupal that there may be alternate implementations it should look for. By default, the class should be written to use generic, non-engine-specific SQL. (That is, no MySQL or PostgreSQL specific features.) It doesn't have to be fast, just work.

    Now comes the fun part. We can also define another service named mysql.mymodule.nodefinder, which has the same interface but is very specific to MySQL. Similarly, we can have a service named pgsql.mymodule.nodefinder or mongodb.mymodule.nodefinder, which would be specific to PostgreSQL or MongoDB, respectively. Just registering those services in the container has virtually no cost if they're not used. Those alternate services can have whatever code in them they want, and any set of dependencies they want, as long as they follow ComplexNodeFinderInterface.

    Now, in the sites/default/services.yml file, a site owner can specify an alternate default backend:

    parameters:
    default_backend: mysql


    The default is mysql, which means that if Drupal finds a mysql version of any "backend_overridable" service, it will use that instead of the generic one. If it doesn't, it just uses whatever is registered by default. (Often times an SQL-database-specific version will be unnecessary, but the capability is there if you need it.) If your site is running on PostgreSQL, change that default_backend to "pgsql". If on MongoDB, set it to "mongodb". And so on. What if we want to use something other than the default? For instance, we're on a mostly-MySQL-based site but we want to use MongoDB for the State system? That's another simple toggle in the services.yml file. To change the backend for our nodefinder service, we would simply add this to the site-specific services.yml file:

    That tells the container to use the MongoDB-specific version of that service instead of whatever it was going to use.
    There are two big advantages of this design:
    1) As a module developer, you can optimize your module for MySQL, PostgreSQL, or MongoDB at the same time. Even if you don't, any other module is free to provide an alternate backend by just registering a service with the correct name.
    2) As a site owner, you can mix and match what backend services you want to use. Want a mostly-MySQL-based site, but with Redis for the lock and caching systems? Go for it. Want to store your entities in SQL but everything else in MongoDB? You can do that. Any well-written module will keep on working just fine, because it's either using Drupal's higher-level abstractions or using swappable backends. And if the backend you're looking for isn't available for that service, there's only one class that needs to be written to make it available.
    That's the power of dependency injection.

    services:
    mymodule.nodefinder:
      alias: mongodb.mymodule.nodefinder

    Aug 27 2015
    Aug 27

    Securing your siteThese days, using SSL with your website isn’t just a good idea — it’s essentially a requirement. Encrypting the information that’s sent between visitors’ browsers and your website is the new price of doing business.

    Fortunately, Acquia has a lot of experience helping to secure websites, and we’ve collected several of these tips into a best practices article on the Acquia Help Center.

    Want to know about using Varnish with SSL (and you’re an Acquia Cloud user)?

    It’s in there.

    Want to ensure that all of your website’s assets are served to visitors using the HTTPS protocol?

    It’s in there.

    Want to set up your 301 redirects from your HTTP pages to HTTPS?

    Surprise! It’s in there.

    For more information on how best to use SSL with your website, visit the article and read for yourself.

    And for even more information that you can use with your Drupal website, feel free to browse the articles and resources on the Acquia Help Center.

    Aug 27 2015
    Aug 27

    Mediacurrent Dropcast: Episode 10

    This episode we have Mario Hernandez, front end developer at Mediacurrent, to talk about his upcoming talks at DrupalCamp LA, and how to properly plan for giving a presentation. We talk about the smart_trim module in our Pro Project Pick, which is an awesome module. We talk about Drupal 8 news and as always, birthday boy Ryan, brings it home with the Final Bell. Also, Mark starts his run for President of these United States.


    Episode 10 Audio Download Link

    Updates:

    Mediacurrent Blog Mentions:

    • The best (and worst) question in a Drupal sales presentation by Josh Linard VP of Sales
      • Best and worst question on a sales presentation is   “Why should we hire your company instead of the other organizations we're evaluating?"
      • Lets Mediacurrent showcase their strengths - Our people , Our work, & Our culture
      • Always be prepared to answer that question for anyone in the organization
    • Why you should speak at Tech Conferences by Mario Hernandez - Sr Front End Developer
      • Share your knowledge with the tech community
      • Learn to speak in public
      • Network and meet a lot of good folks
      • Lots of good tips - Where to speak, What topics to present, Preparation time

    Guest: Mario Hernandez

    MailDrop:

    • Daniel from Dartmouth says we embarrassed him, so lets do that again
    • Jim Birch says thanks for talking about his article

    Pro Project Pick:

    Article:

    This week in Drupal 8:

    The Final Bell:

    • Drupal 101: Theming Drupal 7 with gulp

      • By Chen Hui Jing
      • “In a nutshell, when we do front-end development, there are certain actions or tasks that we do repeatedly. Like the aforementioned furious browser-reloading. Sometimes, we also use Sass, which needs to be compiled. When we write Javascript, best practice implores us to concatenate and minify our scripts (for production). Lots of stuff to take care of. Rather than have to do all that manually, task-runners like Grunt and gulp can do them automatically whenever we save our working files. So that’s what everyone is talking about when they say automating your workflow.”
    • How To Write A Great Commit Message

      • By Mark Dorison

    • Wait, $langcode? What the Heck?

      • By Francesco Placella (Pronounced “Plo-chella”)
      • A look at multilingual content in Drupal
    Aug 27 2015
    Aug 27

    Autoloading in D8 is much more convenient that in previous versions, however, it still has limitations. One such issue is with hook_requirements(), which is supposed to be present in the module install file, not the module itself: when called at runtime for the site report page, the module is loaded and the PSR/4 autoloader works fine. However, when that hook is fired during install to ensure the module can indeed be enabled, the module is not yet enabled, and the autoloader is not yet able to find code from that module, meaning the hook_requirements('install') implementation cannot use namespaced classes from the module, as they will not be autoloadable. What are the solutions ?

    The bad
    The first solution is obvious but painful : since the file layout within the module is known at the time of committing, it is possible to avoid autoloading using require_once for each class/interface/trait needed by the code, typically like this:

    <?php
    // to male \Drupal\mymodule\Some\Namespace\Class available in mymodule_requirements().
    require_once __DIR__ . '/src/Some/Namespace/Class.php';
    // ... for each such class
    ?>

    The good
    But there is a better way: just make the classloader aware of the module being installed:

    <?php
    // Not needed at runtime.
    if ($phase === 'install') {
     
    $module = 'mymodule';
     
    drupal_classloader_register($module, drupal_get_path('module', $module));
    }
    ?>

    During module enabling, its path is already known, so drupal_get_path can be used. With this little help, the module autoloaded code will be available during the install, and allow the hook_requirements() implementation to use it.

    The ugly

    One obvious temptation would be to put the hook_requirements() implementation in the module file, reasoning that, since if is in the module file, it implies that the module is available when the hook is fired. And indeed, this works for hook_requirements('runtime').

    However, during install, the module is still not loaded, so the implementation for hook_requirements('install') is simply not found and the requirements check is ignored. Don't do it.

    Aug 27 2015
    Aug 27

    The Drupal 8 Accelerate campaign has raised over two hundred and thirty thousand dollars ($233,519!!).  That's a lot of money! But our goal was to raise US$250,000 and we're running out of time. I've personally helped raise $12,500 and I'm aiming to raise 8% of the whole amount, which equals $20,000. I've got less than $7500 now to raise. Can you help me? Please chip in.

    Most of my colleagues on the board have contributed anchor funding via their companies. As a micro-enterprise, my company Creative Contingencies is not in a position to be able to that, so I set out to crowdfund my share of the fundraising effort.

    I'd really like to shout out and thank EVERYONE who has made a contribution to get me this far.Whether you donated cash, or helped to amplify my voice, thank you SO so soooo much. I am deeply grateful for your support.

    If you can't, or don't want to contribute because you do enough for Drupal that's OK! I completely understand. You're awesome. :) But perhaps you know someone else who is using Drupal, who will be using Drupal you could ask to help us? Do you know someone or an organisation who gets untold value from the effort of our global community? Please ask them, on my behalf, to Make a Donation

    If you don't know anyone, perhaps you can help simply by sharing my plea? I'd love that help. I really would!

    And if you, like some others I've spoken with, don't think people should be paid to make Free Software then I urge you to read Ashe Dryden's piece on the ethics of unpaid labor in the Open Source Community. It made me think again.

    Do you want to know more about how the money is being spent? 
    See: https://assoc.drupal.org/d8-accelerate-awarded-grants

    Perhaps you want to find out how to apply to spend it on getting Drupal8 done?
    See: https://assoc.drupal.org/d8-accelerate-application

    Are you curious about the governance of the program?
    See: https://www.drupal.org/governance/d8accelerate

    And just once more, with feeling, I ask you to please consider making a donation.

    So how much more do I need to get it done? To get to GAME OVER?

    • 1 donation x $7500 = game over!
    • 3 donations x $2500
    • 5 donations x $1500
    • 10 donations x $750
    • 15 donationsx $500 <== average donation
    • 75 donations x $100 <== most common donation
    • 100 donations x $75
    • 150 donations x $50
    • 500 donations x $15
    • 750 donations x $10 <== minimum donation

    Thank you for reading this far. Really :-)

    Aug 27 2015
    Aug 27

    In my previous post I outlined how to build a Sass directory within a custom Drupal theme including Bourbon and Neat.

    At this point, we’re ready to write some SCSS within the base, components, and layouts directories. In this post I’ll demonstrate how Savas applies SMACSS principles to organize our custom SCSS. As a reminder, I’ll be linking to our Drupal 8 mapping site as an example throughout, but none of this is Drupal-8-specific.

    Drupal-flavored SMACSS

    When we left off, our sass directory looked like this:

    # Inside the custom theme directory
    sass
    ??? _init.scss
    ??? base
    ??? components
    ??? layouts
    ??? lib
    ?   ??? bourbon
    ?   ??? font-awesome
    ?   ??? neat
    ??? styles.scss
    

    At this point we’re ready to start styling. Let’s take a look at the three folders that will hold our custom .scss files, which are loosely based on SMACSS. Acquia has a nice writeup of how SMACSS principles can be applied to Drupal, but I like to simplify it even further.

    Base

    I personally only have three files in the sass/base directory. Don’t forget that we already imported these three partials in styles.scss.

    For full examples of each of these files, check out our base directory.

    _normalize.scss

    This is simply normalize.css renamed as _normalize.scss - remember that CSS is valid SCSS. Thoughtbot recommends using normalize.css as your CSS reset along with Neat. Regardless of which reset you use, include it in base.

    _base.scss

    This is for HTML element styles only. No layout, no classes, nothing else. In here I’ll apply font styles to the body and headings, link styles to the anchor element, and possibly a few other site-wide styles.

    _variables.scss

    This is where I house all of my Sass variables and custom mixins. I typically have sections for colors, fonts, other useful stuff like a standard border radius or spacing between elements, variables for any Refills I’m using, and custom mixins.

    I’d definitely recommend including _normalize.scss in base if you’re using Neat, but other than that do what works for you! If you’re following my method, your sass folder should be looking like this:

    # Inside the custom theme directory
    sass
    ??? _init.scss
    ??? base
    ?   ??? _base.scss
    ?   ??? _normalize.scss
    ?   ??? _variables.scss
    ??? components
    ??? layouts
    ??? lib
    ?   ??? bourbon
    ?   ??? font-awesome
    ?   ??? neat
    ??? styles.scss
    

    Layouts

    This directory holds page-wide layout styles, which means we’ll be making heavy use of the Neat grid here. This is flexible, but I recommend a single .scss partial for each unique template file that represents an entire page. Think about what works best for your site. For the sake of our example, let’s say we’re creating _front-page.scss and _node-page.scss. I like to also create _base.scss for layout styles that apply to all pages.

    Remember that these styles only apply to the page’s layout! I occasionally find myself moving styles from the layouts directory to base or components when I realize they don’t only define layout. In these partials, you should be doing a lot of grid work and spacing. This is the entirety of my sass/layouts/_base.scss file on our mapping site:

    /**
     * @file
     *
     * Site-wide layout styles.
     */
    
    body {
      @include outer-container();
    
      main {
        @include span-columns(10);
        @include shift(1);
        @include clearfix;
    
        h1 {
          margin-top: em($navigation-height) + $general-spacing;
        }
      }
    }
    

    We’re almost there:

    # Inside the custom theme directory
    sass
    ??? _init.scss
    ??? base
    ?   ??? _base.scss
    ?   ??? _normalize.scss
    ?   ??? _variables.scss
    ??? components
    ??? layouts
    ?   ??? _base.scss
    ?   ??? _front-page.scss
    ?   ??? _node-page.scss
    ??? lib
    ?   ??? bourbon
    ?   ??? font-awesome
    ?   ??? neat
    ??? styles.scss
    

    Components

    In SMACSS this is called “modules,” but that gets a little confusing in Drupal Land. This is for applying layout and theme styles to smaller chunks of your site, which in Drupal typically means regions. Create a separate partial for each region, or if you have several distinct components within a region, consider a separate partial for each of them.

    Let’s say we created partials for the header, footer, and sidebar regions, plus one for non-layout node page styles. At this point, our sass directory is looking like this:

    # Inside the custom theme directory
    sass
    ??? _init.scss
    ??? base
    ?   ??? _base.scss
    ?   ??? _normalize.scss
    ?   ??? _variables.scss
    ??? components
    ?   ??? _node-page.scss
    ?   ??? regions
    ?       ??? _footer.scss
    ?       ??? _header.scss
    ?       ??? _sidebar.scss
    ??? layouts
    ?   ??? _base.scss
    ?   ??? _front-page.scss
    ?   ??? _node-page.scss
    ??? lib
    ?   ??? bourbon
    ?   ??? font-awesome
    ?   ??? neat
    ??? styles.scss
    

    Now we’ve got a nicely organized, easy to navigate Sass directory, ready to hold your styles and compile them into one beautiful CSS file!

    But how do we ensure that our one CSS file really is beautiful? Check in next week when I talk about best practices for writing Sass that you can easily maintain or pass off to another developer.

    About the author

    Anne Tomasevich

    Recent posts by Savas

    Drupalcamp Asheville - an all around success!

    A step-by-step tutorial on setting up Bourbon and Neat and compiling it all with Compass.

    We’re giving two presentations at Drupalcamp Asheville!

    Aug 26 2015
    Aug 26

    Drupal is an amazing platform for making websites, but it can also be a world-class API that can easily integrate with other technologies. In this class you will learn how to create fully featured APIs in Drupal, and you’ll build a simple Node.js application that consumes that API to make a highly interactive website.

    If you are looking to learn about building APIs in Drupal, or creating websites with Node.js, this class is for you!

    We will teach you to how to create strategies for success when building and launching your first decoupled Drupal project. To do this, we’ll talk about general API design concepts and best practices, dig into some code, and create a RESTful endpoint in Drupal. Once your API is complete, we’ll learn about best practices in Node.js, the keys to creating a fast and modular front end. You’ll interactively learn how to create a Node.js application using the popular Express framework, and then use that application to consume data from your new Drupal API. While creating your application, we’ll go over some benefits of using Node.js to consume Drupal APIs, and talk about other stacks that you might use. You’ll walk away with working knowledge on how you can build decoupled Drupal sites.

    Meet the Trainers from Four Kitchens

    • Matt Grill (drpal), Engineer at Four Kitchens
    • Patrick Coffey (pcoffey), Engineer at Four Kitchens

    This class is taught by Matt Grill and Patrick Coffey, engineers at Four Kitchens. They have worked together on presentations and trainings at previous DrupalCons and regional U.S. Drupal Camps. They are focused not only on teaching others to create decoupled Drupal stacks, but also on inspiring and enabling attendees to create and consume elegant APIs.

    Attend this Drupal Training

    This training will be held on Monday, 21 September from 09:00-17:00 at the Barcelona International Convention Center. The cost of attending this training is €500 + VAT and includes coffee and pastries before the training, lunch and coffee breaks. A DrupalCon ticket is not required to register to attend this event.

    Register Now

    Aug 26 2015
    Aug 26
    Tags: Drupal, fields

    Based on my presentations at DrupalCamp London, on Saturday 28th February 2015 and DrupalCamp Bristol, July 4th 2015

    Concept of a field

    Fields are the data entry points to a web application. Usually, they provide HTML elements and may be responsible for any manipulation of data before it goes into and comes out of the application. The data captured from a single field can be simple or complex.

    Assuming we want to create a field for country, all we need is a single HTML element - textfield or select options. An address field, on the other hand, is a collection of discrete data which may include standalone simple fields including a textfield representing postcode (provided by a core module) and a country field (maybe from a custom or contributed module).

    FieldsDrupalCampLondon2015-005.jpg

    In the Drupal world, when considering solutions the first phrase you may hear is, “there’s a module for that!”. However, for the task at hand, “you need a module for that!”. We are now going to write a module which provides this custom country field..

    To create a new field in Drupal 7, a number of hooks need to be implemented in a custom module and these include the following:

    • hook_field_info() - the field type definition as well as its settings.
    • hook_field_schema() - the database schema for the field structure.
    • hook_field_widget_info() - the widget types to use for the field type.
    • hook_field_formatter_info() - the display of field values.

    The task in Drupal 8 is founded on the same principles although the implementation differs. The first thing to remember here is, “there is a class for that!”. A lot of the hard work has been done in Drupal core and all we need to do is extend some classes and override default methods to suit our implementation.

    FieldsDrupalCampLondon2015-009.jpg

    Creating a module

    All contrib and custom modules should be placed inside the “modules” folder in your site root. Core-related code is now in “core”. However, it’s also best practice to have “contrib” and “custom” sub-folder in “modules” for clear separation of these types of modules. So we’ll create our “country” folder under modules\custom. What used to go inside *.info file is now in country.yml, so we create that file too and add the following:

    name: Country
    type: module
    description: Defines a simple country field type.
    package: Field types
    version: VERSION
    core: 8.x
    dependencies:
      - field
    

    Inside your module directory, you need a “src” subdirectory to keep all your class files. To organise things further, you need a “Plugin” sub-folder in “src”. There are different types of plugins e.g. fields, actions, blocks and menus. So you need to create another folder called “Field” inside Plugin and you’ll end up with a directory structure like src\Plugin\Field

    FieldsDrupalCampLondon2015-015.jpg

    Next, we need to define our data type, widget and formatter. These will be in classes with each occupying its own folder again. Let’s take them one by one.

    Data Type

    The folder is called FieldType, so create it - src\Plugin\Field\FieldType. Create a class, which we shall call “CountryItem”. The file is called CountryItem.php and in it we should have:

    class CountryItem {
    }
    

    How do we define our field type? With the new plugin system, this requires an annotation1 - something like a special comment block to allow core classes know about our field type. Your code should now look like this:

    /**
     * Plugin implementation of the 'country' field type.
     *
     * @FieldType(
     *   id = "country",
     *   label = @Translation("Country"),
     *   description = @Translation("Stores the ISO-2 name of a country."),
     *   category = @Translation("Custom"),
     *   default_widget = "country_default",
     *   default_formatter = "country_default"
     * )
     */
    class CountryItem {
    }
    

    The information provided in our annotation is quite similar to that provided when implementing hook_field_info() in Drupal 7. Next, at the top of our file, we add a few things like namespaces and import required core classes.

    namespace Drupal\country\Plugin\Field\FieldType;
    
    use Drupal\Core\Field\FieldItemBase;
    use Drupal\Core\TypedData\DataDefinition;
    use Drupal\Core\Field\FieldStorageDefinitionInterface;
    

    Then we make our class inherit from core FieldItem class by extending it.

    class CountryItem extends FieldItemBase {
    }
    

    There are two functions we must implement in our class - schema() and propertyDefinitions(). They’re as follows:

    public static function schema(FieldStorageDefinitionInterface $field_definition) {
        return array(
          'columns' => array(
            'value' => array(
              'type' => 'char',
              'length' => static::COUNTRY_ISO2_MAXLENGTH,
              'not null' => FALSE,
            ),
          ),
          'indexes' => array(
            'value' => array('value'),
          ),
        );
      }
    

    Here we define the schema for this field. The column is to be called “value”, and will hold a 2-character string, representing the ISO-2 name of countries. Oh, don’t forget to add the constant for the length in your class:

    const COUNTRY_ISO2_MAXLENGTH = 2;
    
    public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
        $properties['value'] = DataDefinition::create('string')
          ->setLabel(t('Country'));
        return $properties;
      }
    

    However, we need to add two methods to make our life easier. Firstly, we want to know when our field is considered empty which is what hook_field_is_empty() does in Drupal 7. Then, we want to add some validation so that the country code we want to store doesn’t exceed the maximum length we have defined for our schema. When we are through, our class should look like this:

    /**
     * @file
     * Contains \Drupal\country\Plugin\field\field_type\CountryItem.
     */
    
    namespace Drupal\country\Plugin\Field\FieldType;
    
    use Drupal\Core\Field\FieldItemBase;
    use Drupal\Core\TypedData\DataDefinition;
    use Drupal\Core\Field\FieldStorageDefinitionInterface;
    
    /**
     * Plugin implementation of the 'country' field type.
     *
     * @FieldType(
     *   id = "country",
     *   label = @Translation("Country"),
     *   description = @Translation("Stores the ISO-2 name of a country."),
     *   category = @Translation("Custom"),
     *   default_widget = "country_default",
     *   default_formatter = "country_default"
     * )
     */
    class CountryItem extends FieldItemBase {
    
      const COUNTRY_ISO2_MAXLENGTH = 2;
    
      /**
       * {@inheritdoc}
       */
      public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
        $properties['value'] = DataDefinition::create('string')
          ->setLabel(t('Country'));
        return $properties;
      }
    
      /**
       * {@inheritdoc}
       */
      public static function schema(FieldStorageDefinitionInterface $field_definition) {
        return array(
          'columns' => array(
            'value' => array(
              'type' => 'char',
              'length' => static::COUNTRY_ISO2_MAXLENGTH,
              'not null' => FALSE,
            ),
          ),
          'indexes' => array(
            'value' => array('value'),
          ),
        );
      }
    
      /**
       * {@inheritdoc}
       */
      public function isEmpty() {
        $value = $this->get('value')->getValue();
        return $value === NULL || $value === '';
      }
    
      /**
       * {@inheritdoc}
       */
      public function getConstraints() {
        $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
        $constraints = parent::getConstraints();
        $constraints[] = $constraint_manager->create('ComplexData', array(
          'value' => array(
            'Length' => array(
              'max' => static::COUNTRY_ISO2_MAXLENGTH,
              'maxMessage' => t('%name: the country iso-2 code may not be longer than @max characters.', array('%name' => $this->getFieldDefinition()->getLabel(), '@max' => static::COUNTRY_ISO2_MAXLENGTH)),
            )
          ),
        ));
        return $constraints;
      }
    }
    

    Data Input

    Now we have defined our data type and we want to store the ISO-2 country code. How do we want users to input data? We have two options - select dropdown options and an autocomplete textfield. The select options can be the default widget.

    We start by creating a class called CountryDefaultWidget in src\Plugin\Field\FieldWidget\CountryDefaultWidget.php with the following code:

    namespace Drupal\country\Plugin\Field\FieldWidget;
    
    use Drupal;
    use Drupal\Core\Field\FieldItemListInterface;
    use Drupal\Core\Field\WidgetBase;
    use Drupal\Core\Form\FormStateInterface;
    
    class CountryDefaultWidget extends WidgetBase {
    }
    

    There’s still an important thing missing from our widget class - annotation of the class as provider of a FieldWidget. Add this just above the class statement;

    /**
     * Plugin implementation of the 'country_default' widget.
     *
     * @FieldWidget(
     *   id = "country_default",
     *   label = @Translation("Country select"),
     *   field_types = {
     *     "country"
     *   }
     * )
     */
    

    This is similar to the old array keys for the old hook_widget_info() in Drupal 7. Additional annotation keys may be defined by a hook_field_widget_info_alter() function.

    Our CountryDefaultWidget class isn’t complete yet. Widgets handle how fields are displayed in edit forms. The missing method we need to implement will do this for us. Add this formElement() method:

    public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
        $countries = \Drupal::service('country_manager')->getList();
        $element['value'] = $element + array(
            '#type' => 'select',
            '#options' => $countries,
            '#empty_value' => '',
            '#default_value' => (isset($items[$delta]->value) && isset($countries[$items[$delta]->value])) ? $items[$delta]->value : NULL,
            '#description' => t('Select a country'),
          );
        return $element;
    }
    

    Other modules may alter the form element provided by this function using hook_field_widget_form_alter() or hook_field_widget_WIDGET_TYPE_form_alter().

    This default country widget is a simple widget of select options. Drupal core provides a list of all countries in the world as an array of country names keyed by ISO-2 country codes. This is made available as a service for use anywhere in a Drupal project.

    Let’s start off with a complete implementation for this. Create src\Plugin\Field\FieldWidget\CountryAutocompleteWidget.php with this code:

    namespace Drupal\country\Plugin\Field\FieldWidget;
    
    use Drupal\Core\Field\FieldItemListInterface;
    use Drupal\Core\Field\WidgetBase;
    use Drupal;
    use Drupal\Core\Form\FormStateInterface;
    
    /**
     * Plugin implementation of the 'country_autocomplete' widget.
     *
     * @FieldWidget(
     *   id = "country_autocomplete",
     *   label = @Translation("Country autocomplete widget"),
     *   field_types = {
     *     "country"
     *   }
     * )
     */
    class CountryAutocompleteWidget extends WidgetBase {
    }
    

    There’s nothing unusual here at all. We need to implement same defaultSettings() and formElement() methods as for the default widget. Add this to the class:

    public static function defaultSettings() {
        return array(
          'size' => '60',
          'autocomplete_route_name' => 'country.autocomplete',
          'placeholder' => '',
        ) + parent::defaultSettings();
      }
    

    We want a textfield that’s wide enough (‘size’ => 60). For the autocomplete_route_name key we provide the name of the route from which our autocomplete functionality will return matching values. We’ll be implementing that shortly. We don’t want anything as the placeholder.

    Finally, let’s add our formElement() method:

    public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
        $countries = \Drupal::service('country_manager')->getList();
        $element['value'] = $element + array(
          '#type' => 'textfield',
          '#default_value' =>  (isset($items[$delta]->value) && isset($countries[$items[$delta]->value])) ? $countries[$items[$delta]->value] : '',
          '#autocomplete_route_name' => $this->getSetting('autocomplete_route_name'),
          '#autocomplete_route_parameters' => array(),
          '#size' => $this->getSetting('size'),
          '#placeholder' => $this->getSetting('placeholder'),
          '#maxlength' => 255,
          '#element_validate' => array('country_autocomplete_validate'),
        );
        return $element;
      }
    

    This is a standard autocomplete widget. Looking at the FAPI array keys, some are very familiar. #autocomplete_route_name matches what we entered in our defaultSettings() a while ago. The value is retrieved from there with $this->getSetting(‘autocomplete_route_name’). The same goes for #size and #placeholder. Our #autocomplete_route_parameters has no default value. In order to ensure that the final value to be submitted doesn’t include unwanted values, we add #element_validate and enter the name of our callback function. We will also implement this shortly.

    Creating a route

    Create a YAML configuration file called country.routing.yml in your main module directory with the following:

    country.autocomplete:
      path: '/country/autocomplete'
      defaults:
        _controller: '\Drupal\country\Controller\CountryAutocompleteController::autocomplete'
      requirements:
        _permission: 'administer content types'
    

    The key or name of the route is country.autocomplete which is how this route will be referred to anywhere in the application. At least a route should define 3 things: path, code to execute and who can access the path.

    • path: This is the URL for our AJAX autocomplete calls.
    • _controller: This is the code we want to execute when we visit the defined path. It’s written as CLASS::FUNCTION. If our function requires any parameters, this is where they will be specified. We will be creating our controller shortly.
    • _permission: The string representation of the permission for access control

    Now we move on to the creation of our controller class. Create a folder called Controller under src. Then add CountryAutocompleteController.php inside it. Add this code:

    /**
     * @file
     * Contains \Drupal\country\Controller\CountryAutocompleteController.
     */
    
    namespace Drupal\country\Controller;
    
    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Component\HttpFoundation\Request;
    use Drupal\Component\Utility\Unicode;
    use Drupal;
    
    /**
     * Returns autocomplete responses for countries.
     */
    class CountryAutocompleteController {
    
      /**
       * Returns response for the country name autocompletion.
       *
       * @param \Symfony\Component\HttpFoundation\Request $request
       *   The current request object containing the search string.
       *
       * @return \Symfony\Component\HttpFoundation\JsonResponse
       *   A JSON response containing the autocomplete suggestions for countries.
       */
      public function autocomplete(Request $request) {
        $matches = array();
        $string = $request->query->get('q');
        if ($string) {
          $countries = \Drupal::service('country_manager')->getList();
          foreach ($countries as $iso2 => $country) {
            if (strpos(Unicode::strtolower($country), Unicode::strtolower($string)) !== FALSE) {
              $matches[] = array('value' => $country, 'label' => $country);
            }
          }
        }
        return new JsonResponse($matches);
      }
    }
    

    Whatever we type in our autocomplete widget will get passed to our autocomplete method. Then, we simply search for it in the array of country names which we pull from the country_manager service we have come across before. Finally, we return any matches or an empty array in a JSON response.

    That looks more like it now and we’re nearly there. If you look back at our formElement() method in CountryAutocompleteWidget.php we specified a validation callback. We are going to do that now in our country.module file. Add this code:

    /**
     * @file
     * Defines simple country field type.
     */
    
    use Drupal\Core\Routing\RouteMatchInterface;
    use Drupal\Core\Form\FormStateInterface;
    
    /**
     * Form element validate handler for country autocomplete element.
     */
    function country_autocomplete_validate($element, FormStateInterface $form_state) {
      if ($country = $element['#value']) {
        $countries = \Drupal::service('country_manager')->getList();
        $iso2 = array_search($country, $countries);
        if (!empty($iso2)) {
          $form_state->setValueForElement($element, $iso2);
        }
      }
    }
    

    We get our array of countries, and compare the value we want to send to the database with possible values. Now that we’re here, let’s just implement hook_help to give some information about our module. Just add this below the last use statement:

    /**
     * Implements hook_help().
     */
    function country_help($route_name, RouteMatchInterface $route_match) {
      switch ($route_name) {
        case 'help.page.country':
          $output = '';
          $output .= '&lt;h3&gt;' . t('Country') . '&lt;/h3&gt;';
          $output .= '&lt;p&gt;' . t('The Country module defines a simple country field type for the Field module. It provides 2 widgets - select options and autocomplete textfield - for this purpose.  See the &lt;a href="http://capgemini.github.io/drupal/writing-custom-fields-in-drupal-8/!field-help">Field module help page&lt;/a&gt; for more information about fields.', array('!field-help' => url('admin/help/field_ui'))) . '&lt;/p&gt;';
          return $output;
      }
    }
    

    We have now finished our autocomplete widget and learned something about routing. Not bad at all!

    Data Output

    We have everything ready for creating our field and allowing users to input data. Everything should work. There’s little work left before we can display the output. That’s where the need for a field formatter comes in. Add a new folder: src\Plugin\Field\FieldFormatter and inside it create CountryDefaultFormatter.php. Then add this code.

    /**
     * @file
     * Definition of Drupal\country\Plugin\field\formatter\CountryDefaultFormatter.
     */
    
    namespace Drupal\country\Plugin\Field\FieldFormatter;
    
    use Drupal\Core\Field\FieldItemListInterface;
    use Drupal\Core\Field\FormatterBase;
    use Drupal;
    
    /**
     * Plugin implementation of the 'country' formatter.
     *
     * @FieldFormatter(
     *   id = "country_default",
     *   module = "country",
     *   label = @Translation("Country"),
     *   field_types = {
     *     "country"
     *   }
     * )
     */
    class CountryDefaultFormatter extends FormatterBase {
    }
    

    If we don’t do anything now, everything will work except where we expect to see a country name, we will see the ISO-2 which was saved as the value of the field. To display our country name, we need to override the viewElements() method. So let’s do it:

    /**
     * {@inheritdoc}
     */
    public function viewElements(FieldItemListInterface $items) {
        $elements = array();
        $countries = \Drupal::service('country_manager')->getList();
        foreach ($items as $delta => $item) {
          if (isset($countries[$item->value])) {
            $elements[$delta] = array('#markup' => $countries[$item->value]);
          }
        }
        return $elements;
    }
    

    Once again, we get our array of countries, find the country name for our ISO-2 value and return it as markup. Job done. The module we have created is now functional and can now be installed.

    Field UI

    Let’s take a look at what fields UI offer us with our Country field. You may use an existing content type or start off with a new one. From the list of content types (admin/structure/types) clicking on the Edit operation will take you to the edit form with three tabs at the top: Manage fields, Manage form display, and Manage display which give us access to our field type, field widget and field formatter, respectively.

    • Field type (Manage fields):

    Click “Add field”. Select “Country” from the “Add a new field” select dropdown. That dropdown is populated by all @FieldType plugins from all enabled modules. They are grouped according to the “category” key of field plugins. This is optional, and if it isn’t defined for a field, it goes under “General”. If you inspect it, you’ll see that the name is “country_default” which matches the “id” key of our plugin and the “Country” we see there is the “label”.

    Enter “Location” as the field name in the “Label” textfield and save it.

    If you want to see how the field type settings are reflected in the field UI, go back to the annotation in CountryItem.php. Edit your plugin label, change it to something like “Country - edited” and save it. Then go back to the fields UI page and you’ll see not only the new value in the select dropdown when creating a new field but also under the “Field Type” column for the new Location field. You can revert the change now.

    • Field widget (Manage form display):

    On this screen you can see what was defined in the FieldWidget plugin. In the URL you can see the plugin “id” and the “label” is the description.

    • Field formatter (Manage display):

    There isn’t much choice here so we just leave the default formatter as is.

    You may now take the completed field module for a spin. Finish by adding it to a content type, create a node and view the output. That’s all. We’ve come to the end of looking at how to create custom field modules and in the process learned a few things about Drupal 8. Go make yourself a coffee. You deserve it!

    1: See https://www.drupal.org/node/1882526 for an excellent introduction to annotation-based plugins.

    Aug 26 2015
    Aug 26

    The Drupal community is a vibrant, global group of people with a colorful range of professions, hobbies, and interests. That’s why we couldn’t be more excited to bring DrupalCon to Mumbai, a city of color, excitement, diversity, and light.

    Typically, the Drupal Association produces DrupalCons in North America and Europe, but starting in 2015 we decided to do something a little different. We wanted to make sure that our DrupalCon programming and site selection reflected our community’s wide and diverse spread. That’s why we’ve introduced a third DrupalCon to the mix.

    DrupalCon Asia is going to be a fantastic event — not only is the local Drupal community incredibly active, passionate, and well-organized, but the larger Asian Drupal community is one of our most exciting developing regions. There are hundreds of incredible shops and businesses who use Drupal all across Asia, and we’re looking forward to building stronger friendships and business partnerships with them this February.

    To learn more about our decision to hold DrupalCon Asia in India, check out some of Megan Sanicki’s posts on the Drupal Association blog:

    We're looking forward to seeing some familiar faces and many new ones in Mumbai this February. If you'd like to get involved, you can do so by submitting a proposal for a session or training, or volunteering to help organize and run the Con.

    See you in Mumbai!

    Flickr photo by pdjohnson

    Aug 26 2015
    Aug 26

    We couldn’t have trained dozens of Acquia employees on Drupal 8 without using various applications to schedule, measure our progress, and follow communications about the massive undertaking.

    Let’s take some time in this, the fifth blog in a series about Drupal 8 instruction, to give a quick overview of the tools we used to train.

    We used the collaboration software Confluence because we could set it up quickly. Kent Gale, the co-author of this blog and my partner in the training project, and I would have preferred to have built a tool within Drupal. But we went with Confluence because we were able to deploy it quickly and edit content. It’s where we placed project documentation to enable in-place editing.

    Calendars kept in Google Docs spreadsheets accounted for every employee’s time. Every trainee had time blocked off each week for training. It was protected time, so to speak, agreed upon by employee and supervisor – time that was free of any other obligation. Each week, I’d also schedule 30 minutes with each employee – although meetings didn’t last that long – to talk about training. I wanted to see if they faced any barriers or had questions they were too embarrassed to ask in training sessions. We found this hands-on check-in – which was brief but frequent – kept everyone on track.

    We also used email and a chatroom to communicate. Initially, email was the preferred route, but as more people enrolled in training, the chatroom was better able to handle the flow of communications. The spontaneity of a chatroom allowed a lot of questions to be answered quickly. It built a resource as well as type of behavior.

    On our tracking sheet, we followed the time each employee spent on training and could see how much time was left. We also tracked the lessons they completed and could see if a team fell behind and could quickly address why.

    When you’re ready to train, find a tool and use it a lot before starting the program to ensure it will accomplish what you need. Then pick an end date and work backwards. That will tell you how much time you’ll have. From there, you’ll be able to determine if you should compress training to reach a deadline or if you can spread it out over time.

    As organized and motivated as we were, and despite starting early, it was still difficult to carve out time for nearly 50 people, and keep our end-date within reach. It was a commitment. So keep that in mind: Your managers and employees have to commit to protecting training time to make it all happen. Otherwise, it’s very easy to let the opportunity slip away.

    Aug 26 2015
    Aug 26

    Label the Rest of the Things!

    Native accessible name properties that we discussed in part 1 are all great, but there are situations where these don’t suffice - where either no method for providing an accessible name exists in HTML5 or a situation arises where standard HTML5 methods aren’t enough. Enter aria-label and aria-labelledby. Aria-label and aria-labelledby are global WAI-ARIA attributes which means they can be used on all HTML5 elements although they have widest support by screen readers when used on focusable elements. Let’s look at some use cases.
     

    Multiple nav elements with aria-label

    What happens when you have multiple navigation blocks on a page using the <nav> element where it’s clear to a sighted user what each menu is but there are no indicators such as headings for each menu for a blind user? For example, a site with a main menu, a user menu, a footer menu? Mark up the menus with just the <nav> element and a screen reader user doesn’t know what distinguishes the different menus from each other without listening to the menu links. If they bring up a list of the page's landmarks, they’ll just hear:

    Navigation
    Navigation
    Navigation

    This is a great use for aria-label:

    <nav aria-label="Main menu">
      … list of links
    </nav>
    
    <nav aria-label="User menu">
      … list of links
    </nav>
    
    <nav aria-label="Footer menu">
      … list of links
    </nav>

    Now if the user brings up a list of landmarks, they’ll hear:

    Main menu navigation
    User menu navigation
    Footer menu navigation

    Much more helpful!
     

    Search textbox without <label> using aria-label

    Or say you have the common situation of a search form in the header of the site with just a search box and no visible label. You could include the label and visibly hide it or you could use aria-label to provide a label for the input:

    <input id="searchbox" type="text" name="searchbox" aria-label="Search this site">

    This way, the screen reader will read “Search this site, edit text” (or similar, depending on screen reader) instead of just a generic “edit text” or “input” which is rather unhelpful.

     

    Textboxes with aria-labelledby

    Sometimes there is a label available for an element but just no relationship established between the two. Consider the following form:

    Example form demonstrating aria-labelledby

    Visually, it’s pretty self-explanatory what should go in each textbox. But without visual context, it’s unclear what content is expected because there are no form labels. A screen reader user would simply hear a series of “edit text, edit text, edit text” which tells them there are textboxes for input. However, we do have column and row headers that we can use to label each textbox. Using aria-labelledby, we can specify the header or headers that should label each input.  

    <form>
    <table>
    <caption>Pets</caption>
        <tbody><tr>
            <th id="petnumber" scope="col">Pet's Number</th>
            <th id="petname" scope="col">Pet's Name</th>
            <th id="species" scope="col">Species</th>
            <th id="age" scope="col">Age</th>
        </tr>
        <tr>
            <th id="pet1" scope="col">Pet 1</th>
            <td><input type="text" name="pet1name" aria-labelledby="pet1 petname"></td>
            <td><input type="text" name="pet1species" aria-labelledby="pet1 species"></td>
            <td><input type="text" name="pet1age" aria-labelledby="pet1 age"></td>
        </tr>
        <tr>
            <th id="pet2" scope="col">Pet 2</th>
            <td><input type="text" name="pet2name" aria-labelledby="pet2 petname"></td>
            <td><input type="text" name="pet2species" aria-labelledby="pet2 species"></td>
            <td><input type="text" name="pet2age" aria-labelledby="pet2 age"></td>
        </tr>
        <tr>
            <th id="pet3" scope="col">Pet 3</th>
            <td><input type="text" name="pet3name" aria-labelledby="pet3 petname"></td>
            <td><input type="text" name="pet3species" aria-labelledby="pet3 species"></td>
            <td><input type="text" name="pet3age" aria-labelledby="pet3 age"></td>
        </tr>
        </tbody>
    </table>
    </form>
    

    Now a screen reader user will hear:

    Pet 1, Pet’s Name, edit text
    Pet 1, Species, edit text
    Pet 1, Age, edit text
    Pet 2, Pet’s Name, edit text
    Pet 2, Species, edit text
    ...and so on.  

    This will tell the user exactly what piece of information is needed and for which pet.
     

    Navigation elements with aria-labelledby

    Taking our navigation example from above, what if we do have headings for our navigation menus? No need to add duplicate labels. We can reuse them and associate the headings with the menus so that the name of the navigation menu is read along with the navigation element:

    <h2 id=”popularposts”>Popular Posts</h2>
    <nav aria-labelledby=”popularposts”>
      <ul>
        <li><a href="https://www.mediacurrent.com/blog/drupal-agency-mediacurrent-awarded-best-overall-smb-salesforce"> Drupal Agency, Mediacurrent, Awarded Best Overall SMB by Salesforce</a></li>
        ….more link list items
      </ul>
    </nav>

    Now, instead of just navigation, the menu will be read as "Popular Posts navigation." 
     

    Bonus: aria-describedby

    Although not a naming mechanism, aria-describedby is a close relative to aria-label and aria-labelledby. It allows you to associate existing additional information to your element. For instance, say you have a text field that has a label but requires the user to be aware of additional information in order to fill it in. Putting that additional information in the label field could make it very long. So, it’s generally added before or after the text field in a paragraph or div tag like so:

    Example form demonstrating aria-labelledby

    This means that the additional instructions won’t be read to the user in forms mode - when the user is tabbing from input to input. It will be skipped. Aria-describedby is the way to make sure these additional instructions are made known to the user:

    <label for="telephone">Telephone number</label>
    <input type="text" id="telephone" name="telephone" aria-describedby="telephoneformat" />
    <p id="telephoneformat">Please use the format 123.555.1234</p>

    Now, when focus is placed on the Telephone number input, the label will be read along with the paragraph that includes instructions for the format. Note, however, that on VoiceOver, there is a 7 second delay before aria-describedby text is read. Why?   ¯\_(?)_/¯
     

    Summary

    As you can see, these 3 simple WAI-ARIA attributes can come in pretty handy and go a long way in making a page more accessible to screen reader users. Using native HTML accessible names is the way to go when possible, and when they’re not available, we have aria-label, aria-labelledby, and aria-describedby to fall back on.  

    Additional Resources
    Accessible Names - Label All the Things! (Part 1) | Mediacurrent Blog Post
    5 Simple Things You Can Do to Make Your Site More Accessible | Mediacurrent Blog Post
    Web Accessibility Terminology | Mediacurrent Blog Post

    Aug 26 2015
    Aug 26
    Posted on August 26, 2015

    At Singlebrook, we're using Styleguide Driven Development to create efficiency and strengthen code quality.

    Jeff Amaral led a session at Cornell Drupal Camp 2015 on the topic of Styleguide Driven Development. He has shared his slides here as a downloadable PDF: "Singlebrook Styleguide Driven Development in Drupal"

    The slides contain an outline of major points to consider when using Styleguide Driven Development, as well as some links to helpful resources. 

    Introduction:

    Theming in Drupal has many challenges. The biggest, in our experience at Singlebrook, is coordinating the creation of new site functionality and the CSS styling of the new markup, especially when multiple developers are working on a site.

    In this session, we discuss our brand new theming process using CSS/HTML components, some extensions to the styleguide module, and improved developer/themer communication. We cover:

    • How to style first and build functionality later. 
    • How to include a living styleguide, complete with your custom style components, on your site for review by your client.
    • How to bend Drupal’s default markup to your will, using theme overrides, preprocess functions, and other techniques.
    • Some emerging ideas on CSS organization and techniques to avoid the bad kinds of style cascades.

    ***

    Feel free to add your thoughts and share your experience using this approach to Drupal development in the comments section!

    Aug 26 2015
    Aug 26

    We’re working on our first Drupal 8 project here at Advomatic, and Jim and I have been tasked with implementing a content migration from the client’s existing Drupal 6 site.

    My first assignment was to write a plugin which rewrites image assist tags in node body fields as regular HTML image tags. Fortunately, lots of smart people had already solved this problem for Drupal 6 to Drupal 7 migrations (I adapted my plugin from Olle Jonsson’s script on Github), so the biggest hurdle was learning how to implement this thing in Drupal 8.

    This is the true story of how we made it work.

    Note: You’ll need to use Drush 8 for working with Drupal 8. I’d recommend following Karen Stevenson’s great tutorial from the Lullabot blog to help set up multiple versions of Drush on your system.

    Initial setup

    As of this writing, you’ll need some very specific Git checkouts of Drupal core and the migration helper modules, or you’re going to immediately encounter a pile of fatal errors. These are working for us:

    Enable those modules and their dependencies, then set up your own custom module for your plugin code. The very cool Drupal Console module is a quick way to generate the boilerplate files you’ll need.

    Write some code

    Migration template

    Your migration is likely going to need to provide migration templates for various node types, as well as one that handles all nodes. This plugin for handling image assist tags needs to run on all imported nodes, so we start by copying /core/modules/node/migration_templates/d6_node.yml over to our module and adjusting it a little to instruct it to run the ImgAssist plugin (see line 36 here).

    Migrate plugin

    There are example process plugins in “process” folders around the installation, and looking at those was a great way to figure out how to write ours. Jim made note of these commands to use for finding example code:

    find ./ -type d -name 'migration_templates'
    find ./ -type d -name 'process'

    Our ImgAssist migrate process plugin starts with the Drupal 6 node body and teaser values, and then it runs through a few steps to create their Drupal 8 counterparts:

    Running a node migration, step-by-step

    • 1. Get the D6 site running locally.
    • 2. Install Drupal 8 dev at the commit noted above.
    • 3. Install migrate_plus and migrate_upgrade at the commits noted above, and enable your custom module.
    • 4. Add your D6 database connection information to settings.php (you can follow the Drupal 7 directions here).
    • 5. Run these Drush commands:
      • drush8 migrate-upgrade --legacy-db-url=mysql://dbusername:dbpassword@dbhost/D6databasename --legacy-root=http://d6site.local --configure-only
      • drush8 migrate-status (just to make sure your custom migration template is registering)
      • drush8 migrate-import yourmodule_d6_node

    You’ll probably get an error the first time running migrate-import since the node migration depends on a few others to run first, such as d6_user. Run the dependency migrations as needed, then try the custom node import again.

    If you have a lot of nodes, the import process will take a few minutes. I actually wrote this entire blog post while waiting for imports to run. Go do something fun for a minute, you’ve earned it.

    Eventually, migrate-import will finish running, and you’ll be all set! You can compare the node on your D8 site against the node on the D6 site and see that the tag has been replaced. Hooray!

    If it didn’t work: read on. It’s totally fine, you’ve got this.

    So what if you have to roll it back?

    drush migrate-rollback hasn’t been implemented in D8 just yet (but it is getting close). A workaround is to use drush scr to run a script which deletes your newly-imported nodes. We’ve been using this: https://gist.github.com/sarahg/993b97d6733003814fda

    Then, you’ll need to uninstall your custom module, remove all of its config entities from the database, and drop its database tables. You can do that with queries like these:

    DELETE from config where name=“migrate.migration.yourmodule_d6_node”;
    DROP table migrate_map_yourmodule_d6_node;
    DROP table migrate_message_yourmodule_d6_node;

    To make this a little easier, you could add these queries to a hook_uninstall function in your module. I’m not one for making things easy (I’m working on this migration before there’s even a Drupal 8 release candidate, after all), so I’ve just been using drush sql-cli.

    Now you can adjust your code as needed, re-enable your module and give it another shot (you can just skip ahead to the “drush8 migrate-import yourmodule_d6_node” step at this point).

    Further reading

    It took a lot of research to figure out how to get migrate working in Drupal 8 this early in the game. These articles were immensely helpful (thanks bloggers and documenters!).

    Aug 26 2015
    Aug 26

    We've helped a number of nonprofits move from Luminate CRM to Drupal-Salesforce solutions, including the Young Survival Coalition, Facing History and Ourselves, the National Kidney Foundation, and the Los Angeles Conservancy.

    Without getting too deep into the technical architecture - which you can nerd out on in other posts on our blog - our open source Salesforce integration can map any object/field in Salesforce to a corresponding entity type/field in Drupal. We can then sync these records bidirectionally. We can even support complex, cascading upserts of multiple records in real time.

    This allows us to leverage everything that’s great about Drupal (CMS tools, personalization, paid and unpaid event registrations, membership purchases, general ecommerce, and user access controls) with everything that’s great about Salesforce's Nonprofit Starter Pack (NPSP) 3.0 (best-in-class donor management, unlimited extendability and scalability, flexible and intuitive reporting tools, and the most robust Application Exchange available).

    It's always been clear that Salesforce provides much better constituent relationship management tools on the backend than Luminate or other Convio/Blackbaud products. What’s kept Luminate in the game for so long has been its public-facing web features, such as membership management and event registration tools.

    That said, there is no way that Luminate could ever keep up with the pace of innovation that we see with comparable features in Drupal. The open source model and volume of contributions from the Drupal community is unparalleled. Leveraging Drupal as a donor/constituent front-end for Salesforce, we can provide seamless user experiences that engage with website visitors more deeply, because we can personalize these experience based upon data pulled from Salesforce’s API.

    Take the Los Angeles Conservancy as a case study:

    When we met the Conservancy, they were struggling to engage stakeholders through an aging website and cumbersome collection of Luminate donation and event management tools. Asking website visitors to click away from their website to third-party forms provided by Convio severely hurt their conversion rates. Mobile event registrations and contributions were almost nonexistent on their site.

    The Conservancy wanted an interactive and mobile-friendly solution that would allow their constituents to easily sign up for free walking tours, buy tickets to movie events, update their membership information, set up recurring membership payments, and make donations towards different fundraising campaigns.

    By leveraging Drupal event registration and ecommerce tools, we were able to build all of these features within the Conservancy’s new responsive website. This provided a much more seamless user experience. Conversion rates soared as a result. In fact, the Conservancy staff came to us 3 months after the relaunch concerned that their Google Analytics showed decreased traffic on their event registration pages. They worried that they were losing registrations - when in reality, their conversation rates were going up so dramatically, and the time for completing an ecommerce transaction was dropping so quickly, that these forms were seeing less page clicks while their volume of transactions and their revenue was going up.

    With Drupal-based event registration and donation tools, we have 100% control over ecommerce workflows. We can also support complex pricing options based upon constituent data in Salesforce. For example, we can adjust ticket pricing based upon membership status. Again, we benefit from Drupal Commerce, an ecommerce solution that powers over 60,000 websites, including some of the largest stores on the Internet.

    Further, integrating these Drupal-Salesforce solutions with iATS Payments, we can create Drupal-based donation portals that support “card on file” as well as recurring donations. And with iATS’s integration with Salesforce, donors can update their credit card information or make a donation over the phone by calling the Conservancy, storing this payment information for their next online transaction.

    In short, Convio/Blackbaud just can’t compete… With what our clients save in confusing and expensive Blackbaud licensing fees, we can build more effective fundraising solutions that lead to much higher returns for their investment.

    Aug 26 2015
    Aug 26

    “People like the beard,” quips Jeremy Rasmussen (Director of Web Development, Lever Pulley), who writes a frequent column in magazine (Subscribe! https://drupalwatchdog.com/subscribe/2015)
    about Drush, that Swiss Army knife that “makes Drupal bend to your will.”

    Aug 26 2015
    Aug 26

    We’ve just released Context.IO, an API module with a Feeds plugin submodule that uses the context.io API to import emails into a Drupal site. If you build something interesting with the module in the next 6 days, you can participate in the Context.IO App challenge and make a chance to win 50k USD.

    Context.IO makes email data accessible through a simple REST API. It makes it a lot easier to get data out of mailboxes, it implements oAuth authentication for the major email platforms, so it’s really easy to add email accounts. No need to add the password of your mailbox as a setting in your site, or to go search what the connection details are for an email provider. Just add the email account, and give access through the oAuth authentication process.

    Once connected you can use the filters in the Context.IO feeds fetcher to specify what emails you would like to upload to your site. Currently the module lets you filter messages using the following filters:

    • Subject
    • To, CC and BCC email addresses
    • From email addresses
    • Folder
    • Mails sent before and/or after a certain date

    With the Context.IO parser you can further refine the content you want to upload to your site. We are planning to make it possible to strip out repetitive content from the email body and to split structured information in email titles into separate fields, so that you could use this to automatically organise emails sent by a project management system or any other application.

    The resulting fields can then be mapped to Drupal entities using existing or custom feeds processors. With the Node processor you can map the email fields into the appropriate fields of the content type of your choice. With the User processor you can add users on your site whenever you receive an email that matches certain criteria.

    Once you’ve configured a feed, you can define how many emails you want to upload, or set up an automatic job that will regularly upload new emails into your site.

    An important downside to the module is that it adds another party that will be processing your email, if you are already using a cloud email provider this might not be such a big change, but it’s important to take this into account when using the module. Context.io is a free service by Returnpath a Canadian company that aggregates, anonymises and then analyses the emails they process to help their customers detect email fraud, optimise emails and get insight into consumer behaviour.

    This sounds scary but it is similar to the kind of analysis major cloud email providers do on the mailboxes of their customers. If you use this module to build an application that other people will connect their mailboxes to, you will need to add a warning about this to your terms and conditions.

    We built the Context.IO module because we thought it would be fun to participate in Context.IO's App Challenge. It would of course be great to win the 50k USD cash prize, but it also fits really nicely into our portfolio: At Pronovix we’ve done a lot of Drupal integrations for third party software applications. Because of our previous hustling with Drupal startup projects like WalkHub and Graphmind, we’ve tried and tested a lot of techniques to promote new tools in the Drupal community. We don’t want to just write code for our customers, we want to help them engage with the Drupal community in a way that will create win-wins for everybody.

    If we can help companies like Returnpath, Brightcove, Gitlab and Livefyre recognise the value of the Drupal community, they will become sponsors at Drupal events and spend money promoting Context.IO that helps us grow our ecosystem.

    So how do you win that 50k$ prize money? Context.IO is organising an App Challenge for the best consumer application that uses their API. They have some major players in the VC / startup space (Fred Wilson, Brad Feld, David Cohen, Matt Blumberg, Joshua Baer) and a $125,000 in cash prizes waiting to see what kinds of amazing applications you can build with email data. It was already easy for developers to integrate with their API, but with our Context.IO module it’s now really easy even for site builders to create a project. There is 6 days left, there are plenty of MVPs you could click together even in a single day.

    We are releasing the module before the end of the competition so that other Drupal site builders would be able to take part in the challenge. This might sound counter intuitive, since we are enabling our own competition, but we would really love to see loads of submissions from the Drupal community. By doing a submission you are not only making a chance for some serious prize money, you also help us prove that Drupal is an ecosystem worth investing in, so that other SaaS companies would recognise the Drupal community as a valuable target to spend their marketing dollars.

    Aug 26 2015
    Aug 26

    Managing a website without documentation is like trying to put together Ikea furniture without the directions--it's just not happening. Often, documentation is overlooked by companies and organizations on a budget, but it is a truly invaluable part of building a new website. Check out some great tips and tricks from our team of technical documenters, and learn how we provide our clients with documentation for their sites.

    Write with Efficient Tools

    Writing documentation requires generating dummy content, and our earlier post on lorem ipsum generators give you lots of tools for generating placeholder text. However, technical writers also need to create annotated screenshots to accompany the words that they write, as well as repeat the actual technical steps they are documenting. So here are some additional tools we found to be great assets to a documentarian's repertoire:
    • Awesome Screenshot - Use to take screenshot of a full webpage with auto-scrolling. Also provides a link to share your screenshot (stored on the cloud).
    • Window Resizer - Save pre-configured browser window sizes to capture your responsive design layouts.
    • No Scrollbars Please! - Remove the scrollbar from your browser to take a clean screenshot (especially of a webpage requiring scrolling).
    • Skitch - Use to capture desktop screenshots and annotation with arrows and text. We use it in combination with the extensions above.
    • Firefox Selenium IDE - Automate the repetitive technical steps that you are documenting.

    Confluence Macros

    If you use Confluence (an Atlassian product for documentation that integrates with JIRA), then check out the following Confluence macros which we find to be extremely useful.
    • Code Block - Insert code snippets throughout a page with syntax highlighting
    • Excerpt and Excerpt Include - Reuse a part of documentation on multiple pages
    • Expand - Initially hide some documentation as a link, which expands to display content upon a click on the link
    • Info, Tip, Note, and Warning - Callout important information, such as status of the feature documented and release versions.
    • Panel - Add border (like a box) to separate some documentation from the rest
    • Table of Contents - Great for the beginning of a tutorial guide or as a sidebar on a long page
    • Page Tree - Great on a page that introduces a topic with sub pages

    Be Agile with Documentation

    If you are agile, your documentation can be too. In a Johnson & Johnson Drupal project, we are providing documentation services as technical writers embedded amongst developers. Because we are integrated as part of their agile development process, we track our work in JIRA, participate in standups and retrospectives, such that documentation is continuously up to date with each sprint. We find that writing in agile iterations is a great way to capture feedback from various parties involved, including product owners, developers, and users in trainings. This way, strong documentation can be produced to maximize support for everyone on the project. Writing technical documentation is easier and more efficient to do in-sprint, while the features being documented are still present in the minds of the developers and product owners.

    Find the Voice for Your Audience

    Documentation being agile also means that you can adapt your writing voice to best suit your audience. Try to always learn more about your audience as you write documentation throughout the project. So far, this blog post has been written in an informative, technically instructional voice. Now say that our audience wants something lighter, more familiar, and empowering, then perhaps we should adapt our voice to something as follows.


    Ask Not What Your Product Can Do For You — Ask What You Can Do With Your Product

    When doing technical writing, it's easy to be... well, too technical. Just because you're a "technical writer" doesn't mean you should think of your audience as "technical readers." Your audience consists of people that want to do things. Empower them! Don't drone on and on about how "this product does many things" (yawn), when you can enable your reader by telling them "You can do many things with this product!" Yes, sometimes the product simply "provides," but any opportunity you have to inform the reader of what they can do, instead of telling them what the product does, take it.

    • Boring: "From the dropdown menu, a number of items are available. Selecting one will customize this feature."
    • Empowering: "By clicking the dropdown menu, you will see a number of items available to you for customizing this feature. Choose the option that best embodies the spirit of your brand."
    Much better, right? The first example, while technically sufficient, does little to engage the reader, and does the bare minimum to inform them of what needs to be done. The second example puts them in charge of driving the product, and uses "you" to communicate directly to them. Also, the second sentence of the empowering example informs the reader of what their motivating reason behind making their choice is. Don't just tell your readers how to do things; let them why they're doing things and what it can do for them and/or their business.

    Every website is different, so technical writing should be flexible, adaptive, and leverage the best tools to complete documentation for its team.

    Want to learn more about about documentation? Check out our Training & Documentation page.

    Aug 26 2015
    Aug 26

    Post date: 

    August 26 2015

    Category: 

    Tutorials

    Tags: 

    drupal planet, drupal, development, tips

    Some problems when developing are simply annoying, and show up again and again. Many of these are relatively tricky to solve without knowing the best solution for the problem. I’ve combined my answers to a few of these problems that I've found I run into often.

    1. You need to access Drupal site with no login details

    Sometimes it just happens that there will be a website that you need to manage, and you don't have the administration password for it. You might think that there is a reset password functionality, but if the email of the administrator is invalid, getting the password is not so simple.

    Use Drush to generate an one-time login link

    This is a very quick and easy way to get logged into Drupal. It only requires that you have server access and Drush (http://www.drush.org/) is installed. The drush command you would use is:

    drush uli
    

    Drush will then output you a one-time user login link for this particular website. The Drush command has options that you can add to it that are listed below.

    --browser : Optional value denotes which browser to use (defaults to operating system default). Set to 0 to suppress opening a browser.
    --uid : A uid to log in as.
    --redirect-port : A custom port for redirecting to (e.g. when running within a Vagrant environment)
    --name : A user name to log in as.
    --mail : A user mail address to log in as.

    A more advanced command example would be:

    drush uli --browser=firefox --name=admin node/2
    

    This would log you in using firefox, for the admin user, and redirect you to node/2.

    For more to read on Drush check out http://www.drush.org/en/master/

    Update password using the database

    In the case Drush isn’t available, your only option may be accessing the database. The idea is to simply change the encrypted password to another one through the database. If you’re using a GUI such as Sequel Pro, all you need to do is to navigate to users and change the encrypted password of the user admin.

    Without a GUI, you can do it with a simple MySQL query.

    UPDATE users SET name='admin', pass='$S$DfQ/y58nGpZvyRLYd3LSyJ.s82xSC3Z.2oxdCIL4EHKAYcQnDl9T' WHERE uid = 1;
    

    This would set the password of admin, if its the uid 1, to “lol”. This is an encrypted password string. To create your own password hash you can navigate to Drupal docroot and run the following command.

    php scripts/password-hash.sh 'yourpassword'
    

    And it will generate you an encrypted password.

    Use a module to hack your way through

    This is a solution I would only use on local setups to change my password. There is no real use case for using this on production servers, as it logs everyone in as user 1 that try to access the site. However, if you don’t have any server access, and can only push code to the server, this might be your only shot.

    
    
    1. global $user;

    2. $user = user_load(1);

    Then you can go change the account settings or promote other users to uid 1.

    2. No images show up on my local development site

    As we know, Drupal consists of three components, the database, the codebase and the files. The third one is considered the least important when developing, but to thoroughly test your work you do need the images to show up.

    There is often an issue that the Drupal site that you are working on has hundreds if not thousands of large images which could end up as large as 10gb downloads, and downloading this for your local setup is simply not worth it. Fortunately there are a few solutions that you can use to conquer the problem.

    Stage file proxy

    https://www.drupal.org/project/stage_file_proxy

    Stage file proxy regenerates the image links in a way that they will use the production server to get the images, and doesn't make you download them to your local setup. However default behavior of the module downloads the files when they’re missing. I encourage using the “Hotlink” mode of the module which does as previously explained.

    Installing Stage File Proxy can be as simple as :

    
    
    1. drush en stage_file_proxy -y

    2. drush variable-set stage_file_proxy_origin "http://www.example.com"

    But in most cases I find that saving the settings manually from the configuration is needed. It supports even locked in sites, with more documentation at https://www.drupal.org/project/stage_file_proxy.

    Using JS to populate images with a dummy image

    If you are working without an internet connection or there are issues with stage file proxy, then what you can do is to use JS to populate broken images with dummy images. This doesn't respect Drupal image styles, but it is a way to play with images. Add it to your JS after document ready.

    
    
    1. $('img').error(function(){

    2. $(this).attr('src', "/dummy-image.jpg");

    3. });

    3. Getting a database without server access

    Getting a database, files and code from your Drupal website can sometimes be tricky, especially when you have no server access. For example; you are working on a client site that has been forgotten somewhere in the cloud for a year, and no one has access to the server, there is still a solution you can try to get a copy of the site.

    Use the Backup and Migrate module.

    https://www.drupal.org/project/backup_migrate

    Fortunately most cloud servers allow modules to be installed on the fly. All you need to do is to use Drupal UI to install this module and you’ll be able to get a copy of the website easily. To do this you need to enable Update Manager, and then install the file using /admin/modules/install user interface. If the server where your website is does not support this, then you need to gain access to the server.

    The latest version of the Backup and Migrate module allows you to get a whole site with database, files and code. For simpler sites, using this module is great.

    4. Moving modules around in a Drupal setup causes errors

    Drupal gets angry when you move modules around in a setup. When you as a developer get your hands on a drupal website that other people have worked on, often the first instinct is to move the modules into a correct directory. Doing this can cause errors on the site and often results in a WSOD.

    The error that results is often something like follows:

    Fatal error: require_once(): Failed opening required '/profiles/profile/modules/contrib/entity/includes/entity.inc' in /profile/includes/bootstrap.inc on line 3161

    This is due to Drupal looking at functions where they were before, and now don’t exist anymore. To fix this issue you need to fix the module paths.

    Repair paths via drush registry rebuild

    Drush to the rescue again! Compared to the manual solution explained after, this is definitely faster and a safer solution. Install Drush rebuild registry by running the following command (you need to have drush installed first):

    drush dl registry_rebuild
    

    After you’ve moved the modules to the directory you want just run the drush registry rebuild command.

    drush rr
    

    This will go through your module registry and fix all of the broken connections.

    Then clear your drupal caches, and if needed re-run the drush rr command.

    Do not blindly trust the power of this command on production servers. I would recommend thorough testing before moving modules around and doing these changes on live sites, as it can become a mess. Always remember to take a backup of your database!

    Repair module paths manually

    If for some annoying reason you cannot use the power of Drush, or it has failed you, you can still do things manually. Manually fixing is time consuming if you’re doing a lot of changes to your directory structure. Remember to backup your database before starting.

    1. Make sure you’re logged in your Drupal setup before moving the modules. This allows you to access the /admin/modules page. Accessing this page rebuilds the system table which might solve your problem. Move your modules to the directory you want, and access the /admin/modules page.
       
    2. If the problem still continues you need to manually fix the following tables: system, registry and registry_file. The have filenames for each module, these need to be fixed as they are pointing to wrong directions. The following query is an example and was used when moving modules from the profile to a sites/all/modules/contrib setup.

      
      
      1. UPDATE system SET filename = REPLACE(filename, profiles/myprofile/modules', 'sites/all/modules/contrib');

      2. UPDATE registry SET filename = REPLACE(filename, 'profiles/myprofile/modules', 'sites/all/modules/contrib');

      3. UPDATE registry_file SET filename = REPLACE(filename, profiles/myprofile/modules', 'sites/all/modules/contrib');

    3. After doing the changes, clear your Drupal caches and keep your fingers crossed for success. You might need to clear all the caching from the database as well.

    5. Creating your re-usable local.settings.php

    This is more of a personal touch. In my local development I’ve tried to create a local.settings.php that is relatively universal to all of my projects.

    There are modules that always cause issues with local development such as securepages, or just need config, such as the before described stage_file_proxy. The local.settings.php is a file that is added to your docroot to provide these settings and make it faster for you to develop.

    
    
    1. # Local site configuration settings.

    2. if (is_readable('/path/to/site/sites/default/local.settings.php')) {

    3. include_once('/path/to/site/sites/default/local.settings.php');

    4. }

    And on your local when you’re setting up your site, you just add your optimal local settings php.

    This is my current version of the local.settings.php. Check out my latest one at GitHub and feel free to contribute to it, or add your comments below. The idea would be to include as much as I can in a file, as extra config doesn't really matter!
    This will speed up your development by making sure that the settings you want are there, and most importantly done without clicking around the site!

    
    
    1. global $conf;

    2. // Turn off Secure Pages. Secure Pages Module.

    3. $conf['securepages_enable'] = FALSE;

    4. $conf['https'] = FALSE;

    5. // Stage File Proxy Configuration

    6. $conf['stage_file_proxy_origin'] = 'http://mysite.com';

    7. // Stage file optional with securepages

    8. // $conf['stage_file_proxy_origin'] = 'http://username:[email protected]';

    9. $conf["stage_file_proxy_use_imagecache_root"] = FALSE;

    10. $conf['stage_file_proxy_hotlink'] = TRUE;

    11. // Turn off Caching.

    12. $conf['cache'] = 0;

    13. // Block caching - disabled.

    14. $conf['block_cache'] = 0;

    15. // Expiration of cached pages - none.

    16. $conf['page_cache_maximum_age'] = 0;

    17. // Aggregate and compress CSS files in Drupal - off.

    18. $conf['preprocess_css'] = 0;

    19. // Aggregate JavaScript files in Drupal - off.

    20. $conf['preprocess_js'] = 0;

    21. // Minimum cache lifetime - always none.

    22. $conf['cache_lifetime'] = 0;

    23. // Cached page compression - always off.

    24. $conf['page_compression'] = 0;

    25. // Turn off other caching.

    26. $conf['css_gzip'] = FALSE;

    27. $conf['javascript_aggregator_gzip'] = FALSE;

    28. // Turn on all error reporting for local development.

    29. error_reporting(-1);

    30. $conf['error_level'] = 2;

    31. ini_set('display_errors', TRUE);

    32. ini_set('display_startup_errors', TRUE);

    This will speed up your development by making sure that the settings you want are there, and most importantly done without clicking around the site!

    These are just some of the problems have come up during the days. If you have one you’re always running into, feel free to leave a comment about it!

    Aug 26 2015
    Aug 26
    146 Drupal Update Automation and Drop Guard with Manuel Pistner - Modules Unraveled Podcast | Modules Unraveled

    Skip to main content

    Update Automation

    • I’d like to talk a little bit about automation processes in general before we jump into Drop Guard, if that’s okay. What types of things are we talking about updating? Server configuration? Drupal projects? Deployment?
    • What are some of the technologies you were using before developing Drop Guard? Maybe the underlying pieces that make up the Drop Guard architecture.

    Drop Guard

    • What is Drop Guard?
      • Simply put, Drop Guard is a service to automate Drupal updates with seamless integration into development and deployment processes. Drop Guard helps Drupal shops and other Drupal support and service providers to automate their update work. In case of critical security updates Drop Guard will update the site automatically within 1 hour. This makes the operation of a site more secure and reliable and makes Drupal updates a full part of the development process.
    • You said it’s “integration into development and deployment workflows.” What do you mean by that?
      • Drop Guard works simply as a dedicated team member that is responsible for applying updates in the development as well as in the maintenance and support life-cycle of a project. You can configure Drop Guard to work with any hosting provider and with any team workflow. Drop Guard can execute different Rules-Based commands to trigger deployment actions just as a real team member would do it on manual update work.
    • How granular can you get with updates? Security only? All updates?
    • How does Drop Guard actually work? Is there a module to install? Server setup?
    • What happens if a bug is introduced with an automatic update? Is there a process to notify the developer?
    • Who is Drop Guard designed to be used by?
      • Drop Guard is designed to help Drupal agencies and freelancers to deliver Drupal update services automatically. Every Drupal shop can use Drop Guard as a white label service to deliver update services to their clients as part of support contracts. For end users that don’t understand the processes behind deployment and developement deeply enough, the service is too complex but Drupal shops will definitely benefit from additional developer time that they can save for their project business.
    • What prompted you to start building the Drop Guard service? And when was that?
      • We started with the base technology in 2012 to build a system for our internal support contracts. We had the need to automate recurring things and ensure that our SLAs for security patches are processed reliably. When Drupalgeddon shocked the Drupal world and many sites had to be patched in a very short period of time, we already had the benefit of automated updates for our supported projects. At this point I realized that the system might have a benefit for other Drupal shops. So Drop Guard has its birthday with Drupalgeddon :-)
    • Do you have any insights of the roadmap of Drop Guard?
      • Sure! Currently we are in an internal Beta phase. That means we harden the service with some trusted users and we will add more beta users each week till the end of September.Then we will open Drop Guard for a public Beta version where everybody that is interested can start using the service with the help of our support team. I am sure that there are many usability issues we will face as the high flexibility results in a more complex configuration processes. But thanks to our current beta users we were able to address and fix many of them till now. Also the Feedback from Drupalcon Barcelona visitors will be an important milestone for us.
    • Does this work with all hosting providers? (VPS, Pantheon, Platform.sh, Acquia cloud etc.)
    • What does the pricing structure look like after the beta period?
    • You mentioned there’s an incentive for people to get involved with the beta now. Do you want to talk about that?
    Aug 25 2015
    Aug 25

    There are rare occasions when you want to re-index all your site's content in Solr. Such occasions include:

    • Major Drupal version upgrade (e.g. from Drupal 6.x to Drupal 7.x).
    • Changing your Solr schema to include more search criteria.
    • Upgrading your Solr server to a new major version.
    • Moving your Solr server from an old server to a new one.

    The usual way of doing this re-indexing is to make cron run more frequently. However, if you do that, there is a risk of cron being blocked because of other long running cron tasks. Moreover, you are usually limited to a few hundred items per cron run, and then you have to wait until the next iteration of cron running.

    The indispensable swiss army knife of Drupal, Drush, has hook for Solr. Therefore, for someone like me who does almost everything from the command line, using drush was the natural fit for this task.

    To do this, in one terminal, I enter this command:

    while true; do drush @live --verbose solr-index; sleep 5; done
    

    This command runs the indexing in a loop, and is not dependent on cron. As soon as the 100 items (or whatever limit you have in your settings) is done, another batch is sent.

    In another terminal, you would monitor the progress as follows:

    while true; do drush @live solr-get-last-indexed; sleep 30; done
    

    Once you see that the number of items in the second terminal to stop increasing, you check the first terminal for any errors. Usually, it means that indexing is complete. However, if there are errors, they may be due to bad content in nodes, which needs to be fixed (e.g. bad fields) or unpublished as the case may be.

    Doing this reindexing on a Drupal 7.x site sending content to a Solr 4.x server, took from 11 pm to 1 pm the next day (14 hours), for 211,900 nodes. There was an overnight network disconnect for the terminals, and it was restarted in the morning, so the actual time is actually less.

    In all cases, this is much faster than indexing a few hundred items every 5 minutes via cron. That would have taken several days to complete.

    Aug 25 2015
    Aug 25

    The primary goal of this project was to introduce Wight’s new brand positioning, which shifted its identity from a “get it done, design-build” firm to one that focuses on world-class design and quality construction —  but not always both at the same time. To do this, we essentially split Wight’s extensive portfolio into two: one for design services, and one for delivery services. On the Home Page slideshow, when a user rolls over the “Design” side, she sees links to the markets, services, and projects that fit under design. When she rolls over “Delivery,” she sees a different set of links directing her to the markets, services, and projects relevant to delivery.

    Wight wanted to tell its story in a stimulating way — to inspire curiosity in users through thoughtful and unexpected details within the page design. Moments of surprise are scattered throughout the site, including within the prominent Home Page ampersand, which was inspired by the “&” in Wight & Company. When a user hovers over the symbol, it becomes a navigational item pointing to various process-centric pages on the site.

    An underlying goal of the project was to distinguish Wight from competing firms, many of which use a full-page, basic transition Home Page slideshow to showcase projects. To set Wight’s Home Page — and with that its work — apart from the rest, we built the slideshow from scratch so it can accommodate one image, two images, one video, or one video and one image.

    Wight has over 150 projects in its portfolio, and as is often the case with an architecture firm’s portfolio, the projects represent a wide range of content. While some projects lend themselves to an in-depth case study with a full slideshow of big, beautiful images, other projects are not as photogenic, and may not require detailed descriptions. We provided Wight with two separate project templates to suit these needs. In each version, staff can turn fields on or off based on available content. We also gave Wight’s internal staff the ability to exercise creative control over a number of site features, including the color of rollovers throughout the site.

    With a staff of 175, it was important to Wight to showcase staff of all levels, not just leadership. All staff members are represented on the People Page, which is sortable by leadership, design, delivery, corporate, and a variety of keywords ranging from capability to location. Bios for the leadership team contain a mix of images, text, and video.

    The new site is fully responsive and all pages — including the complex Home Page slideshow — look great on desktop, mobile, and tablet.

    In terms of development, this project took ten months to complete. We used agile project management and had milestones every two weeks to review and test specific sections of the site. In total there are 14 different page layouts used across the site that have all been functionally tested in the latest versions of Chrome, Firefox, Safari, Chrome for Android, iOS Safari, and Internet Explorer versions 8-11. In terms of build tools we relied on Sass, Gulp, Vagrant, Chef, and Git. On the back-end we developed five site-specific custom modules used for site settings, blocks, and other minor tweaks to the display and management of the site.  

    Aug 25 2015
    Aug 25

    This would be my last weekly update as far as Google Summer of Code 2015 is concerned. The long road is coming to an end as the season closes on Friday, 28th August 2015. This week I tackled a bug in core of Drupal which I discussed in my last week’s update.

    Fixing WWW-Authenticate

    This issue is #2553531 on the Drupal bug tracker. Previously when a user was accessing an area which required them to be logged in without logging in, Drupal would call authentication providers for a “challenge”. This challenge allows Basic Auth to specify it’s WWW-Authenticate header and send a HTTP 401 unauthorised error telling the user that they need to be logged in and can use Basic Auth as a means to log-in. This was good, as basic was the only protocol which would communicate via WWW-Authenticate until Hawk came along.

    WWW-Authenticate can have multiple values, a server sending WWW-Authenticate: Hawk, Basic for example is saying that the client can use hawk or basic auth protocol. This wasn’t possible in the current code base as Drupal did not allow multiple Auth providers to specify the challenge. I modified the code to allow multiple auth providers to send their challenge which gets compiled by the authentication provider manager into an exception. Previously, the auth provider would send an exception itself which is why multiple auth providers could not specify their own challenge.

    This fix is still to be accepted into Drupal core, although I hope it would get accepted soon.

    Concluding Summer of Code

    This would probably be the last coding I will be doing during Summer of Code, but it’s not last related to Drupal or my project as I plan to continue it’s development after GSoC as well and hopefully I get to stick around Drupal for a long time.

    I had a lot of fun during the summer, and I got to learn a lot of new things as well as got introduced to Drupal and it’s community. I worked on implementing a new protocol within PHP, developing a general purpose library which can be used by anyone willing to use the protocol with PHP and implemented the protocol as a Drupal module. All things that I have never done in the past, and the things I struggled with at times but ultimately learned them and managed to succeed to the best of my abilities. I also improved my understanding of concepts such as Dependency Injection, unit testing, composer, authentication and authorization as well as security concepts related to them, encryption, hashing and general Drupal architecture and development.

    For students participating in the future, don't hesitate to ask around the Drupal community via the forums or IRC if you get stuck doing something as they are very helpful. Drupal is a complicated beast and there are a lot of people apart form your mentor who are willing to help, it would also be faster at times when your mentor might not be available. I took a lot of help from the community during my project and the community really helped around.

    I’m glad to have taken part in this year’s summer of code and I will remember this experience forever. A big thanks to my mentor Jingsheng Wang (skyred) and the Drupal community for their support as well as Avantika Agarwal for proofreading my blog and documents related to Summer of Code. I will continue with what I started this summer of code and try to learn and share as many things as I can.

    Thank you!

    Aug 25 2015
    Aug 25

    Currently Drupal has naming conventions for branches and tags in git for contrib module. These are based on the core version then the module version, for example 7.x-1.x would create a dev version 1 for Drupal 7, 7.x-2.3 would create a stable release version 2.3 for Drupal 7.

    As we head towards Drupal 8 there has been a lot of talk about versioning for contrib. Core has already moved to using semantic versioning (semver), which is widely adopted by a lot of software now. Contrib is still on the old version numbering format. There is a lot of discussion about switching to something like semantic versioning for contrib. It’d be ideal to keep the core version somewhere in the number, there have been many suggestions, some of which are:

    • 2.3.0-d8
    • 2.3.0#d8
    • 2.3.0@d8
    • d8.2.3.0
    • 8.2.3.0

    My preferred, and it seems the favourite so far is 8.2.3.0, this is much like semver but the major version has been bumped down to make way for the core version, therefore core.major.minor.patch. The only possible issue here is if using composer for contib modules, composer will think the core version number is the major version number, and it will think the major version number is the minor version number. I feel that this is an ok compromise and we as developers can take this into account when using the syntax in composer.json.

    Another versioning related issue is that we currently add the version number into the contrib info file as part of the packager that creates the module zip or tarball files. If more people pull modules straight from git (via composer) they won’t have this version number, causing the core update module not to work.

    I say we should start asking module maintainers to add the version number to the info file. They already have to add the version number to the tag or branch, surely it’s no extra effort to add it to the info file, and saves so much effort trying to find a fancy programatic solution.

    Please enable JavaScript to view the comments powered by Disqus.

    blog comments powered by
    Aug 25 2015
    Aug 25

    I've spent a fair amount of time thinking about how to win back the Open Web, but in the case of digital distributors (e.g. closed aggregators like Facebook, Google, Apple, Amazon, Flipboard) superior, push-based user experiences have won the hearts and minds of end users, and enabled them to attract and retain audience in ways that individual publishers on the Open Web currently can't.

    In today's world, there is a clear role for both digital distributors and Open Web publishers. Each needs the other to thrive. The Open Web provides distributors content to aggregate, curate and deliver to its users, and distributors provide the Open Web reach in return. The user benefits from this symbiosis, because it's easier to discover relevant content.

    As I see it, there are two important observations. First, digital distributors have out-innovated the Open Web in terms of conveniently delivering relevant content; the usability gap between these closed distributors and the Open Web is wide, and won't be overcome without a new disruptive technology. Second, the digital distributors haven't provided the pure profit motives for individual publishers to divest their websites and fully embrace distributors.

    However, it begs some interesting questions for the future of the web. What does the rise of digital distributors mean for the Open Web? If distributors become successful in enabling publishers to monetize their content, is there a point at which distributors create enough value for publishers to stop having their own websites? If distributors are capturing market share because of a superior user experience, is there a future technology that could disrupt them? And the ultimate question: who will win, digital distributors or the Open Web?

    I see three distinct scenarios that could play out over the next few years, which I'll explore in this post.

    Scenario 1: Digital distributors provide commercial value to publishers (A1 ? A3/B3)

    Digital distributors provide publishers reach, but without tangible commercial benefits, they risk being perceived as diluting or even destroying value for publishers rather than adding it. Right now, digital distributors are in early, experimental phases of enabling publishers to monetize their content. Facebook's Instant Articles currently lets publishers retain 100 percent of revenue from the ad inventory they sell. Flipboard, in efforts to stave off rivals like Apple News, has experimented with everything from publisher paywalls to native advertising as revenue models. Except much more experimentation with different monetization models and dealmaking between the publishers and digital distributors.

    If digital distributors like Facebook succeed in delivering substantial commercial value to the publisher they may fully embrace the distributor model and even divest their own websites' front-end, especially if the publishers could make the vast majority of their revenue from Facebook rather than from their own websites. I'd be interested to see someone model out a business case for that tipping point. I can imagine a future upstart media company either divesting its website completely or starting from scratch to serve content directly to distributors (and being profitable in the process). This would be unfortunate news for the Open Web and would mean that content management systems need to focus primarily on multi-channel publishing, and less on their own presentation layer.

    As we have seen from other industries, decoupling production from consumption in the supply-chain can redefine industries. We also know that introduces major risks as it puts a lot of power and control in the hands of a few.

    Scenario 2: The Open Web's disruptive innovation happens (A1 ? C1/C2)

    For the Open Web to win, the next disruptive innovation must focus on narrowing the usability gap with distributors. I've written about a concept called a Personal Information Broker (PIM) in a past post, which could serve as a way to responsibly use customer data to engineer similar personal, contextually relevant experiences on the Open Web. Think of this as unbundling Facebook where you separate the personal information management system from their content aggregation and curation platform, and make that available for everyone on the web to use. First, it would help us to close the user experience gap because you could broker your personal information with every website you visit, and every website could instantly provide you a contextual experience regardless of prior knowledge about you. Second, it would enable the creation of more distributors. I like the idea of a PIM making the era of handful of closed distributors as short as possible. In fact, it's hard to imagine the future of the web without some sort of PIM. In a future post, I'll explore in more detail why the web needs a PIM, and what it may look like.

    Scenario 3: Coexistence (A1 ? A2/B1/B2)

    Finally, in a third combined scenario, neither publishers nor distributors dominate, and both continue to coexist. The Open Web serves as both a content hub for distributors, and successfully uses contextualization to improve the user experience on individual websites.

    Conclusion

    Right now, since distributors are out-innovating on relevance and discovery, publishers are somewhat at their mercy for traffic. However, a significant enough profit motive to divest websites completely remains to be seen. I can imagine that we'll continue in a coexistence phase for some time, since it's unreasonable to expect either the Open Web or digital distributors to fail. If we work on the next disruptive technology for the Open Web, it's possible that we can shift the pendulum in favor of “open” and narrow the usability gap that exists today. If I were to guess, I'd say that we'll see a move from A1 to B2 in the next 5 years, followed by a move from B2 to C2 over the next 5 to 10 years. Time will tell!

    Aug 25 2015
    Aug 25

    At Annertech, there are three things we take very seriously: website/server security, accessibility, and website load times/performance. This article will look at website performance with metrics from recent work we completed for Oxfam Ireland.

    We use a suite of tools for performance testing. Some of these include Apache Benchmark, Yahoo's YSlow, and Google's PageSpeed Insights. Our favourite at the moment is NewRelic, though this does come at a cost.

    Apache Benchmark (AB) is used for testing of the server application as well as load testing. It can identify whether or not your caching has been set up correctly and indicate what pages might be under-performing due to complex database queries.

    However, it doesn't render the page or execute the JavaScript so it is not helpful for front-end performance testing. As on average 90% of a web page's load time is accounted for by the front-end, this is where we focus most of our performance testing efforts.

    Areas we pay attention to when performing front-end testing include:

    • How long media assets take to load? This may indicate images in the content that are too large or too-high resolution. By reducing the file size of these images, we can improve the site load time.
    • Design assets, such as icons, can also be combined together in a single 'sprite', again reducing the load time as the number of files also reduces the time spent waiting.
    • Are there any scripts slowing down the site?
    • Identify which ones take longest and see if they can be tweaked or made asychronous.
    • Are there any CSS or JS files that can be compressed to make downloading and rendering quicker?

    After we run our AB tests, we like to use services such as:

    WebPageTest.org
    SpeedCurve.com
    Pingdom Tools
    Chrome Developer Tools

    Let's have a look at a case study of some of our recent work in this area.

    Case Study: Improving the performance of oxfamireland.org

    The Oxfam Ireland website was developed a number of years ago by Annertech, and while performance would have been important at the time, the reality is that a website can never be too fast. Oxfam asked us whether there were any marginal gains that were relatively quick to implement that we could deploy to the site.

    Benchmark

    If you can't measure it, your can't manage it. So the first step in improving performance is to see how the site currently stands.
    There are lots of different ways to test the performance of a website, and for many years, the trusty Apache Benchmarking tool (AB) was our key weapon. This tool is still very useful in determining raw server performance for serving php pages.

    However, in the case of Oxfam, we wanted something that was more relevant to real users. Enter "PageSpeed Insights".

    PageSpeed Insights

    Our first tool deployed was Google's PageSpeed insights. This is a free service run by google, which downloads, parses and grades a website's performance.

    The key difference over AB is that browser performance is tested – so all the assets required to render a page – HTML, images, CSS, JavaScript, fonts – are downloaded, including those on third party sites.

    PageSpeed insights runs a series of tests against the site, checking for various best practices, and returns a headline figure result.
    This can be a bit skewed, as the result can be gamed a little. The actual figure can be improved by adjusting some items than have no real impact for the actual site under test.

    Still – its gives us a grade, that we can aim to improve on.

    The grade returned two different values, one for mobile and one for desktop. We ran the test against two key pages on the site: the homepage, and the "Get Involved!" landing page.

    PageSpeed Insights report for Oxfam Ireland

    WebPageTest

    WebPageTest is another online testing tool, run by Patrick Meenan. While the UI might not be as nice as PageSpeed insights, the results returned are extremely detailed and very useful for in-depth performance monitoring and improvement.

    In particular, the tests are run twice against the site, so any efforts made to leverage browser-side caching on subsequent page loads are measured.

    For our purposes, we picked out 3 key metrics – SpeedIndex, Number of Requests and Page size. We aimed to reduce all of them. SpeedIndex is of particular interest. It is the average time at which visible parts of the page are displayed. From a user's perspective, this is a key value. There are other browser metrics that are measured, such as "DOM Content Loaded" and the "Onload" event, but SpeedIndex is really the best measure of "perceived performance" - as perceived by the end users.

    What we did to improve things

    Naturally a complete redesign/redevelopment was out of scope, and we're already using Drupal's inbuilt aggregation for CSS and JavaScript. The simplest tool at our disposal was the Advanced Aggregation module. However, this module isn't a straightforward 'set and forget' module, and takes some careful configuration and testing to produce the key results.

    Our key objective was to move as much render-blocking JavaScript from the header of the HTML document to the footer. We also optimised the 'bundles' of CSS and javascript aggregated that are generated, and minified the javascript as part of the aggregation process.

    How the numbers added up

    After we had finalised our adjustments to the site, and verified the improvements on our staging infrastructure, the changes were deployed to the live site. As our focus was improving perceived speed, it was encouraging to see the significant improvement in the 'SpeedIndex' value.

    On the Homepage first view, the value moved from 8373 to 7268, an improvement of 12.98% and on the repeat view, the value moved from 5487 to 4702, an improvement of over 14%.

    On the Get Involved page, we managed an improvement of over 10% on the first view, and almost 3% on the repeat view.

    The other benchmarked values weren't improved significantly on this phase of the work, and indeed, the page weight increased slightly. This is a feature of performance improvement where significant increases in one benchmark may come at the cost of another.

    The chart below shows the load time of Oxfam Ireland's home page before and after optimisation of the site. It shows the results for both initial visitors and repeat visitors, the latter being where their browser has cached some elements of the page.

    Oxfam Ireland website performance changes

    Click here to read the full results of the process.

    Ongoing

    Since this work was carried out, a significant design update was applied to the homepage on the site. Using our predetermined benchmarking tools and measures, we were careful not to throw away our performance gains recently made.

    The benchmarking process sets a line in the sand of where the website performance is currently at. Performance is now a key factor in any changes made to the website, and its has a significant effect on the bottom line.

    Aug 25 2015
    Aug 25

    Moodle is a free and open-source software learning management system written in PHP and distributed under the GNU General Public License. Moodle is used for blended learning, distance education, flipped classroom and other e-learning projects in schools, universities, workplaces and other sectors.

    Our main objective is that we wanted to manage all the users from Drupal i.e., use drupal as the front end for managing users. For this purpose, we have a moodle plugin and drupal module. Drupal services is a moodle authorization plugin that allows for SSO between Drupal and Moodle. Moodle SSO provides the Drupal functionality required to allow the Moodle training management system to SSO share Drupal sessions. 

    In order to make SSO work, we need to ensure that sites can share cookies. Drupal and moodle sites should have url like drupal.example.com and moodle.example.com. As mentioned earlier, sites should be able to share cookies. To make sites use shared cookie, we need set the value of $cookie_domain in settings.php file on the drupal site. In our case, the site urls was something like drupal.example.com and moodle.example.com. For these type of sub-domains, the cookie_domain value can be set like the below one:

    $cookie_domain = ".example.com";

    Note: The dot before "example.com" is necessary.

    Let's start with the steps that need to followed for achieving SSO between drupal and moodle:

    1. Moodle site

    2. Drupal site

    • We need to install all the dependency modules of Moodle SSO.
    • Configure Moodle SSO

      • Most of the settings would be preconfigured. We need to ensure services settings are proper. Check if muser, moodlesso, login, logout are all enabled at /admin/structure/services/list/moodlesso/resources.

    After doing all these configurations, we will be able to achieve the following things:

    • When we log into Drupal site, we will be automatically logged into Moodle site with the same account.
    • If the same account is not present in moodle, it will be automatically created.
    • Similarly logging out of the moodle site will automatically log out of drupal site as well.

    We wanted to import all the users from moodle to drupal. For this, we created a custom local plugin based on web service. From drupal site, we made a call to the web service function and got the list of all users in moodle. Using this list of users, we created them in Drupal site.

    The Drupal Moodle user integration is just a first step in the arena. We at Knackforge have worked on Course, Certificate integration between Moodle and Drupal. We would share that experience in the upcoming posts.

    Aug 25 2015
    Aug 25

    If you are planning to import data from database (MySQL, PostgreSQL) download the required database connector,

    For PostgreSQL, you can download here

    First step, configure the data source file in SOLR. To do this add the new file in SOLR home directory solr/<core>/conf/data-import.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <dataConfig>
      <dataSource   
        driver="org.postgresql.Driver"
        url="jdbc:postgresql://{host}:{post}/{database}"
        user="{username}"
        password="{password}"
      />
      <document name="doc">
          <entity name="prospects" 
              query="select id, name from users">
              <field name="id" column="id" />
              <field name="name" column="name" />
          </entity>
      </document>
    </dataConfig>

    This configuraion tells solr about your database credentials and fields that you want to import in order to enable search in SOLR.

    Solrconfig Changes :

    If required, you can also change the solrconfig.xml details to suit your requirements. Our next step is to add the dataimport handler in solrconfig.xml file and point the data source is going to be imported (data-import.xml).

    Also include the data-import handler library and postgres driver in solrconfig.xml file.

    <requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
      <lst name="defaults">
        <str name="config">data-import.xml</str>
      </lst>
    </requestHandler>

    Now you can start your server and go to Dataimport admin page under collection1. (http://{youripaddress}:8983/solr/#/collection1/dataimport/) Choose fullimport from command dropdown and select your entity and click execute to start index documents from your data source.

    If your import is successful you will see a green entry saying Indexing Completed as shown in the image below.

    Aug 25 2015
    Aug 25

    This post explains about creating slideshow in drupal. There are many ways and plugins available to create slideshow in drupal and I am going to discuss some methods which will be very efficient and useful.

    1) Using Views slideshow module

    2) Using jQuery cSlider plugin

    3) Using Bootstrap carousel

    1. Using Views slideshow module:

    The modules required for this method are:

      1) Views

      2) Views slideshow

      3) jQuery cycle plugin ( Download here and place it at sites/all/libraries/jquery.cycle/)

    Enable the added modules. To create views slideshow, create a new content type for instance "Slideshow" with an image field which can be used as slideshow image.

    Add multiple slideshow nodes with images. Then, we have to create a view block with slideshow content. Select "slideshow" as required format and configure transition effect in the Settings link.

    After saving this view, place this view block at neccessary region at admin/structure/blocks.

    2. Using jQuery cSlider plugin:

    1) You can download this plugin from here. There is also a demo file in this plugin which can be used as a reference.

    2) Copy style.css from css folder and jquery.cslider.js and modernizer.js from js folder

    3) Use simple classes to add sliding effect to images and text to the slides.

    <div id="da-slider" class="da-slider">
      <div class="da-slide">
        <h2>Some headline</h2>
        <p>Some description</p>
        <a href="#" class="da-link">Read more</a>
        <div class="da-img">
          <img src="images/1.png" alt="image01" />
        </div>
      </div>
      <div class="da-slide">
        <!-- ... -->
      </div>
        <!-- ... -->
      <nav class="da-arrows">
        <span class="da-arrows-prev"></span>
        span class="da-arrows-next"></span>
      </nav>
    </div>
    <div id="da-slider" class="da-slider">
      <div class="da-slide">
        <h2>Some headline</h2>
        <p>Some description</p>
        <a href="#" class="da-link">Read more</a>
        <div class="da-img">
          <img src="images/1.png" alt="image01" />
        </div>
      </div>
      <div class="da-slide">
        <!-- ... -->
      </div>
        <!-- ... -->
      <nav class="da-arrows">
        <span class="da-arrows-prev"></span>
        <span class="da-arrows-next"></span>
      </nav>
    </div>

    It can also be used as block by adding a separate template file for this slideshow.

    3. Using Bootstrap carousel:

    If you are using bootstrap theme, then creating a slideshow is quite easy. Bootstrap uses carousel.js to add slideshow effects. Here is a sample code:

    <div id="sample_carousel" class="carousel slide" data-ride="carousel">
      <!-- Indicators -->
      <ol class="carousel-indicators">
        <li data-target="#sample_carousel" data-slide-to="0" class="active"></li>
      </ol>
    
      <!-- Wrapper for slides -->
      <div class="carousel-inner" role="listbox">
        <div class="item active">
          <img src="sample.jpg">
        </div>
      </div>
    
       <!-- Left and right controls -->
      <a class="left carousel-control" href="#sample_carousel" role="button" data-slide="prev">
        <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
        <span class="sr-only">Previous</span>
      </a>
      <a class="right carousel-control" href="#sample_carousel" role="button" data-slide="next">
        <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
        <span class="sr-only">Next</span>
      </a>
    </div>

    The outermost <div>:

    Carousel requires the use of a id (in this case id="sample-carousel") for carousel controls to function properly.

    The class="carousel" specifies that this <div> contains a carousel. 

    The .slide class adds a CSS transition and animation effect, which makes the items slide when showing a new item. Omit this class if you do not want this effect.

    The data-ride="carousel" attribute tells Bootstrap to begin animating the carousel immediately when the page loads.

    The "Indicators" part:

    The indicators are the little dots at the bottom of each slide (which indicates how many slides there are in the carousel, and which slide the user are currently viewing).

    The indicators are specified in an ordered list with class .carousel-indicators.

    The .data-target class points to the id of the carousel.

    The .data-slide-to class specifies which slide to go to, when clicking on the specific dot.

    The "Wrapper for slides" part:

    The slides are specified in a <div> with class .carousel-inner.

    The content of each slide is defined in a <div> with class .item. This can be text or images.

    The .active class needs to be added to one of the slides. Otherwise, the carousel will not be visible.

    The "Left and right controls" part:

    This code adds "left" and "right" buttons that allows the user to go back and forth between the slides manually.

    The data-slide attribute accepts the keywords "prev" or "next", which alters the slide position relative to its current position.

    Some more slideshow modules:

    Aug 24 2015
    Aug 24

    One of our key values at the Drupal Association is communication:

    We value communication. We seek community participation. We are open and transparent.

    One of the ways that we try to live this value is by making our numbers -- both operating targets and financial -- available to the public. The monthly board reports share basic financial numbers and all our operational metrics. Once a quarter, we release full financial reports for the previous quarter. You can access all this information at any time on the Association web site.

    At the close of each year, we take the opportunity to have our financials reviewed (and sometimes audited). The review process ensures that we've represented our financials properly. This work takes some time. Though our fiscal year closes on 31 December, it takes six to eight weeks to get the final bits and pieces handled in our financial systems. The independent review or audit adds another 8+ weeks to the process of closing out our year. Then we have to review the findings with the Finance Committee and the full Board before we share them publicly. That's why it's August and we're just now sharing the 2014 reviewed financial statements with you.

    In 2014 we also began tracking our progress towards several operational goals for the first time. Though we share those numbers every month in the board report, we pulled some of our favorite stats and stories together into an Annual Report to share the work that our financials represent.

    What happened in 2014?

    2014 was an investment year. Per our Leadership Plan and Budget for the year, our key focus was building an engineering team to first address technical debt on Drupal.org and then take on actual improvements to the site. We purposely built a budget that anticipated a deficit spend in order to fully fund the team. The intent was to also build some new revenue programs (like Drupal Jobs) that would ramp up and eventually allow us to fund the new staff without deficit spending. And that's what we did. We went from two full time staff focused on Drupal.org to ten.

    The investment has been paying off. We spent a lot of 2014 playing catch up with technical debt, but also managed to improve site performance markedly while also increasing the portability of our infrastructure. On top of that, staff worked with community volunteers to release new features related to commit messages, profiles, and Drupal 8 release blockers. Most importantly, staff and the working groups prioritized upcoming work and published a strategic roadmap for improvements to Drupal.org.

    We held two huge DrupalCons, one in Austin and one in Amsterdam, and planned for a third. Our very small team of events staff and a crew of remarkable volunteers hosted over 5,500 people across our two events, all while planning our first Con in Latin America. We had some stumbling blocks and learning opportunities, and have been applying what we learned to the three 2015 DrupalCons.

    We launched Drupal Jobs. This was something the community asked for very clearly when we conducted a 2013 study. We’ve seen steady growth in usage since our quiet launch and will continue to refine the site, including our pricing models, so that it is accessible to Drupalers around the world.

    We diversified our revenue streams. DrupalCons used to be 100% of our funding. Not only is this a risky business strategy, it puts undue pressure on the Cons to perform financially, leaving us little room to experiment or make decisions that may be right for attendees, but could negatively impact the bottom line. As we increase the funding sources for the Association, we can make more and different choices for these flagship programs and also grow new programs with the community.

    We introduced branded content including white papers, infographics, and videos. These materials have been widely used by the community and have helped us understand the Drupal.org audience in a better way. You can see a lot of this work on the Drupal 8 landing pages, where the key content pieces were downloaded thousands of times in 2014.

    We released new vision, mission, and values statements for the Association. These tools are really useful in defining the focus of the organization and helping to guide how we get our work done. Working in a community of this size and diversity is extremely challenging. There is no choice we can make that will include everyone’s ideals, but our values help us make those decisions in a way that allows for transparency and open dialogue with the community. It’s something that we try to honor every day.

    What about money in 2014?

    As anticipated, we ran a deficit in 2014. However, we did manage to grow our overall revenue by about 6% from 2013 to 2014. This trend has continued into 2015, though not at the rate we had hoped. Still, we are now on track to support the investment we made in 2014 into the future. Another key win in 2014 is that we grew non-DrupalCon revenue to 21% of our total revenue. Diversifying our revenue streams reduces our financial risk and takes the pressure off of Cons, allowing us to experiment more.

    I want all the details

    Excellent! You can check out:

    Pages