Drupalcon Baltimore Edition

Posted by Lullabot - 20 Apr 2017 at 20:00 UTC
Matt and Mike sit down with several Lullabots who are presenting at Drupalcon Baltimore. We talk about our sessions, sessions that we're excited to see, and speaking tips for first-time presenters.

Upgrading A Drupal 7 Module to Drupal 8: Configuration Forms

Posted by CU Boulder - Webcentral - 20 Apr 2017 at 19:41 UTC

In the last post in this series, we set up some routing for our module for three paths. One of those paths is to the module's main configuration form. Since this module has a Drupal 7 version, I am going to go by the old tried and true method of CDD, a.k.a Copy Driven Development. Copy, paste, cry, try to copy something else.

Developer Blog

Get the most out of your first DrupalCon!

Posted by Acquia Developer Center Blog - 20 Apr 2017 at 18:59 UTC
Acquia Drupal logo shirt, DrupalCon MunichDrupal Association DrupalCon swag storeDrupalCon Munich code sprintsDrupalCon Prague group photoSwag collected at DrupalCon AustinDriesnote, DrupalCon DenverDrupalCon beer taps

To me, meeting and building relationships in person is the glue that holds us together and makes Drupal a community. If this is your first DrupalCon or first Drupal community event, it’ll be your first taste of this crazy, smart bunch of people scattered around the globe most of the rest of the year. Welcome! I’d like to help you get the most out of your first DrupalCon!

Tags: acquia drupal planetcommunityfirst timerseventdrupalcon

Dropcast: Episode 31 - DRUPALCON

Posted by Mediacurrent - 20 Apr 2017 at 16:58 UTC
Dropcast: Episode 31 - DRUPALCON

Recorded April 12th, 2017

The State-of-Drupal Poll

Posted by The Accidental Coder - 20 Apr 2017 at 15:25 UTC

Speak out about your feelings on several topics that are swirling in the Drupalsphere. The results of the poll will be published here during Drupalcon Baltimore. 

Take the Poll!

Tags: Drupal Planet

Ultimate guide to migrating data into Drupal 8

Posted by MTech, LLC - 20 Apr 2017 at 15:16 UTC
Ultimate guide to migrating data into Drupal 8

I give special greetings to all the people who read us and particularly to Baltimore at the headquarters of Drupalcon 2017.

Charlotte León Thu, 04/20/2017 - 09:16

Replacing hook_boot and hook_init Functionality in Drupal 8

Posted by Chromatic - 20 Apr 2017 at 13:15 UTC

Adam uncovers methods of firing code on every page in Drupal 8, the right way.

Empowering Drupal 8 Content Editors with EVA: Attach All the Displays!

Posted by Zivtech - 20 Apr 2017 at 13:00 UTC

Entity Views Attachment, or EVA, is a Drupal module that allows you to attach view displays to entities of your choosing. We used it recently on a project and loved it. You know it’s good because it has a no-nonsense name and an even better acronym. (Plus, the maintainers have taken full advantage of the acronym and placed a spaceman on the project page. Nice!)

Since the now-ubiquitous Paragraphs module provides the “paragraph” entity type, I figured these two will make good dancing partners.

Getting them to tango is simple enough. You create a paragraph bundle, target that bundle in the settings on an EVA view display, then arrange the view in the paragraph’s display settings. Voila – your view display shows up wherever you add this paragraph!

By attaching a view display to a paragraph entity and enabling that paragraph on a node’s paragraph reference field, you give your content editors the ability to place a view wherever they want within their page content. Better still, they can contextualize what they are doing since this all happens in the edit form where the rest of the node content lives. As far as I can tell, no other approach in the Drupal ecosystem (I’m looking at you Blocks and Panels) makes adding views to content this easy for your editors.

Case Study

The concept is pretty straightforward, but with a little cleverness it allows you to build some complex page elements. Let’s walk through an example. Consider the following design:

This mockup represents Section nodes and lists of Subpage nodes that reference them. In addition, the buttons links should point to the parent Section node. With a little elbow grease, we can build a system to output this with our friends EVA and Paragraphs.

Here’s how I’m breaking this down conceptually:

We have three things to build:

  1. A create a container paragraph bundle

  2. A child paragraph bundle with a Section entity reference field

  3. An EVA of subpages to attach to the child paragraph bundle

Building the Subpage EVA

As I mentioned before, Subpage nodes will reference Section nodes. With this in mind, we can build the EVA that lists subpages and expects a section node ID to contextually filter to subpages that reference that node.

Building the Section paragraph type

Next, we’ll create the Section paragraph type that will handle each grouping of a section node with its related subpages. The Section paragraph will have one field, an entity reference field limited to Section nodes, that gives us all the data we need from our section.

We’ll attach our EVA to this paragraph type and configure it to pass the referenced node’s ID as the contextual filter using tokens in the EVA settings. You will need to install the Token module to do this. Go to /admin/help/token to see all available tokens once installed. You need to grab the node ID through your entity reference field, so your token argument should look something like this:

[paragraph:field_node_reference:entity:nid]

We pass that token to our contextual filter, and we can tell our view to use that argument to create a link to the section node for our “View All Subpages” link. To do this, we’ll add a global text area to the view footer and check the “Use replacement tokens from the first row” checkbox. Then we’ll write some HTML to create a link. It’ll look something like this:

<a href="/node/{{ raw_arguments.nid }}">View all Subpages</a>

Building the Section List paragraph type

Lastly, we’ll create the Section List paragraph type. This only really needs a paragraph reference field that only allows the user to add Section paragraphs, but I also added a title field that will act as a header for the whole list.

Tip: Install Fences module to control your field’s wrapper markup. I used this here to wrap the title in <h2> tags.

We’re finished!

Now that everything is built, we can allow users to select the Section List paragraph type in a paragraph reference field of our choosing. A user adds a Section List, then adds Sections via the entity reference. It looks like this in the node edit form:

Do you have any cool ways you use the EVA module in your builds? Let us know in the comments section below.

Migrate translations from CSV, JSON or XML to Drupal 8

Posted by Evolving Web - 20 Apr 2017 at 12:38 UTC
Photo of baggage labels from 1980s airlines such as TWA.

In my last post, I showed you how to migrate translated content from Drupal 6 to Drupal 8. But clients often don't start with their data in Drupal 6. Instead there's some other source of data that may include translations, like a CSV spreadsheet. In this article, I'll show you how to migrate multilingual content from such sources to Drupal 8.

This article would not have been possible without the help of my colleague Dave. Gracias Dave!

The problem

We have two CSV files containing some data about chemical elements in two languages. One file contains data in English and the other file, in Spanish. Our goal is to migrate these records into a Drupal 8 website, preserving the translations.

Before we start

  • Since this is an advanced migration topic, it is assumed you already know the basics of migration.
  • To execute the migrations in this example, you can download the migrate example i18n. The module should work without any trouble for a standard Drupal 8 install. See quick-start for more information.

Migrating JSON, XML and other formats

Though this example shows how to work with a CSV data source, one can easily work with other data sources. Here are some quick pointers:

  • Find and install the relevant migrate source module. If you do not have a standard source module available, you can:
    • try converting your data to a supported format first.
    • write your own migration source plugin, if you're feeling adventurous.
  • Modify the migration definitions to include custom parameters for the data source.
  • Some useful source formats are supported by these projects:

The module

To write the migrations, we create a module—in our case, it is named migrate_example_i18n. There's nothing special about the module declaration except for the dependencies:

How to migrate translations

    Before we start writing migrations, it is important to mention how Drupal 8 translations work. In a nutshell:

    • First, we create content in its base language, say in English. For example, we could create a brand new node for the element Hydrogen, which might have a unique node ID 4.
    • Now that the base node is in place, we can translate the node, say to Spanish. Unlike some previous versions of Drupal, this won't become a new node with its own node ID. Instead, the translation is saved against the same node generated above, and so will have the same node ID—just a different language setting.

    Hence, the migration definition for this example includes the following:

    • We migrate the base data in English using in example_element_en migration.
    • We migrate the Spanish translations using the example_element_es migration, and link each translation to the original English version.
    • We group the two migrations in the example_element migration group to keep things clean and organized.

    Thus, we can execute the migrations of this example with the command drush migrate-import --group=example_element.

    Warning

    Note that this plan only works because every single node we are importing has at least an English translation! If some nodes only existed in Spanish, we would not be able to link them to the (non-existent) original English version. If you encounter data like this, you'll need to handle it in a different way.

    Step 1: Element base migration (English)

    To migrate the English translations, we define the example_element_en migration. Here is a quick look at some important parameters used in the migration definition.

    Source

    source:
      plugin: csv
      path: 'element.data.en.csv'
      header_row_count: 1
      keys:
        - Symbol
      fields:
        Name: 'Name'
        Symbol: 'Symbol'
        'Atomic Number': 'Atomic number'
        'Discovered By': 'Name of people who discovered the element'
      constants:
        lang_en: en
        node_element: 'element'
    • plugin: Since we want to import data from a CSV file, we need to use the csv plugin provided by the migrate_source_csv module.
    • path: Path to the CSV data source so that the source plugin can read the file. Our source files for this example actually live within our module, so we modify this path at runtime using hook_migration_plugins_alter() in migrate_example_i18n.module.
    • header_row_count: Number of initial rows in the CSV file which do not contain actual data. This helps ignore column headings.
    • keys: The column(s) in the CSV file which uniquely identify each record. In our example, the chemical symbol in the column Symbol is unique to each row, so we can use that as the key.
    • fields: A description for every column present in the CSV file. This is used for displaying source details in the UI.
    • constants: Some static values for use during the migration.

    Destination

    destination:
      plugin: 'entity:node'
    • plugin: Nothing fancy here. We aim to create node entities, so we set the plugin as entity:node.
    • translations: Since we are importing the content in base language, we do not specify the translations parameter. This will make Drupal create new nodes for every record.

    Process

    process:
      type: constants/node_element
      title: Name
      langcode: constants/lang_en
      field_element_symbol: Symbol
      field_element_discoverer:
        plugin: explode
        delimiter: ', '
        source: Discovered By

    This is where we map the columns of the CSV file to properties of our target nodes. Here are some mappings which require a special mention and explication:

    • type: We hard-code the content type for the nodes we wish to create, to type element.
    • langcode: Since all source records are in English, we tell Drupal to save the destination nodes in English as well. We do this by explicitly specifying langcode as en.
    • field_element_discoverer: This field is a bit tricky. Looking at the source data, we realize that every element has one or more discoverers. Multiple discoverer names are separated by commas. Thus, we use plugin: explode and delimiter: ', ' to split multiple records into arrays. With the values split into arrays, Drupal understands and saves the data in this column as multiple values.

    When we run this migration like drush migrate-import example_element_en, we import all the nodes in the base language (English).

    Step 2: Element translation migration (Spanish)

    With the base nodes in place, we define a migration similar to the previous one with the ID example_element_es.

    source:
      plugin: csv
      path: 'element.data.es.csv'
      header_row_count: 1
      keys:
        - 'Simbolo'
      constants:
        lang_en: en
      # ...
    destination:
      plugin: 'entity:node'
      translations: true
    process:
      nid:
        plugin: migration
        source: Simbolo
        migration: example_element_en
      langcode: constants/lang_es
      content_translation_source: constants/lang_en
      # ...
    migration_dependencies:
      required:
        - example_element_en

    Let us look at some major differences between the example_element_es migration and the example_element_en migration:

    • source:
      • path: Since the Spanish node data is in another file, we change the path accordingly.
      • keys: The Spanish word for Symbol is Símbolo, and it is the column containing the unique ID of each record. Hence, we define it as the source data key. Unfortunately, Drupal migrate support keys with non-ASCII characters such as í (with its accent). So, as a workaround, I had to remove all such accented characters from the column headings and write the key parameter as Simbolo, without the special í.
      • fields: The field definitions had to be changed to match the Spanish column names used in the CSV.
    • destination:
      • translations: Since we want Drupal to create translations for English language nodes created during the example_element_en migration, we specify translations: true.
    • process:
      • nid: We use the plugin: migration to make Drupal lookup nodes which were created during the English element migration and use their ID as the nid. This results in the Spanish translations being attached to the original nodes created in English.
      • langcode: Since all records in element.data.es.csv are in Spanish, we hard-code the langcode to es for each record of this migration. This tells Drupal that these are Spanish translations.
      • content_translation_source: Each translation of a Drupal node comes from a previous translation—for example, you might take the Spanish translation, and translate it into French. In this case, we'd say that Spanish was the source language of the French translation. By adding this process step, we tell Drupal that all our Spanish translations are coming from English.
    • migration_dependencies: This ensures that the base data is migrated before the translations. So to run this migration, one must run the example_element_en migration first.

    Voilà! Run the Spanish migration (drush migrate-import example_element_es) and you have the Spanish translations for the elements! We can run both the English and Spanish migration at once using the migration group we created. Here's how the output should look in the command-line:

    $ drush migrate-import --group=example_element
    Processed 111 items (111 created, 0 updated, 0 failed, 0 ignored) - done with 'example_element_en'
    Processed 105 items (105 created, 0 updated, 0 failed, 0 ignored) - done with 'example_element_es'

    If we had another file containing French translations, we would create another migration like we did for Spanish, and import the French data in a similar way. I couldn't find a CSV file with element data in French, so I didn't include it in this example—but go try it out on your own, and leave a comment to tell me how it went!

    Next steps

    + more awesome articles by Evolving Web

    Making a difference, One Drupal security patch at a time

    Posted by Dropsolid - 20 Apr 2017 at 11:52 UTC
    security 20 Apr Making a difference, one Drupal security patch at a time Nick Advisory by the Drupal security team

    Recently, the References module started receiving some attention (read here, here and here). The reason for this is that the Drupal security team posted an advisory to migrate away from the References module for Drupal 7 and move to the entity_reference module. At the time of writing (20 April), 121.091 sites are actively reporting to Drupal.org that they are using this module. That makes for a lot of unhappy developers.

    Things kicked off after a security vulnerability was discovered in the References module. The security team tried to contact the existing maintainers of that module, but there was no response. The security team had no choice but to mark the module as abandoned and send out the following advisory explaining that the details would be made public in a month and that everyone should upgrade, as there was no fix available.

    Migrate efficiently

    At Dropsolid, we noticed that for many of our older Drupal 7 installs we were still using this module extensively. Migrating all of the affected sites would have meant a very lengthy undertaking, so I was curious to find a way to spend less time and effort while still fixing the problem. We immediately contacted one of the people who reported the security issue and tried to get more information other than what was publicly available. That person stayed true to the rules and did not disclose any information about the issue.

    We didn’t give up, but made an official request to the security team offering to help and requesting access to the security vulnerability issue. The Drupal security team reviewed the request and granted me access. In the Drupal Security issue queue there was some historical information about this vulnerability, some answers and a proposed patch. The patch had not been tested, but this is where Dropsolid chimed in. After extensively testing the patch on all the different scenarios on an actual site that was vulnerable, we marked the issue as Reviewed and Tested by the Community (RTBC) and stepped up maintain the References module for future security issues.

    It pays off to step in

    I’d like to thank Niels Aers, one of my colleagues, as his involvement was critical in this journey and he is now the current maintainer of this module. He jumped straight in without hesitation. In the end, we spent less time fixing the actual issue compared to the potential effort for changing all our sites to use a different module. So remember: you can also make a similar impact to the Drupal community by stepping up when something like this happens. Do not freak out, but think how you can help your clients, company and career by fixing something for more than just you or your company.

    Documenting web APIs with the Swagger / OpenAPI specification in Drupal

    Posted by Pronovix - 20 Apr 2017 at 08:19 UTC

    As part of our work to make Drupal 8 the leading CMS for developer portals, we are implementing a mechanism to import the OpenAPI (formerly known as Swagger) specification format. This is a crucial feature not only for dedicated developer portals, but also for all Drupal sites that are exposing an API. Now that it has become much easier to create a RESTful API service in Drupal 8, the next step is to make it more straightforward to create its API reference documentation. That is why we think our work will be useful for site builders, and not just for technical writers and API product owners.

    Re-activating Vote Up/Down

    Posted by marvil07.net - 20 Apr 2017 at 02:27 UTC

    Vote Up/Down is a drupal module that uses Voting API to provide a way to vote.
    These notes are about part of the history of the module, and the recent news about it, including a couple of releases!

    A long time ago...

    The project itself is really ancient, it started in 2006 by frjo, in Drupal 4.7, and the same code has evolved until Drupal 7.
    I took co-maintainership of the project around 2009-2010, when I met with lut4rp, at the time the one maintainer of the project; who made a rewrite to modularize it at the start of 6.x-2.x.
    At that time we were still using CVS officially (and some of us git locally), and we were thrilled to receive and integrate a patch from merlinofchaos, that extended the module a lot, and make it more maintainable.
    With the past of the time, I became the only active maintainer of the module.

    At the start I was pretty active as a maintainer there; but over the years, I have not been responsive enough, especially around the D7 port.
    During that time the community provided several patches and finally amitaibu created a sandbox, that I end up integrating into the project.
    Also, I managed to write another submodule, vud_field, in that process.
    For me it was clear, I advocated to remove vud_node, vud_term, and vud_comment form the project in favour of vud_field.
    From my perspective it was more beneficial: (a) vud_field provided mostly the same functionality on nodes, taxonomy terms, and comments; but also (b) provided voting on any entity, embracing D7 new APIs; and also (c) made things more maintainable.
    Sadly, the removal did not happened at that time, and that was one of the reasons why D7 version was never out of alpha status.

    Recent news

    After quite some time of inactivity in vote_up_down, this January, I started to port the module to D8, but I only started: only 4 porting commits got into the new 8.x-1.x branch.

    Then, I decided to add a GSoC project as student's suggestion to port Vote Up/Down to D8 for this year.

    In preparation, this week I have branched out D7 into two different versions 7.x-1.x and 7.x-2.x, adding respective releases to make things more clear:

    • 7.x.1-x (with 7.x-1.0-beta1 release): It still keeps all submodules, but it is not planned to be maintained for much longer anymore. I applied there all related code pending about vud_node, vud_comment, and vud_term.
    • 7.x-2.x (with 7.x-2.0 release): Instead, it only contains vud and vud_field, and it is planned to be maintained as the stable branch. Sadly there in not a complete upgrade path neither from 6.x-2.x nor from 7.x-1.x, but I added some starting code to do that on the related issue #1363928, and maybe someone would like to continue that.

    Hopefully one of the students proposing the port to Vote Up/Down to D8 gets accepted.
    It will be great to see the module active again!

    Etiquetas:

    Debug Drupal PHP in Vim with Vdebug

    Posted by Mediacurrent - 19 Apr 2017 at 22:51 UTC
    alt=””

    I know quite a few developers that love Vim but think they have to use an IDE to be able to debug their applications. In this post I will show you how to set up Vim as a Xdebug client.

    The Vdebug plugin for Vim provides a way to do debugging inside Vim using the tools that Vim provides to great advantage. As the project page says,

     

    Radios, Checkboxes, and Drupal’s Admin Interface

    Posted by Aten Design Group - 19 Apr 2017 at 22:09 UTC

    Custom styled form elements are a common thing to see in a design. That’s because default form styles vary visually from browser to browser and OS to OS. It makes sense that we’d want these elements styled consistently. Styling them is pretty straightforward, with the exception of select dropdowns which can be more complex. Recently, I ran into an unexpected problem when working on a site that needed a branded admin experience.

    Styling Radio and Checkbox Buttons

    There’s a simple method of styling radio buttons and checkboxes I’ve been using for a while. I first saw it from the people at Tuts+, and they provided this Pen demoing the technique. Briefly explained, we visually hide the input for our radios/checkboxes and draw a new one using :before and :after pseudo elements on the label element. CSS’ :checked selector allows us to toggle our styles based on if the input is checked or not. This technique relies on appropriately marked up inputs and labels, for example:

    <div class=”form-element”>
      <input type=”checkbox” id=”click-me”>
      <label for=”click-me”>Click Me</label>
    </div>

    Clicking the label (containing the fake checkbox styling) will toggle the state of the real checkbox that’s visually hidden.

    Drupal’s Admin Interface

    One thing I learned while working with some of Drupal’s admin interfaces is that they only supply the input, and not an accompanying label. This seemed especially true in tabled interfaces, where you’d check off rows of content and perform some action on the selected items. Since we’re hiding an input that doesn’t have a label to attach the visuals to, we just end up with a blank space. There were several options we had for how to address this issue.

    1. Drop the Custom Styles

    The simplest is to just rely on browser defaults for checkboxes and radios. It’s not a great option, but it is an affordable one for tight budgets.

    2. Create the Missing Labels

    This ended up being my first approach to fixing this, and became more akin to a game of Whack-a-Mole than I anticipated. After going through various preprocess functions, alters, and render functions I was still encountering inputs that were missing labels. Some I was never able to fully track down where the markup was coming from. Manually finding and fixing every missing label might be a viable solution if your website or application has only a handful of places you need to update. However this is not the most scalable solution, and if your product grows this can quickly become a financial black hole.

    3. Create the Missing Labels… with Javascript

    Instead of trying to find every place that creates a checkbox or radio on the server side, we could use Javascript to target every checkbox or radio input that is not followed by a label. From there, we just create the label element and insert it after the selected inputs. This is how that might look using jQuery, though it can also be done with Vanilla JS.

    This is great, as it solves the problem for every input in one fell swoop. One downside here is the Javascript dependency. Should your Javascript not run for any reason, you’re still left with the original problem of missing inputs. Another is page rendering. User’s might be left with a janky experience as Javascript inserts these elements into the DOM.

    4. Drop the Custom Styles… for Older Browsers

    In the end, this was the solution that won out. Using CSS Feature Queries and CSS’ appearance property, we’re able to provide styled inputs for most modern browsers and then fall back to default styles in browsers that lack the support we need. This gives us our custom styles, without the scaling problem of #2, and the Javascript dependency of #3. The downside to this solution is that all versions of Internet Explorer and Firefox will use their browser defaults.

    Firefox was a surprise to me, as the documentation says it supports appearance. However in practice what I got was a less appealing version of the browser default styles. Also surprisingly was by checking for only -webkit-appearance support, Edge still gets our custom styles applied. This all sat well with me for a working solution. Every team and project has it’s own constraints, so your mileage may vary.

    Migrating Wordpress into Drupal 8

    Posted by Aten Design Group - 19 Apr 2017 at 19:17 UTC

    Quite a bit has changed for the Migrate module in Drupal 8: the primary module is part of core and some of the tools have been split into their own modules. Recently, we migrated a Wordpress site into Drupal 8 and this article will help guide you in that process. If you’re looking for information about Wordpress to Drupal 7 migrations, check out Joel Steidl’s article on that here.

    At the time of writing this post, the migration modules are considered "experimental" so be aware of that as well. The module's location in core also means that all Drupal core modules also have migration-related code to help out with your Drupal upgrades. We used the WP Migrate module (Migrate Wordpress) as a starting point in bringing this content to Drupal.

    This module will give you a good basis for migration, but it is missing a few things that you might want to consider:

    • It will create all vocabularies and taxonomies based on what is in Wordpress but you will need to add some code to connect the taxonomies with posts.
    • Also, it will not bring in featured images.
    • WP content might be using the "line break to paragraphs" functionality, which you need to account for either in your text format for posts or in the migration.

    And if you are looking for information about Wordpress to Drupal 7 migrations, check out Joel Steidl's article on that here.

    Taxonomy

    There's code existing to pull in Wordpress's terms and vocabularies, but you will need to do some work to put them into the right fields with your posts. For this, I ended up taking a more efficient route by querying the source database in prepareRow():

    <?php
     
    // place in Posts.php prepareRow()
     
    // get terms for this blog post
    $tags = $this->select('wp_term_relationships', 'r')
      ->join('wp_term_taxonomy', 't', 't.term_taxonomy_id=r.term_taxonomy_id')
      ->fields('r')
      ->condition('t.taxonomy', 'tags')
      ->condition('object_id', $row->getSourceProperty('id'))->execute();
    $tags = $tags->fetchAll();
    $tags = array_map(function($tag) {
      return intval($tag['term_taxonomy_id']);
    }, $tags);
    $row->setSourceProperty('tags', $tags);
     
    // get categories for this blog post
    $category = $this->select('wp_term_relationships', 'r')
      ->join('wp_term_taxonomy', 't', 't.term_taxonomy_id=r.term_taxonomy_id')
      ->fields('r')
      ->condition('t.taxonomy', 'category')
      ->condition('object_id', $row->getSourceProperty('id'))->execute();
    $category = $category->fetchAll();
    $category = array_map(function($tag) {
      return intval($tag['term_taxonomy_id']);
    }, $category);
    $row->setSourceProperty('categories', $category);

    And then I updated the migration template with those new values:

    # add to the process section
    field_tags: tags
    field_category: tags

    Featured Images

    Wordpress stores featured images as attachment posts and stores the relationship in the postmeta table. To bring these in as image fields, we need to make file entities in Drupal which means configuring a new migration.

    First, create a migration template called wp_feature_images.yml. Note that I stole some of this from Drupal's core file module:

    id: wp_feature_images
    label: Wordpress Feature Images
    migration_tags:
      - Wordpress
    migration_group: wordpress
    source:
      plugin: feature_images
    destination:
      plugin: entity:file
    process:
      filename: filename
      uri: uri
      status:
        plugin: default_value
        default_value: 1
    # migration_dependencies:
    #   required:
    #     - wp_users

    And then create a source plugin:

    <?php
    /**
     * @file
     * Contains \Drupal\migrate_wordpress\Plugin\migrate\source\FeatureImages.
     */
     
    namespace Drupal\migrate_wordpress\Plugin\migrate\source;
     
    use Drupal\migrate\Row;
    use Drupal\migrate\Plugin\migrate\source\SqlBase;
    use Drupal\Core\File\FileSystemInterface;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    use Drupal\migrate\Plugin\MigrationInterface;
    use Drupal\Core\State\StateInterface;
     
    /**
     * Extract feature images from Wordpress database.
     *
     * @MigrateSource(
     *   id = "feature_images"
     * )
     */
    class FeatureImages extends SqlBase {
     
      public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, FileSystemInterface $file_system) {
        parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state);
        $this->fileSystem = $file_system;
      }
     
      /**
       * {@inheritdoc}
       */
      public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
        return new static(
          $configuration,
          $plugin_id,
          $plugin_definition,
          $migration,
          $container->get('state'),
          $container->get('file_system')
        );
      }
     
      /**
       * {@inheritdoc}
       */
      public function query() {
        $query = $this
          ->select('wp_postmeta', 'm')
          ->fields('p', ['ID', 'guid']);
        $query->join('wp_posts', 'p', 'p.ID=m.meta_value');
        $query
          ->condition('m.meta_key', '_thumbnail_id', '=')
          ->condition('p.post_type', 'attachment', '=')
          ->condition('p.guid', '', '<>')
          // this prevents some duplicates to get the count closer to even
          ->groupBy('ID, guid');
        return $query;
      }
     
      /**
       * {@inheritdoc}
       */
      public function fields() {
        $fields = array(
          'ID' => $this->t('The file ID.'),
          'guid' => $this->t('The file path'),
        );
        return $fields;
      }
     
      /**
       * {@inheritdoc}
       */
      public function prepareRow(Row $row) {
        $url = $row->getSourceProperty('guid');
        $parsed_url = parse_url($url);
        $filename = basename($parsed_url['path']);
        $row->setSourceProperty('filename', $filename);
        $public_path = 'public://' . $parsed_url['path'];
        $row->setSourceProperty('uri', $public_path);
     
        // download the file if it does not exist
        if (!file_exists($public_path)) {
          $public_dirname = dirname($public_path);
     
          // create directories if necessary
          if (!file_exists($public_dirname)) {
            $this->fileSystem->mkdir($public_dirname, 0775, TRUE);
          }
     
          // try to download it
          $copied = @copy($url, $public_path);
          if (!$copied) {
            return FALSE;
          }
        }
        return parent::prepareRow($row);
      }
     
      /**
       * {@inheritdoc}
       */
      public function bundleMigrationRequired() {
        return FALSE;
      }
     
      /**
       * {@inheritdoc}
       */
      public function getIds() {
        return array(
          'ID' => array(
            'type' => 'integer',
            'alias' => 'p',
          ),
        );
      }
     
    }

    In Migrate, the template defines what source, processing, and fields are created. The source plugin is used by that migration to allow you to specify what is created. The source plugin above will get the feature images for posts, but also try and download the image into Drupal's files directory.

    You can add this as a dependency for the wp_posts migration. A word of warning though: if one migration (Migration A) depends on a different migration (Migration B), all of the content from A must be migrated before B can be run. If there are images that cannot be resolved for some reason (maybe leftover DB references after an image or post is deleted), this might stop the migration because the dependency cannot be resolved.

    And finally, you will also need to add "wp_feature_images" to your manifest_wordpress.yml before running the migration.

    Converting content

    So far we have updated migration source plugins, but there are also process plugins, which can be used to change row values. As mentioned, the WP content often uses the autop filter to create paragraph/line breaks automatically so we need to change those to HTML for Drupal. (You can also just use this functionality in your text format and skip this step if having this on will not cause issues with other content)

    First, create a "src/Plugin/migrate/process" directory if one does not exist in the module and add this processor:

    <?php
     
    namespace Drupal\migrate_wordpress\Plugin\migrate\process;
     
    use Drupal\migrate\MigrateExecutableInterface;
    use Drupal\migrate\ProcessPluginBase;
    use Drupal\migrate\Row;
     
    /**
     * Apply the automatic paragraph filter to content
     *
     * @MigrateProcessPlugin(
     *   id = "wp_content"
     * )
     */
    class WpContent extends ProcessPluginBase {
     
      /**
       * {@inheritdoc}
       *
       * Split the 'administer nodes' permission from 'access content overview'.
       */
      public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
        return _filter_autop($value);
      }
     
    }

    Then, update the "process" section of "wp_posts.yml" to include this processor:

    'body/value':
        plugin: wp_content
        source: post_content

    All of this should put you on the road to getting Wordpress content migrated into a Drupal 8 site, although you’ll probably have to adjust code to your specific circumstances along the way.

    Acquia in action at DrupalCon Baltimore!

    Posted by Acquia Developer Center Blog - 19 Apr 2017 at 16:01 UTC
    Acquia's team at DrupalCon Asia Mumbai

    If you’re coming to DrupalCon Baltimore and you’re curious about Acquia, there are a couple of ways to meet the company and see what we’re about beyond the marketing and sales efforts that get directed at potential clients. One great way is to come to our sessions!

    Tags: acquia drupal planet

    Meet the ThinkShout Team at DrupalCon Baltimore

    Posted by ThinkShout - 19 Apr 2017 at 16:00 UTC

    We’re packing our bags for Baltimore and polishing up our slide decks for DrupalCon! We’re so excited to join the Drupal community for a full week of Drupal-y things. We’ve got some great content planned for this year’s conference, and we’re very excited to share it with you all - here’s what you need to know:

    Exhibit Hall

    The ThinkShout Headquarters this year is booth 432! We’ll be giving away free t-shirts and raffling off an Amazon Echo. You can enter to win for the low, low price of one business card. If you have any questions about our work, current available job opportunities, or what the weather’s like in Portland (spoiler: it’s probably raining), stop by - we’d love to chat with you!

    ThinkShout Sessions

    The ThinkShout team has two sessions in the DrupalCon agenda this year. We’re also very excited to be leading a discussion in our first DrupalCon Nonprofit Summit. Take a look at our lineup and mark your calendars

    Rapid Response Campaigns & Digital Tools” - Monday (4/24), 12:30 - 1:15pm, Nonprofit Summit

    The news cycle doesn’t stop, and your website must help you respond to emergencies, not act as a barrier. Drupal can help you react quickly, in concert with your other channels, to turn current events into opportunities to spread your message and further your mission. In this breakout session, Brett Meyer and Lev Tsypin will talk about the tools you have at your disposal in Drupal, scenarios that call for rapid response solutions and how to implement them, and strategies that will help you turn these situations into lasting engagement with your constituents.

    Demystifying Rendered Content in Drupal 8 Twig Files” - Tuesday (4/25), 3:45 - 4:45pm

    Amy Vaillancourt-Sals is going to show you the ins and outs of Twig! Twig is a robust and elegant template engine for PHP. It’s lightweight, fairly quick to pick up, very readable, and it grants users ultimate control over the markup, including wrapping elements and rendering exactly the output you need. In this session, you’ll learn about the debugging process of sorting through twig variables, using xdebug in PHPStorm, the other helpful debugging tools at your disposal, plus common patterns Amy found helpful for rendering content in twig files.

    Content Strategy in Popular Culture, Part Deux” - Thursday (4/27), 10:45 - 11:45am

    Brett Meyer’s got a sequel to his session from DrupalCon New Orleans. Another year, another array of pop culture obsessions to examine and apply to the work we do. By exploring how crucial aspects of content strategy play out in movies, music, comic books, and video games, we’ll continue to expand the palette of language we can use to explain and convince more people about the importance of content strategy online, and ensure they understand that it’s not just vital, but fun as well.

    Let’s Chat

    If you’d like to schedule some time to chat with us in advance, drop us a line via our contact form. We’d be happy to meet up with you in Baltimore!

    Cross-Pollination between Drupal and WordPress

    Posted by Lullabot - 19 Apr 2017 at 15:27 UTC

    WordPress controls a whopping 27% of the CMS market share on the web. Although it grew out of a blogging platform, it can now can handle advanced functionality similar to Drupal and is a major (yet friendly) competitor to Drupal. Like Drupal, it’s open source and has an amazing community. Both communities learn from each other, but there is still much more to share between the two platforms.

    Recently I had the opportunity to speak at WordCamp Miami on the topic of Drupal. WordCamp Miami is one of the larger WordCamps in the world, with a sold-out attendance of approximately 800 people.

    undefined What makes Drupal so great?

    Drupal commands somewhere in the neighborhood of 2% of the CMS market share of the web. It makes complex data models easy, and much of this can be accomplished through the user interface. It has very robust APIs and enables modules to share one another’s APIs. Taken together, you can develop very complex functionality with little to no custom code.

    So, what can WordPress take away from Drupal?

    Developer Experience: More and better APIs included in WordPress Core

    The WordPress plugin ecosystem could dramatically benefit from standardizing API’s in core.

    • Something analogous to Drupal’s Render API and Form API would make it possible for WordPress plugins to standardize and integrate their markup, which in turn would allow plugins to work together without stepping on each other’s toes.
    • WordPress could benefit from a way to create a custom post type in the core UI. Drupal has this functionality out the the box. WordPress has the functionality available, but only to the developer. This results in WordPress site builders searching for very specific plugins that create a specific post type, and hoping it does what they want.
    • WordPress already has plugins similar to Drupal’s Field API. Plugins such as Advanced Custom Fields and CMB2 go along way to allowing WordPress developers to easily create custom fields. Integrating something similar to this into WordPress core would allow plugin developers to count on a stable API and easily extend it.
    • An API for plugins to set dependencies on other plugins is something that Drupal has done since its beginning. It enables mini-ecosystems to develop that extend more complex modules. In Drupal, we see a module ecosystems built around Views, Fields, Commerce, Organic Groups, and more. WordPress would benefit greatly from this.
    • A go-to solution for custom query/list building would be wonderful for WordPress. Drupal has Views, but WordPress does not, so site builders end up using plugins that create very specific queries with output according to a very specific need. When a user needs to make a list of “popular posts,” they end up looking through multiple plugins dedicated to this single task.

    A potential issue with including new APIs in WordPress core is that it could possibly break WordPress’ commitment to backwards compatibility, and would also dramatically affect their plugin ecosystem (much of this functionality is for sale right now).

    WordPress Security Improvements

    WordPress has a much-maligned security reputation. Because it commands a significant portion of the web, it’s a large attack vector. WordPress sites are also frequently set up by non-technical users, who don’t have the experience to keep it (and all of its plugins) updated, and/or lock down the site properly.

    That being said, WordPress has some low-hanging fruit that would go a long way to help the platform’s reputation.

    • Brute force password protection (flood control) would prevent bots from repeatedly connecting to wp-login.php. How often do you see attempted connections to wp-login.php in your server logs?.
    • Raise the minimum supported PHP version from 5.2 (which does not receive security updates). Various WordPress plugins are already doing this, and there’s also talk about changing the ‘recommended’ version of PHP to 7.0.
    • An official public mailing list for all WordPress core and plugin vulnerabilities would be an easy way to alert developers to potential security issues. Note that there are third-party vendors that offer mailing lists like this.
    Why is WordPress’ market share so large?

    Easy: It can be set up and operated by non-developers—and there are a lot more non-developers than developers! Installing both Drupal and WordPress is dead simple, but once you’re up and running, WordPress becomes much easier.

    Case in Point: Changing Your Site's Appearance

    Changing what your site looks like is often the first thing that a new owner will want to do. With WordPress, you go to Appearance > Themes > Add New, and can easily browse themes from within your admin UI. To enable the theme, click Install, then click Activate.

    undefined

    With Drupal, you go to Appearance, but you only see core themes that are installed. If you happen to look at the top text, you read in small text that "alternative themes are available." Below that there is a button to “Install a New Theme.”

    undefined

    Clicking the button takes you to a page where you can either 1) paste in a URL to the tarball/zip, or upload a downloaded tarball/zip. You still have to know how to to download the zip or tarball, and where to extract it, and then browse to appearance, and enable the theme.

    So it goes with Drupal. The same process goes with modules and more. Drupal makes things much more difficult. 

    So, what can Drupal learn from WordPress?

    To continue to grow, Drupal needs to enable non-developers. New non-developers can eventually turn into developers, and will become “new blood” in the community. Here’s how Drupal can do it:

    • A built in theme and module browser would do wonders for enabling users to discover new functionality and ways to change their site’s appearance. A working attempt at this is the Project Browser module (available only for Drupal 7). The catch 22 of this is that you have to download this the old-fashioned way in order to use it.
    • The ability to download vetted install profiles during the Drupal installation process would be amazing. This would go a long way to enable the “casual explorers," and show them the power of Drupal. A discussion of this can be found here.
    • Automatic security updates is a feature that would be used by many smaller sites. Projects have been steered toward WordPress specifically because smaller clients don’t have the budget to pay developers to keep up with updates. This feature has been conceptually signed off on by Drupal’s core committers, but significant work has yet to be done.

    Mitigating Security Risks

    The downside for this functionality is that Drupal would need to have a writable file-system, which at it’s core, is less secure. Whether that balances out with automatic updates is debatable.

    Automatic security updates and theme/module installation would not have to be enabled out of the box. The functionality could be provided in core modules that could be enabled only when needed.

    What has Drupal already learned from WordPress?

    Cross-pollination has already been happening for a while. Let’s take a look at what the Drupal community has already, or is in the process of, implementing:

    • Semantic versioning is one of the most important changes in Drupal 8. With semantic versioning, bug fixes and new features can be added at a regular cadence. Prior to this, Drupal developers had to wait a few years for the next major version. WordPress has been doing this for a long time.
    • A better authoring experience is something that Drupal has been working on for years (remember when there was no admin theme?). With Drupal 8, the default authoring experience is finally on par with WordPress and even surpasses it in many areas.
    • Media management is the ability to upload images and video, and easily reference them from multiple pieces of content. There’s currently a media initiative to finally put this functionality in core.
    • Easier major version upgrades is something that WordPress has been doing since it’s inception.

    Drupal has traditionally required significant development work in between major versions. That however, is changing. In a recent blog post, the lead of the Drupal project, Dries Buytaert said,

    Updating from Drupal 8's latest version to Drupal 9.0.0 should be as easy as updating between minor versions of Drupal 8.

    This is a very big deal, as it drastically limits the technical debt of Drupal as new versions of Drupal appear.

    Conclusion

    Drupal and WordPress have extremely intelligent people contributing to their respective platforms. And, because of the GPL, both platforms have the opportunity to use vetted and proven approaches that are shortcuts to increased usability and usage. This, in turn, can lead to a more open (and usable) web.

    Special thanks to Jonathan Daggerhart, John TuckerMatthew Tift, and Juampy NR for reviewing and contributing to this article.

    undefined

    How to create custom Form with CRUD(Create, Delete, Update) operations in Drupal 8

    Posted by Valuebound - 19 Apr 2017 at 14:38 UTC

    Custom form with CRUD Operations is basically building the form with different fields like UID, Name, Mobile Number, Address, Email id etc. The CRUD operations for these fields is Deleting the value of the fields from the database or updating the existing value with new value, and printing the updated value. 

    How To Create a Custom form with CRUD Operations?

    To create a custom form with CRUD Operations, we need to follow the following folder structure as shown in the image. To perform the same operation of crud in drupal we need to follow the following folder structure.

    Chromatic at DrupalCon Baltimore

    Posted by Chromatic - 19 Apr 2017 at 13:00 UTC

    All the ways Chromatic will be representing at DrupalCon Baltimore next week.

    Pages

    Subscribe with RSS Subscribe to Drupal.org aggregator - Planet Drupal