Drupal News

Subscribe to Drupal News feed
Drupal.org - aggregated feeds in category Planet Drupal
Updated: 44 min 25 sec ago

Drupal Watchdog: When Howard Met Ronnie

2 hours 39 min ago

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)

Images:  Video: 

Acquia Developer Center Blog: 10 Ways Drupal 8 Will Be More Secure

2 hours 59 min ago

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.

  1. 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 8 block.html.twig:

  2. 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.

  3. 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.


  4. 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:

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

    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.

  5. 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)

  6. 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:

  7. 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.

  8. 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.

  9. 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).

  10. 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.

Blog series: Drupal 8Workflow: PublishedFeatured: NoTags: acquia drupal planetSecurityDrupal 8 related: YesAuthor: Peter Wolanin

Acquia Developer Center Blog: Securing Your Site’s Communications with SSL

3 hours 19 min ago
*/

These 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.

Workflow: PendingFeatured: NoTags: acquia drupal planetDrupal 8 related: NoAuthor: Lynette Miles

Mediacurrent: Mediacurrent Dropcast: Episode 10

7 hours 38 min ago

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.

Frederic Marand: Drupal 8 tip of the day: autoloaded code in a module install file

12 hours 55 min ago

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 ?

read more

KatteKrab: D8 Accelerate - Game over?

Wed, 08/26/2015 - 18:47
Thursday, August 27, 2015 - 10:47

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 :-)

DrupalCon News: Introduction to Headless Drupal

Wed, 08/26/2015 - 17:22

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!

Capgemini Engineering: Writing custom fields in Drupal 8

Wed, 08/26/2015 - 17:00

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).

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.

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

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.

Country autocomplete widget

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="!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.

Writing custom fields in Drupal 8 was originally published by Capgemini at Capgemini on August 27, 2015.

DrupalCon News: First Asia Post

Wed, 08/26/2015 - 11:57

words words namaste words

Acquia Developer Center Blog: Terrific Tools for Drupal 8 Training

Wed, 08/26/2015 - 11:20

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.

Blog series: Organizing to Rock with Drupal 8Workflow: PublishedFeatured: NoTags: acquia drupal planetDrupal 8 related: YesAuthor: Thomas Howell

Mediacurrent: Accessible Names - Label All the Things! (Part 2)

Wed, 08/26/2015 - 10:52
Label the Rest of the Things!

Singlebrook Technology: Styleguide Driven Development in Drupal

Wed, 08/26/2015 - 10:37

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:...

Advomatic: Altering Data For a Drupal 8 Migration, Step-by-Step

Wed, 08/26/2015 - 10:00

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... Read more »

The post Altering Data For a Drupal 8 Migration, Step-by-Step appeared first on Advomatic.

ThinkShout: Migrating from Luminate CRM to Drupal and the Salesforce Nonprofit Starter Pack

Wed, 08/26/2015 - 09:00

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.

Drupal Watchdog: VIDEO: DrupalCon Los Angeles Interview: Jeremy Rasmussen

Wed, 08/26/2015 - 08:22

“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.”

Tags:  Video DrupalCon LA Drupal Video: 

Pronovix: 6 days to win 50k USD with the new context.io module — a powerful mailhandler alternative

Wed, 08/26/2015 - 06:25

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.

Zivtech: Website Documentation Tips and Insights

Wed, 08/26/2015 - 05:30

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. Terms: Related Services Training We turn smart people into great developers. Read more

Realityloop: Drupal Development tips for Common Problems

Wed, 08/26/2015 - 00:21
26 Aug Jarkko Oksanen

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.  
  3. // Turn off Secure Pages. Secure Pages Module.
  4. $conf['securepages_enable'] = FALSE;
  5. $conf['https'] = FALSE;
  6.  
  7. // Stage File Proxy Configuration
  8. $conf['stage_file_proxy_origin'] = 'http://mysite.com';
  9. // Stage file optional with securepages
  10. // $conf['stage_file_proxy_origin'] = 'http://username:password@mysite.com';
  11. $conf["stage_file_proxy_use_imagecache_root"] = FALSE;
  12. $conf['stage_file_proxy_hotlink'] = TRUE;
  13.  
  14.  
  15. // Turn off Caching.
  16. $conf['cache'] = 0;
  17. // Block caching - disabled.
  18. $conf['block_cache'] = 0;
  19. // Expiration of cached pages - none.
  20. $conf['page_cache_maximum_age'] = 0;
  21. // Aggregate and compress CSS files in Drupal - off.
  22. $conf['preprocess_css'] = 0;
  23. // Aggregate JavaScript files in Drupal - off.
  24. $conf['preprocess_js'] = 0;
  25.  
  26. // Minimum cache lifetime - always none.
  27. $conf['cache_lifetime'] = 0;
  28. // Cached page compression - always off.
  29. $conf['page_compression'] = 0;
  30.  
  31.  
  32. // Turn off other caching.
  33. $conf['css_gzip'] = FALSE;
  34. $conf['javascript_aggregator_gzip'] = FALSE;
  35.  
  36.  
  37. // Turn on all error reporting for local development.
  38. error_reporting(-1);
  39. $conf['error_level'] = 2;
  40. ini_set('display_errors', TRUE);
  41. 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!

drupal planetdrupaldevelopmenttips

Modules Unraveled: 146 Drupal Update Automation and Drop Guard with Manuel Pistner - Modules Unraveled Podcast

Tue, 08/25/2015 - 23:00
Published: Wed, 08/26/15Download this episodeUpdate 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?
Episode Links: Manuel on drupal.orgManuel on TwitterDrop Guard on TwitterDrop Guard WebsiteDrop Guard WebinarTags: Automationplanet-drupal

OSTraining: Drupal Error: More Than 5 Failed Login Attempts

Tue, 08/25/2015 - 18:22

If you've forgotten your Drupal password and try unsuccessfully to login, you may get this message:

Sorry, there have been more than 5 failed login attempts for this account. it is temporarily blocked

The image below shows how the message appears. I'm going to show you how you can fix this error.

Pages