Planet Drupal

Subscribe to Planet Drupal feed
Drupal.org - aggregated feeds in category Planet Drupal
Updated: 58 min 55 sec ago

Dave Hall Consulting: Interacting with the Acquia Cloud API with Python

Mon, 21/07/2014 - 10:54

The Acquia Cloud API makes it easy to manage sites on the platform. The API allows you to perform many administrative tasks including creating, destroying and copying databases, deploying code, managing domains and copying files.

Acquia offers 2 official clients. The primary client is a drush plugin which can only be downloaded from Acquia Insight. The other is a PHP library which states in the README that it is "[n]ot ready for production usage".

On a recent project using WF Tools we needed some pretty advanced deployment scripts for sites hosted on Acquia Cloud. We had tried using a mix of bash and PHP, but that created a maintenance nightmare, so we switched to Python.

I was unable to find a high quality Python library, so I wrote a python client for the Acquia Cloud API. The library implements all of the features that we needed, so there is a few things missing.

Chaining complex commands together is easy because the library implements a fluent interface. An extreme example of what is possible is below:

import acapi # Instantiate the client c = acapi.Client('user@example.com', 'acquia-token') # Copy the prod db to dev, make a backup of the dev db and download it to /tmp c.site('mysite').environment('prod').db('mysite').copy('dev').backups().create().download('/tmp/backup.sql.gz')

Some of the code is library is "borrowed" from the Python client for Twilio. The library is licensed under the terms of the MIT license.

I am continuing to develop the library. Consider this a working alpha. Improving error handling, creating a comprehensive test suite and implementing the missing API calls are all on the roadmap. Pull requests are welcome.

The code is PEP 8 (coding standards and PEP 257 (documentation standards) compliant and uses the numpydoc for code documentation.

Check out the Python client for Acquia's Cloud API on github.

Categories: Elsewhere

godel.com.au: Creating an immersive Drupal front-end with Yes Way

Mon, 21/07/2014 - 09:20
Mon July 21, 2014 Creating an immersive Drupal front-end with Yes Way

Yes Way are a creative agency who connect businesses, brands and communities with the creative talent they need. They specialise in strategic planning for businesses and representation for creative individuals to engage their target audience through branding, events and marketing.

The brief

Godel were approached by Yes Way to help complete designs for their website update and produce a custom responsive website built in a Drupal 7 backend with a totally custom front-end that leveraged a minimalist and modern Aurora subtheme, Singularity grids and a lot of Javascript via Drupal behaviors.

The brief was to create a vibrant online presence to reflect the creatives that Yes Way represent; specialists in photography, street art, fine art, illustration and fashion styling. Yes Way wanted to stick with their existing branding, but give it new life through a new design. As such, the new site design that we created for Yes Way is not only clean and minimalist with a typographic focus, but also projects a vibrant persona, bringing creative talent to the forefront through their personal profiles and visual portfolios.

Working on projects like this is a great experience as it allows us to work closely with the client to iteratively improve on an existing product. Although we did the redesign and site build in a short period of time this time, this sort of iterative improvement process can work as on ongoing agreement as well, allowing us to build trust with our clients and gradually make improvements to their product over time, keeping it up to current standards in design and dev and allowing the client freedom to make suggestions based on their changing needs.

The site

Yes Way's new landing page features a full length background image and a retractable navigation which engages as soon as the viewer starts scrolling. More information is revealed about Yes Way as you scroll down past each header and when the a navigation menu item is clicked the screen smoothly transits to the appropriate area on the site using jQuery.

Godel wanted to bring the site up to date with dynamic and responsive features. Responsive design elements include the use of mmenu which creates a slick, user-friendly navigation pattern for mobile devices. The desktop functions as a "one pager" with some pop-up overlays. The navigation uses the scrollTo library to hijack the normal scrolling behaviour of the browser when the user clicks a menu item from the sticky header. The idea was to make site navigation as easy and fun as possible - the user never has to reload the page or follow a series of links, only interact with a single page.

All of the second-level sections are created using a nice little technique we've created using data-attributes. It allows us to create an immersive Javascript-powered app-style front end for a Drupal CMS backend, which creates websites that don't necessarily have to look "like Drupal sites".

Data attributes and custom display suite fields

This section is a brief technical explanation of our technique, skip it if it's Greek to you!
The day we learnt about custom display suite fields from This PreviousNext blog post was a happy day for us. Although DS offers a lot of great tools for UI-focused node display building, for devs who want more control it was starting to feel a bit limiting. We didn't want to go down the php field route (shudder) so we were happy to be able to create fields with PHP possibilities through this custom DS field technique.

One of the best things about the custom fields is the ability to generate fields that actually contain more data than the eye can see, stored in data attributes of HTML elements away from the visible part of the DOM. For example, we were able to store all of the data for an artist portfolio popup in the teaser tile for that artist that appears on the initial page load. What that means is that when the user clicks on an artist's face to view their portfolio, it loads dynamically in to the page via Javascript and that data that it displays is already stored on the page, just hidden.

First, we define the info hook for our field:

/** * Implements hook_ds_fields_info. */ function gp_global_ds_fields_info($entity_type) { $fields = array(); $fields['node']['body'] = array( 'title' => t('Body data attribute'), 'field_type' => DS_FIELD_TYPE_FUNCTION, 'function' => 'gp_global_ds_field_body', ); if (isset($fields[$entity_type])) { return array($entity_type => $fields[$entity_type]); } return; }

Then we make the markup for the field itself, which is surprisingly simple:

/** * Return the body as a div with a data attribute. */ function gp_global_ds_field_body($field) { $entity = $field['entity']; if(isset($entity->body[LANGUAGE_NONE][0]['safe_value'])){ $data = $entity->body[LANGUAGE_NONE][0]['safe_value']; $content = '<div class="body" data-body="' . check_plain($data) . '"></div>'; return $content; } }

The key is "data-body", a custom data attribute we create and then store the body text in. It doesn't get rendered on the page until we grab it with our Javascript, like this (abridged version):

(function($, undefined) { // We get the element that has the data-attribute on it and extract the data from the attribute bodyEl: '.fullwidth .body', _this.bodytext = $(element).find('[data-body]').data('body'); bodyText: function bodyText() var _this = Drupal.behaviors.overlayAnimate; // We replace the HTML of the blank element with the data we grabbed earlier. $(_this.bodyEl).html(_this.bodytext); }, }) (jQuery); Why this technique is meaningful

We think it's a step towards creating a better reputation for Drupal by creating beautiful sites that don't necessarily need to use the template themes Drupal provides. We use techniques like this in combination with very bare themes to build up our own custom front-end markup.

You can see this technique in action with the unique hover state overlays for each featured artist on the main page. The user can click through to more information about each person including a written blurb, gallery of images and even a video. For each of those things, the data is entered as a node in the Drupal backend, sent to the front of the site as a data attribute in a custom display suite field and triggered in to visibility via Javascript.

All in all, the user experience is intended to have an immersive web-app feeling, with content loading in to the page quietly, displayed in seamless overlays rather than new page loads and making them most of a one-page layout with some animated navigation styles. Yes Way are able to keep users on their site for longer by holding their attention for longer. Because users aren't directed off site (not even off-page!) they're more likely to click around and explore the single page they see. Because we already load the data into the page before we display it, they get the added benefit of a fast-loading site as well.

We think the result is an engaging site that uses some cool techniques to satisfy a real business need. Check out the website here!

Emma ForsterProject managerEmma manages our client relations and sits in between the dev team and the site owner to facilitate efficient, productive and fun projects. Ideas to help keep your Drupal project secure against the OWASP Top 10 Fri July 11, 2014 I'm sure you've heard the phrase "Security is a process, not a product" before, or something along those lines. Drupal has a pretty good track record as far as Web-based CMS security goes, and there's a dedicated team of experts looking after Core and Contrib, but it's no secret that...
Categories: Elsewhere

Larry Garfield: An open letter to conference organizers

Sun, 20/07/2014 - 01:51

Let's be honest, I spend a lot of time at conferences. Over the past 2 years or so I've averaged more than one speaking engagement at a conference per month, including a half-dozen keynotes. I've also helped organize several conferences, mostly DrupalCamps and DrupalCons. I'd estimate conferences make up more than a third of my professional activity. (Incidentally, if someone can tell me how the hell that happened I'd love to hear it; I'm still confused by it.)

As a result I've gotten to see a wide variety of conference setups, plans, crazy ideas, and crazy wonderful ideas. There are many wonderful things that conference organizers do, or do differently, and of course plenty of things that they screw up.

I want to take this opportunity to share some of that experience with the organizers of various conferences together, rather than in one-off feedback forms that only one conference will see. To be clear, while I definitely think there are areas that many conferences could improve I don't want anyone to take this letter as a slam on conference organizers. These are people who put in way more time than you think, often without being paid to do so, out of a love for the community, for learning and sharing, and for you. Whatever else you may think about a conference or this list, the next time you're at a conference take a moment to find one of the organizers and give them a huge hug and/or firm handshake (as is their preference) and say thank you for all the work that they do.

read more

Categories: Elsewhere

MariqueCalcus: Optimize before you go live (Part 2).

Sat, 19/07/2014 - 17:30
Part 2: Site builder

Drupal is a powerful content management framework but it's even better when you take into account the 20000+ modules and themes provided by the community. Whatever you are building, you will most likely find a module to help you. When you embrace the wonderful world of free and open source code, keep in mind that end users and search engines actually prefer fast websites. In this article we will discuss some common pitfalls that should be avoid, and will give some suggestions for site builder to create light and fast websites. This post is part of a multipart series. The first instalment was related to performance for back-end developer.

Read More...
Categories: Elsewhere

Drupal core announcements: Tuesday, July 29: Drupal 8.0.x being branched for semantic versioning

Sat, 19/07/2014 - 00:15
Start:  2014-07-29 12:00 - 14:00 America/New_York Online meeting (eg. IRC meeting)

On this date, the new 8.0.x branch for Drupal 8 will be created so we can start using the new Drupal release cycle in advance of beta 1.

Steps involved are:

  • drumm will create the 8.0.x branch
  • Existing issues will be moved automatically from 8.x-dev to 8.0.x-dev (this may take a couple of hours)
  • Testbot will be patched to look at the new 8.0.x branch instead of the old 8.x branch.

After we're sure there is no fallout from this, the README.txt on the old 8.x will be amended to inform about the change, and then the 8.x branch will be removed entirely after a few days.

Core developers should do the following once the process is complete to ensure they're patching against the latest version of the code:

git fetch
git checkout 8.0.x

Woohoo!

Categories: Elsewhere

Propeople Blog: Building Quality Into Drupal Development Workflow

Fri, 18/07/2014 - 20:29
Background 

Building a large Drupal website can be a daunting and complex process. There are many engineering, project and other risks associated with it. More often than not, budget and deadline overrun occurs.

Moreover, large projects often result in a prolonged Q/A, testing and troubleshooting period which once again can pose additional risks. 

Propeople was recently presented with the following challenge by a client:

 
  • 1200 budget hours

  • 2 month of development time

  • 4 developers

  • 1 hard launch date

To add another challenge to the mix, there was minimal Q/A engineer availability for the project.

In order to meet the client’s budget and timeline requirements above, we needed to rethink a new development workflow that largely incorporated quality into the project in order to meet both the deadline and budget requirements. 

 Typical Development Workflow 

Propeople selected GIT as the revisioning software to manage the development process/workflow for the project. GIT is a popular, open source distributed versioning system used by many organizations of all sizes. For more information on GIT, you can visit this site.

Organizations that employ a repository management system such as GIT, typically one of the following workflow models is used.

 1. Using the Master Branch

This workflow is typically employed by smaller organizations with a small number of developers working on the project. In this workflow, all of the code changes are committed into the master branch by all of the developers. It results in a linear development workflow:

This workflow works well at keeping everything simple, allowing developers to avoid branching and merging. It also allows for the creation of some tags to designate stable release or state of the code repository.

However, there are many drawbacks to this workflow. One of the most overlooked facts is that most likely, John and Joe will not check each other’s commits. Once a change is committed to the master branch, the change is incorporated into the project until someone notices any poorly written code or commits. 

 2. Development -> Stage -> Production

One of the most widely adopted workflows, this three-tiered workflow fully leverages GIT’s ability to create and merge branches. It also gives web developers the ability to mirror the branches to a different “working environment” so that they can have:

  • Development website

  • Staging website

  • Production website

3. Feature Branch

We ultimately chose to adopt a “feature” branch workflow for this project. This model takes advantage of the git branching/merging model. It is also chosen because we did not necessarily need a “staging” or “production” environment during the agile development phase.

This workflow works well at keeping everything simple, allowing developers to avoid branching and merging. It also allows for the creation of some tags to designate stable release or state of the code repository.

However, there are many drawbacks to this workflow. One of the most overlooked facts is that most likely, John and Joe will not check each other’s commits. Once a change is committed to the master branch, the change is incorporated into the project until someone notices any poorly written code or commits. 

 

Introduction of Github and the Magical Pull Request

 

One of the biggest reasons that we adopted the feature branch approach is Github. Github.com is one of the longest-running and most popular hosted git management platforms. It offers many developer friendly tools. One of the most useful and popular tools and functions is the Pull Request.

 Looking ahead

We are looking ahead to adding automated regression testing to the pull requests. This will allow developers to easily see page changes caused by their commits.

A more integrated issue and time tracking system would help consolidate all of the project efforts into Github. We used a separate issue tracking and hour tracking system for the project.

 Conclusion

Largely due to the new development workflow, we were able to meet the the hard deadline set by client. Although the project had a 8% budget overrun, this number is a great success, given the 27%* industry average. We were also able to reduce our post launch Q/A cycle by 66.67%, from 30 days to 10 days.

A big thanks to the masterminds behind the new development workflow:

Yuriy Gerasimov (https://www.drupal.org/user/257311)

Andriy Podanenko (https://www.drupal.org/u/podarok)

 

http://hbr.org/2011/09/why-your-it-project-may-be-riskier-than-you-think/

 

Tags: CIGITContinuous IntegrationQ/AProjectService category: TechnologyCheck this option to include this post in Planet Drupal aggregator: planetTopics: Tech & Development
Categories: Elsewhere

Forum One: Building Your (Drupal) Business: What Keeps You Up At Night?

Fri, 18/07/2014 - 16:57

How to get more business in the door, and once you have it – how in the world to get it all done?!

These were some of the issues that “keep them up at night”  raised by business owners in the Drupal professional services sector at the recent DrupalCon in Austin, TX.  I’ve co-led a “Bats of a Feather”  session at DrupalCon for three years now for business owners on the key issues they face; this year we had, again, a highly engaged audience of about 40-50 business owners and leaders join. Sean Larkin of ThinkShout, a digital agency in Portland, OR, joined me in facilitating the discussion. The attendees were all from consulting / professional services firms, ranging in size from 1 to 80, with a median size of about a dozen employees.

We listed and clustered the topics / questions of primary interest (see picture of our flip chart notes), which were:

  • Business development and lead generation – how to keep work flowing in
  • Growth and capacity – how to balance hiring with business inflow
  • Support and hosting – how to provide effective support and hosting services
  • Scaling a sales team
  • The Acquia effect – how Acquia’s presence affects Drupal agencies
  • Partnering with other firms.

We homed in on the two ends of the business pipeline – how to bring in more work, and how to scale the business once you have the work. Here are a few of the highlights:

Subcontracting

We had a lively discussion about whether and how to work as a subcontractor to other larger firms as a way to keep busy. Some folks are happy to do “white label” work for which they do not need to do business development, while others avoid it.

Pros: Tap into the clientele and BD pipeline of a larger organization that already has a backlog.

Cons: You’ll never build your own vision of your company if you are anonymous and behind someone else, your rates will never be as good, and you might sometimes end up being the scapegoat.

Interestingly, at Forum One, we did not subcontract for larger firms in our early growth stages, but it has become a sizable part of our portfolio in recent years.

Partnering

We had good discussion about partnering among other firms – finding the businesses in your area that have similar or complementary offerings, and looking to scratch each others’ backs. The Drupal share of the total web CMS market pie is still small, so we can all pitch in with each other to make the pie even bigger.

Why grow?  A lot of the owners from solo or very small shops have to do everything from bringing in the business to doing the work and sending the invoices. Not to mention cleaning the bathroom before a client comes over (been there). They are eager to grow out of that stage and have help so they can focus on what they feel they are best at. But how far to grow? One of the owners spoke about his satisfaction with having a 15-person team that was cohesive, cooperative, and did great work for their clients; he said he had no aspirations to grow beyond that and have bigger headaches.  It’s great that he’s clear about his goals for the business and is on track.  Others talked about wanting to build bigger practices.

At Forum One, I’ve been in the thick of all these stages of growth, from a small team of three doing everything, to a multidisciplinary team of about 80. In our case, we’ve chosen to grow aggressively for three main reasons: to expand the capabilities we can offer our clients, increase the impact of our work for our clients, and offer growing career opportunities to our team.

Taking big steps

A few of the attendees said they are grappling with issues of when and how to take their next big step – whether it’s hiring their first staff person, signing a lease for office space, or bringing on their first operational hire (project manager, BD person, operations manager, etc.). We did not have time to talk about these issues, but I think those of us who have been through these big steps were smiling to ourselves. I know I was. Not because we know the answers – there are no easy ones. But we’ve been through it and know that those stages are part of the excitement and the challenge of building a business out of nothing!

For further dialogue and networking on these topics, check out and join the LinkedIn group for owners of Drupal services firms called “Drupal CxO Owners Network.”

Categories: Elsewhere

ThinkShout: Getting Started with SASS for Drupal and Zen, Part II

Fri, 18/07/2014 - 15:00

In part one of "Getting Started with SASS for Drupal and Zen," we went over getting your environment set up to work with SASS.

If you followed the instructions in part one, you should have SASS/Compass, Zen, and your sub-theme installed. Your theme will be installed in sites/all/YOUR THEME NAME.

Test the Install

Let's test to see if SASS is installed and compiling. Use your toolkit to compile your SASS directory or run compass watch from the command line in your theme directory. You should see the following output.

>>> Compass is watching for changes. Press Ctrl-C to Stop

To see more Compass commands, you can run Compass -h.

Open your Drupal site in your browser. Now that we are polling for changes with Compass, let's add the following to style.scss to see our changes being applied. After you save your change, refresh your page and you should see the difference.

body { background: #000; color: #fff; }

Compass will also output the overwritten files in your console if you are using command line to run it. It's okay to delete the CSS you added, so things will appear like the default Zen theme.

SASS Primer

If you haven't used SASS, prepare to be hooked on it. Some advantages of SASS include DRY (Don't Repeat Yourself), CSS, function (mixins) for repetitive and lengthy blocks of CSS, and the ability to extend common styles.

Variables

Variables in SASS start with a '$'. Use variables to define values you will use throughout your stylesheets. For example, let's define our color palette in _init.scss. There is a commented section for colors. You can drop them in there. I'm going to grab this zen 2 palette from Kuler.

$sand: #b0ae9e; $brown: #424345; $white: #fafeff; $seagreen: #9dbec7; $wetsand: #b0a092; $red: #ff0000; $gray: #a1a1a1;

Now these colors can be used everywhere in our stylesheets without having to write the hex value each time.

Nesting

In typical CSS fashion, we would write a style like this:

a { color: #9dbec7; text-decoration: none; } a:hover { color: #424345; -webkit-transition: color 0.5 ease-out 0.5s; -moz-transition: color 0.5 ease-out 0.5s; -o-transition: color 0.5 ease-out 0.5; transition: color 0.5 ease-out 0.5s; }

With SASS, we can nest the style like this:

a { color: $seagreen; text-decoration: none; &:hover { color: $brown; -webkit-transition: color 0.5s ease-out 0.5s; -moz-transition: color 0.5s ease-out 0.5s; -o-transition: color 0.5s ease-out 0.5; transition: color 0.5s ease-out 0.5s; } }

The ampersand represents the outer anchor selector. Also, notice how we are relying on the variables we defined for the colors instead of using hex values.

Mixins and Extends Mixins

Let's clean up that transition by writing a mixin for it.

@mixin transition($property, $duration, $easing) { -webkit-transition: $color $duration $easing; -moz-transition: $color $duration $easing; -o-transition: $color $duration $easing; transition: $color $duration $easing; }

Now we can rewrite the anchor style and include the transition mixin.

a { color: $seagreen; text-decoration: none; &:hover { color: $brown; @include transition(color, 0.5s, ease-out, 0.5s); } }

Keep in mind that Compass already provides some great cross-browser mixins for CSS3. Style transition is one of them.

Extends

SASS lets you inherit common styles. A practical example is styling buttons. Buttons might have common styling, but differ in color or size.

// This is a SASS comment /* This is also a comment */ // Our default button .button { background: $seagreen; padding: 1em; border: 1px solid $seagreen; } .primary { @extend .button; padding: 1.5em 2em; } .warn { @extend .button; background: $red; } .disabled { @extend .button; background: $gray; }

So why didn't we just use nesting? Extending keeps you from having to write multiple class names on html elements instead of writing it like the following:

<a class="button primary" href="http://thinkshout.com">ThinkShout</a>

We can use one class because 'primary' will include all the same styles as 'button.'

<a class="primary" href="http://thinkshout.com">ThinkShout</a> Using SASS in Your Theme

The stylesheets in your Zen sub-theme are organized according to the principles of SMACSS. You'll notice the style.scss file doesn't actually contain any styles, but only imports. The _init.scss file contains additional imports such as Zen Grids and Compass utilities, mixins and helpers. If you look in layouts/responsive.scss, you'll see the Zen theme includes a mobile-first responsive layout by default.

Let's add some sass of our own. Add a file called _main-nav.scss to the components directory. In that file, add the following SASS. It's similar to the style we used in our SASS primer.

#navigation { background: $sand; .links { a, a:visited { color: $white; text-decoration: none; &:hover { color: $brown; @include transition(color, 0.5s, ease-out, 0.5s); } } } }

In order to get this change to take effect, you need to import it into your style.scss. Add an import statement for _main-nav.scss in the components section.

/* Component (SMACSS module) rules */ @import "components/misc"; @import "components/main-nav"; // Add this import statement

You may be wondering why you don't need the underscore in front of the file when importing. The underscore tells SASS that the file is a partial. The partial won't be compiled into its own file. It will be included in the style.css when compiled. If you don't have Compass running, go ahead and run compass watch in your theme directory or use your toolkit to compile. You should see your navigation style applied to your Drupal site when you refresh.

As you progress in your SASS development, I encourage you to use the SASS Globbing gem. It makes importing a breeze.

Now that you have used SASS in your theme and have the basics down, be sure to check out the SASS and Zen Grids documentation to be even more productive in your theme development. Get the code for this article on Github.

Categories: Elsewhere

Drupal Easy: BYOD (Bring Your Own Developers) Drupal Career Training

Thu, 17/07/2014 - 23:11

With four sessions graduating more than 60 People over the past four years, there's no doubt that the Drupal Career Starter Program can bring aspiring developers from zero to hero in just a matter of a few months. Imagine what it can do for you, or your people, who are already developers, but need to be trained up in Drupal. We have, and are making it highly accessible in a live, online format designed to fit into working schedules.

The upcoming Drupal Career Online training program kicks off in just about a month, and your organization now has the ability to choose the developer(s) that match well to your team and leverage our unique, holistic training to turn them into a solid member of your Drupal development team.

-->

read more

Categories: Elsewhere

Drupal core announcements: Drupal core updates for July 16, 2014

Thu, 17/07/2014 - 22:45
What's new with Drupal 8?

This week saw the commit of part one and two of the major menu-system rewrite in which menu-links become plugins. The original patch weighed in at over 600kb and was one of the remaining seven beta-blockers. Splitting it into five separate issues made reviews more forthcoming and this was evident with part one and two moving quickly from needs review to RTBC to ultimately being committed. Reviewers have now moved onto parts three through five.
There was a massive volume of commits this week with cleanups keeping the committers very-busy, lots of deprecated functions were removed and lots of procedural menu and form code was ported to the new Object-oriented approaches.

Where's Drupal 8 at in terms of release?

In the past week, we've fixed 3 critical issues and 8 major issues, and opened 5 criticals and 9 majors. That puts us overall at 107 release-blocking critical issues and 623 major issues.

Outstanding beta blockers

Outstanding critical issues in Drupal 8

Outstanding major issues in Drupal 8

Where can I help? Top criticals to hit this week

Each week, we check with core maintainers and contributors for the "extra critical" criticals that are blocking other work. These issues are often tough problems with a long history. If you're familiar with the problem-space of one of these issues and have the time to dig in, help drive it forward by reviewing, improving, and testing its patch, and by making sure the issue's summary is up to date and any API changes are documented with a draft change record, we could use your help!

More ways to help

Issue #1679344: Race condition in node_save() when not using DB for cache_field recently caused a Drupal.org outage. The issue already has a proposed resolution recommended in comment #24 — help out by reviewing the patch for either D7 or D8.

Additionally, there are a bunch of easy documentation issues which need some help moving forward. For each of these, there is a "Child Issues" sidebar. Look there for issues that are "active", "needs work", or "needs review":

As always, if you're new to contributing to core, check out Core contribution mentoring hours. Twice per week, you can log into IRC and helpful Drupal core mentors will get you set up with answers to any of your questions, plus provide some useful issues to work on.

You can also help by sponsoring Drupal core development.

Notable Commits

The best of git log --since "1 week ago" --pretty=oneline (112 commits in total):

  • Various conversions of controllers and forms to OO code, only a handful remain now
    • Issue 2010246 by tim.plunkett, tkuldeep17, plopesc, InternetDevels, pfrenssen, googletorp: Convert update_manager_install_form, update_manager_update_form, update_manager_update_ready_form to the new form interface.
    • Issue 2030165 by Berdir, tim.plunkett, vijaycs85, tkuldeep17 | rteijeiro: Convert form_test_* functions to classes.
    • Issue 1978926 by likin, YesCT, Pancho, kim.pepper, h3rj4n, tim.plunkett, disasm, Luxian, neetu morwani | vijaycs85: Convert locale_translation_status_form to a Controller.
    • Issue 2132477 by tkuldeep17, tim.plunkett | shameemkm: Convert batch_test forms to controllers.
    • Issue 2086499 by phiit, tim.plunkett | Gábor Hojtsy: Convert two page callbacks in language_elements_test.module to the new controller system.
    • Issue 2078867 by tim.plunkett, jackbravo, ianthomas_uk, InternetDevels, piyuesh23, disasm, nano_monkey | vijaycs85: Convert _form_test_* functions to classes.
    • Issue 1998198 by pwolanin, splatio, Albert Volkman, tim.plunkett, andypost, disasm, Les Lim, tkuldeep17: Convert user_pass_reset to a new-style Form object.
    • Issue 2302525 by tim.plunkett: Convert file_module_test_form to a class.
    • Issue 2078015 by er.pushpinderrana, RoSk0 | alexanansi: Modernize views_test_data.module forms.
    • Issue 2302531 by tim.plunkett: Convert database_test_theme_tablesort to a class.
  • Issue 2291137 by cilefen | webchick: Rename various *links.yml files to improve DX.
  • Issue 2202511 by hussainweb, benjy | mikeryan: Added Implement migration groups.
  • Issue 2302463 by effulgentsia: Cleanup User::hasPermission() and UserSession::hasPermission() to follow Law of Demeter.
  • Issue 2302331 by kim.pepper: Move drupal_valid_path to PathValidator service.
  • Issue 2296839 by MKorostoff, er.pushpinderrana | YesCT: Remove deprecated comment_num_new().
  • Issue 2289063 by larowlan, andypost | Berdir: Change contact message entity to behave more like a normal entity.
  • Issue 2301239 by pwolanin, dawehner, Wim Leers, effulgentsia, joelpittet, larowlan, xjm, YesCT, kgoel, victoru, berdir, likin, and plach: MenuLinkNG part1 (no UI or conversions): plugins (static + MenuLinkContent) + MenuLinkManager + MenuTreeStorage.
  • Issue 2284103 by alexpott, fabpot, damiankloip, Xano, Xen, Berdir: Fixed Remove the request from the container - this switches from using Request to RequestStack, gets rid of our custom HttpKernel and the Request scope, lets us upgrade Symfony past 2.3 and closes a critical. Special thanks to Fabien Potencier, Project Lead for Symfony for getting the ball rolling and working with the Drupal community on patches.
  • More standardising of entity-field API
    • Issue 2292821 by andypost, larowlan: Use widget for comment subject field.
    • Issue 1498662 by andypost, larowlan | dawehner: Refactor comment entity properties to multilingual.
    • Issue 1856562 by andypost | sun: Convert "Subject" and "Message" into Message base fields.
  • Lots of cleanup of deprecated functions
    • Issue 2297487 by er.pushpinderrana, marcingy: Remove the check_plain function.
    • Issue 2301591 by joshi.rohit100: Remove drupal_rebuild_form() as it is deprecated.
    • Issue 2208893 by ngocketit, longwave: Remove unused functions from Views.
    • Issue 2301601 by joshi.rohit100: Remove drupal_validate_form() as it is deprecated.
    • Issue 2301587 by joshi.rohit100: Remove form_state_defaults() as it is deprecated.
    • Issue 2301577 by ParisLiakos, joshi.rohit100: Remove drupal_alter() as it is deprecated.
    • Issue 2300853 by joshi.rohit100: Remove language() method from bootstrap.inc as it is deprecated.
    • Issue 2300891 by joshi.rohit100: Remove format_backtrace() from error.inc as deprecated.
    • Issue 2301597 by joshi.rohit100: Remove drupal_prepare_form() as it is deprecated.
    • Issue 2300831 by joshi.rohit100: Remove module_exists() as it is deprecated.
    • Issue 2300857 by joshi.rohit100: Remove lock() method from bootstrap.inc as deprecated.
    • Issue 2300821 by joshi.rohit100: Remove module_invoke_all() as it is deprecated.
    • Issue 2300847 by joshi.rohit100: Remove drupal_get_form() as it is deprecated.
    • Issue 2300843 by joshi.rohit100: Remove drupal_json_encode() and drupal_json_decode() methods as deprecated.
    • Issue 2300833 by joshi.rohit100: Remove module_hook() as it is deprecated.
    • Issue 2300697 by joshi.rohit100: Remove drupal_is_cli() as It is deprecated.
    • Issue 2299499 by joshi.rohit100: Remove form_clear_error() as it is deprecated.
    • Issue 2301975 by kim.pepper: Move drupal_is_front_page to PathMatcher service.
  • Issue 697760 by sun: Replace getInfo() in tests with native phpDoc + annotations (following PHPUnit).

You can also always check the Change records for Drupal core for the full list of Drupal 8 API changes from Drupal 7.

Drupal 8 Around the Interwebs

Blog posts about Drupal 8 and how much it's going to rock your face.

  • Drupalize.me recap Drupal 8's plugin system.
  • Nuvole give us a preview of their Amsterdam session on packaging and reusing configuration in Drupal 8.
  • chx gives us an update on Drupal 8 from both his and a MongoDB perspective.
  • Wunderkraut gave us the lowdown on configuration entities in Drupal 8.
  • Cameron Zemek from PreviousNext introduces us to Mink previewing one of the core-conversations from Amsterdam.
Drupal 8 in "Real Life" Whew! That's a wrap!

Do you follow Drupal Planet with devotion, or keep a close eye on the Drupal event calendar, or git pull origin 8.x every morning without fail before your coffee? We're looking for more contributors to help compile these posts. You could either take a few hours once every six weeks or so to put together a whole post, or help with one section more regularly. Contact xjm if you'd like to help communicate all the interesting happenings in Drupal 8!

AttachmentSize july_criticals.png40.56 KB july_majors.png37.64 KB july_beta_blockers.png32.25 KB
Categories: Elsewhere

Mediacurrent: How to Start a Drupalcamp

Thu, 17/07/2014 - 18:23

Getting a new regional Drupalcamp up and running appears daunting at first, but the support of the Drupal Community helps provide a giant head start. At Drupalcon 2014 in Austin, SVP of Professional Services Jeff Diecks shared some tips to help ease into the planning process.

Additional Resources

Categories: Elsewhere

Advomatic: This Is The House That Jack Themed

Thu, 17/07/2014 - 16:47

This is Jack:

Usually, Jack is theming beautiful website like these:

 

 

 

But when Jack's not in the office, he's got other things on his mind:

 

So when Jack's son grew out of his old room, Jack took on a new theming project:

 

Pretty delightful, huh?

 

And here's a bonus shot of Jack in his son's old room, where he video chats us from:

Yup, that's a monkey in a tree back there.

Categories: Elsewhere

VM(doh): Ensuring Consistent Configuration Across Drupal 7 Environments

Thu, 17/07/2014 - 14:51

A common issue that many Drupal developers have is maintaining consistent configuration across environments. Quite often, a developer may run into an issue where something that was tested and confirmed working in development fails in production, or vice versa. Typically, the issue stems from an undocumented change that was made in one environment but not the other. This is an adverse side effect of storing configuration within the database.

Ideally, all configuration should be under version control. In Drupal 8, this issue has been solved by the Configuration Management Initiative. However, to achieve the same goals in Drupal 7, one must implement workarounds.

For variables, it's rather trivial to enforce certain parts of your configuration. When it comes to the variable system, the $conf global has the final say on the value of a variable. The variable_get() function simply retrieves a variable from the global $conf array, and that array is built from the variables table with values in settings.php overriding the retrieved values. Basically, there are two ways to find out what variables on your site you can force via settings.php: the most thorough is to print out the $conf array (preferably through dpm()), but you can also search for instances of variable_set() and variable_get(). Looking for variable_get() might also expose undocumented but useful variables.

But what about more complex pieces of configuration, such as fields, Views, entity types, etc? In many cases, you can export those with the Features module. However, in order to be successful in using Features to manage the configuration of different parts of your site, you need to implement a policy that overridden Features modules in production should be considered broken.

But what about things that aren't exportable to Features? What about special steps that need to be taken to implement a bug fix or new feature? We like to leverage hook_update_N() within a custom deployment module. With this approach, we're able to define (and therefore easily document) changes in code (and therefore under version control) and simply use "drush updb" to implement them. (If you're not using Drush, and you really should be using Drush, this is the same as running update.php.) We put all of our configuration changes in one of these hooks in our deployment module, including variable_set(), module_enable(), module_disable(), features_revert() for any Features that we have changed, database queries to fix data issues caused by previous bugs, etc.

This has several advantages. For one, deployments become a lot simpler. Ideally, you want your deployments to be hands-off. What this method allows us to do is write a simple deployment script that pulls the new code from Git, put the site into maintenance mode, runs a registry rebuild via drush just in case we moved a module (some moves can cause white screens of death if you don't do this), runs updates via Drush, clears cache (just in case), runs cron (just in case), and takes the site back out of maintenance mode. In cases where we manage the ops side or the client's ops team allows, we'll also send a notification to the monitoring system to make sure that the new deployment is noted (very useful for determining when a problem was introduced).

Another key advantage is documentation. With configuration changes made via update hooks, we can tell exactly when configuration changes were introduced and by whom. It also all but eliminates the risk of a costly missed step on deployment to production as the deployment steps themselves are tested when a developer updates their development environment.

For some configuration settings, such as enabling a debug mode for a particular module, we may want to allow those changes to be made temporarily through the UI. However, accidentally leaving those debugging settings enabled can cause performance issues. In these cases, we combat this by defining critical settings in an implementation of hook_requirements(). (This only works for settings that have not been defined via the global $conf variable.) Using hook_requirements(), we're able to check that settings are appropriate for the environment (typically limited to production) and display a message to users with proper access if they are not in order to warn them that they need to adjust that setting back to the appropriate value.

But what should we do with hook_install()? There are two schools of thought here. One is to define all of your final configuration here, and the other is to loop over your implementations of hook_update_N(). I prefer the latter. While looping over hook_update_N() can be a more expensive process if your site has gone through some serious evolution, it's less duplication of code and less of a chance for you to miss something important. The goal of our use of hook_install() is to eliminate database cloning by only requiring the developer to install the deployment module to initialize a fully functional development version of the site.

Eliminate database cloning? For the most part, yes. Database cloning is a bad practice, even cloning upstream from production. Databases can be huge, and cloning a huge database can impact the performance of the site for your users. Databases can contain sensitive information (most standards dealing with the handling of sensitive information dictate that sensitive information only be accessible to those who absolutely need to access it), and most developers don't need access to sensitive information. Databases in production while a bug existed in production don't usually fit the requirement of presenting a known good starting point for development. Believe it or not, your content and customer information are not necessary for development.

So what can we do about content and other information? The answer is to generate it. Generate dummy content. Generate dummy orders. Generate dummy products. And so forth and so on. If you're doing automated testing, you will be having to do that anyway.

There are exceptions to not cloning the production database. Sometimes you will run into bugs that seem to only occur in production. In this case, it is acceptable to clone the database because the bug is likely caused by something that was unanticipated. However, when fixing these bugs you should take steps to ensure that whatever content or other information change that surfaced the bug is tested for before deploying to production thereafter.

Another exception is if you are using a staging and/or QA environment. In this case, you will want to clone the production database upstream to staging/QA just before deploying your fresh code to staging/QA. You need to do this to absolutely ensure that the changes in your deployment module cover all of the changes that will need to be made to production.

Finally, it's important to test. Writing the actual tests are outside the scope of this post, but it is important that you have automated tests in place that ensure that your site is configured exactly how you need it. Even if you have tests for your site's custom modules in those modules, you need to test your deployment module. The goal here is to fail fast. By having a separate test group for your configuration, you can have Jenkins (or whatever other continuous integration software you use) proceed to other tests only after your configuration tests have passed.

Categories: Elsewhere

ThinkShout: Safeguard Your Nonprofit's Website with NodeSquirrel

Thu, 17/07/2014 - 13:00

In our web hosts we trust, right? Right. They safeguard your nonprofit’s website, ensure it can handle your incoming traffic, and, perhaps most importantly, they backup your site so that if for some reason, your website ever imploded, it wouldn’t be lost for good.

But just how accessible are those backups? How surefire is your contingency plan? Have you tested it out? A lot of website administrators will find that actually initiating this plan isn’t as easy as it may seem. Those backups might take hours or days of ticketing and waiting to get a hold of, particularly if your website host is already inundated with other customer support issues. What then are you to do when something breaks and the site comes tumbling down?

Enter NodeSquirrel. NodeSquirrel is a Drupal backup service developed and maintained by Gorton Studios. It gives site admins control over their site backups. I sat down with Gorton Studios’ Drew Gorton and Keri Poeppe to learn why nonprofits should consider making NodeSquirrel a part of their workflow.

Stephanie: So what exactly is NodeSquirrel?

Keri: It’s a system for creating, managing, and securely storing website backups. Drupal developers out there will know the Backup and Migrate module. NodeSquirrel extends Backup and Migrate, allowing you to make backups of your website and store those backups in the cloud.

Drew: Backup and Migrate is one of the most popular modules in Drupal. One of the reasons it’s so popular is because it’s easy to create a backup. But by default, that backup stays on your server. What we’re trying to do with NodeSquirrel is make it easy to get that backup off of your server and move it somewhere safer - in this case, Amazon’s cloud. What makes NodeSquirrel such an integral addition to your regular hosting is that it’s something you can use whenever you need to access those backups. Getting to your web host’s backups and testing them can be difficult - and just because they’re backed up doesn’t mean they actually work. With NodeSquirrel, there are no surprises. You can get into your backups, make sure nothing is corrupted, and restore it yourself rather than wait on your host.

Stephanie: How does NodeSquirrel accomplish this?

Keri: NodeSquirrel is an off-site destination, but the process of getting the copy of your site uses the Backup and Migrate Module.

Drew: Here’s an example: there was a NodeSquirrel user whose site was being backed up daily by their web host. Unfortunately, that organization had a major failure and needed to restore the whole site, but the backups they received from their host were unusable. The host had to go back two months to find a backup that actually worked. And, this was from a hosting service costing at least $100 a month.

NodeSquirrel, luckily, was running on their site and they were able to use one of the backups stored on the cloud. It saved them. The problem is that no one ever tests hosting company backups. It’s stored by your host, but no one ever goes back and to check the integrity of the backup and figure out if it can be used when something goes wrong.

NodeSquirrel is different because it’s part of Drupal and the Drupal workflow. We’ve made it easy for you or your developer to retrieve and test your backups.

Stephanie: What sets NodeSquirrel apart for the competition? What sort of functionality can I expect from it?

Keri: It’s unique in that it makes a very specific kind of backup. It copies the database, code, and the files rather than making a backup of the whole server and all of the extra infrastructure. It’s not a lightweight backup, but it’s one that can be very targeted, and you can be more nimble with it. For example, if someone accidentally deletes a blog post or wipes out blocks on the homepage, you can quickly restore the website from a NodeSquirrel backup. You don’t need to spend lots of money or staff time recreating the blog post or home page! And you don’t need to call your hosting company to solve the problem. I think what distinguishes it from standard backup systems is how much control users have over the management of their backups. NodeSquirrel’s settings are managed in your site’s backend, so your website administrator has full control of your backup schedule and functions. Want to backup your site every hour? Go for it. Make the system as robust or as hands-off as you like. You can have that level of control and granularity.

Stephanie: How can I tell if my organization needs a service like NodeSquirrel? Is there such a thing as being "too small?"

Drew: It’s very affordable for anyone who’s invested time and money into their website and wants to safeguard that investment. The site is probably too valuable not to backup. We wanted to make this service accessible and affordable, so for about $100 a year, you’ll have this extra protection. Versus the time you spend trying to fix a bad backup, this is a better alternative. With that price point, it’s more of a question of "why not?"

Stephanie: It sounds like NodeSquirrel offers users a lot of options. Is there anything it won’t protect against? What doesn’t it do?

Drew: Most people ask how it compares to their standard hosting, since we have no direct competition. It’s not a full-server backup or a backup for a complex server. It doesn’t backup your DNS settings or load balance configuration. Typically though, if you have a complex setup, you’ll have a system admin or a disaster response team in your organization. Even if you do, NodeSquirrel might still be supplemental and helpful as an extra layer of protection.

Keri: If you can’t call your hosting company and see a backup, you might want to think about NodeSquirrel.

Drew: That’s actually a great way to test your site host. Call them and ask to access your backups. How long will it take? Will they charge you extra to set up a test environment?

Keri: Download and restore a backup. There’s your test to see if you can sleep easy at night. With NodeSquirrel, you can.

Stephanie: Is there anything else we should know about NodeSquirrel? Any tips for getting the most out of the service?

Keri: I’d stress the low threshold to use it. It requires no additional software. It’s integrated seamlessly, especially if Backup and Migrate is already installed. Ask your developers to install version 3 of Backup and Migrate. It’ll give you the most flexibility. NodeSquirrel is free to try, too. We have a trial offer that allows you to make 20 free backups. No credit card required.

Drew: We wanted to make it easy to do the right thing, and having onsite backup is the right thing. If it works, keep on going.

Our conclusion:

NodeSquirrel is a highly-affordable extra layer of protection that could save you and your stakeholders a major headache and a great deal of money in the event of a site meltdown. Even if your hosting provider has a backup solution, in the event of data loss, NodeSquirrel is a great alternative to sitting in support queues, waiting on your web host to resolve the issue.

With NodeSquirrel, you can take complete ownership of your backups and spare yourself the worry of whether or not you’ll be able to get your site up and running. It’s poised to integrate beautifully with your Drupal website administrative workflow, allowing you to safeguard your investment without having to spend time building new safety net systems. With plans starting at $9/month, it’s a question of "can you afford not to use NodeSquirrel?"

Want to see it in action for yourself? Sign up for the free trial. If you do take it for a spin, let us know what you think in the comments section.

Categories: Elsewhere

Drupalfund.us: #D8Rules As a Proof that Drupal Community Is a Living Cell

Thu, 17/07/2014 - 11:28

When D8Rules project waiting in a Funding phase had just seven days left to be successfully funded, success didn’t seem likely. The project had raised just over 40% of its funding goal so far. The days shortened; the pressure rose. Happiness exploded exactly two days before the finish line thanks to the rescuing amount which came just in time.

The Biggest Nest of Funders So Far

We know that the Drupal Community is generous in donating money. They confirmed it again in the case of the ‘D8Rules - Support the Rules module for Drupal 8’ project. Together, 138 backers funded 106% of its funding goal. It equated to 15.973 dollars. With this number, D8Rules is, for the moment, the biggest project successfully funded onDrupalfund.us.

Public crowdfunding for D8Rules on Drupalfund started on May 13th. In one day, funders covered 8% of the funding goal already—quite good for a start. During the first two weeks the donating line grew and then it became static. The days were flowing away and more than a half of the final amount was still missing. What happened next?!

Categories: Elsewhere

Deeson Online: Deeson Online create Drupal 8 personas

Thu, 17/07/2014 - 06:30
Deeson Online create Drupal 8 personasBy Lizzie Hodgson | 17th July 2014

The momentum behind Drupal 8 is growing, and Deeson Online have been playing their part...

We in the Drupal community probably know something about Drupal 8 – even if it's just that we're aware it's coming!

But how do you clearly and simply highlight the benefits of Drupal 8 to a non-developer audience, or those beyond our community?

How can you then potentially create a non-dev community of Drupal 8 advocates and share good practice?

Introducing Drupal 8 personas What is a persona?

A persona is a ‘person' that represents a specific group of users.

Organisations and companies can use intel from personas to create, for example, 
a piece or pieces of content that will:

  • Highlight expectations and use of your site for your 
end user
  • Help drive the benefits in 
a way that will be immediately understood 
by the audience

Deeson Online have been working of a series of personas to help clearly articulate the benefits of Drupal 8.


How did we create Drupal 8 personas?

Using interviews with a range of Drupal and non-Drupal users, we got to grips with all the pain points for a range of potential Drupal 8 users. Using Dries Buytaert’s personas from his DrupalCon Prague Keynote speech as a starting point, we then focused on:

We then carried out a series of interviews via Skype and Google Hangouts asking people from across the globe from each of these user groups over 30 questions.

These questions ranged from "How many people work in the company?" to "From the time you wake up to the time you go to bed, what does a day in your working life look like?"

What did we do with the answers?

We then analysed all the responses, reducing them down to one 'persona' per user group, ensuring that we captured the persona needs and pain, then matching them against how Drupal 8 will help.

The result

A range of easy to consume dowloadable infographic persona fact sheets, that established and potential users can read and share.

The results so far have been really positive. The infographic personas are proving especially useful for those within our community to have something to refer to when talking not just about the power and benefits Drupal 8, but Drupal itself.

So learn more about Drupal 8, download the persona infographics and share the Drupal love!  
Categories: Elsewhere

PreviousNext: Drupal continuous integration with Docker

Thu, 17/07/2014 - 03:03

Continuous integration platforms are a vital component of any development shop. We rely on it heavily to keep projects at the quality they deserve. Being early adopters of Docker (0.7.6) for our QA and Staging platform we thought it was time to take our CI environment to the next level!

Categories: Elsewhere

Metal Toad: The Best Way to Learn Programming for Beginners

Thu, 17/07/2014 - 00:32

What is the best way to learn programming for beginners? I've spent a lot of time over the past 12 months thinking about this question, and as our firm has grown steadily from 19 to 39 people, I've reflected on what makes the difference between the people who walk in the door and knock things out of the park and those who struggle. Since my blog post on How to Become a Web Developer I have a number of people who regularly ask me this very question, I'd like to share my thoughts and observations.

Categories: Elsewhere

Drupal core announcements: Core contact module roadmap

Thu, 17/07/2014 - 00:27
Background

Now that we have a new release cycle, we have the possibility of new features in minor releases, i.e. although we are in feature freeze for 8.0, that doesn't mean we can't add new features until 9.0. Provided they are backwards-compatible, we can add new features in 8.1 and 8.2.
After recently taking over maintainer-ship of the core contact module, @tim-e and I, in consultation with @andypost and @berdir have formulated a draft roadmap for the features we'd like to see in contact module in the future.
We're publishing it here for wider community-input.

High-level goal

To provide the 80% use-case of webform. i.e. allowing creation and submission of feedback forms from site-users; and providing editing, listing and administration of submitted form values.
Webform contains lots of features, we're only after expanding contact module slightly to add storage and administration and in the process meet the basic use-case of webform in core.
Note that some of these items are features and can be developed in contrib during 8.0 if required with the view to include in point releases eg 8.1, 8.2.

  1. Open issues
    1. Move subject/message fields to use widgets https://www.drupal.org/node/1856562
    2. Make contact message behave like normal entity https://www.drupal.org/node/2289063
    3. Rename contact category to form https://www.drupal.org/node/2285083
    4. Provide redirect option https://www.drupal.org/node/306662
  2. Key features/issues on roadmap
    1. Add (pluggable) storage of messages https://www.drupal.org/node/1856560 - we already have a test implementation of this (in a test module) in core, so it is already technically possible.
    2. Add views integration https://www.drupal.org/node/1856560
    3. Add admin listing of submissions w/ bulk actions to delete https://www.drupal.org/node/1856560
    4. Add ability to edit submissions
    5. Support for file-fields attached to emails - requires formatter for file-field.
    6. Ability to edit format of messages bodies including tokens
    7. Move email logic out of form submit handler to allow submission of messages via REST api that also send email
    8. Move email logic into own service and add events for other modules to interact
      1. Make email sending optional at category (form) level
    9. Path integration to allow simple alias management of contact categories
    10. Per contact-category permissions to allow granular access
    11. Provide a menu-link per category in a custom menu - auto builds menu of contact category links leveraging the menu link API to solve the category selector regression.
    12. Provide a configurable and themable block of selected contact forms. Probably needs views to query contact categories. https://www.drupal.org/node/1997692 and https://www.drupal.org/node/599770
Approach
Categories: Elsewhere

Pages