Migrating Drupal 7 to Backdrop 1.x – The Important Parts

Migrating Drupal 7 to Backdrop CMS
Backdrop is designed to act as the next version of Drupal 7 but the migration process is not necessarily seamless.

Backdrop promises to offer an easier upgrade process than making the jump to Drupal 9+ but it’s not without its pitfalls.

Fortunately the upgrade process is not heinously difficult.

This guide serves as an overview and breaks down the migration process described in the official documentation.

1. Test for Theme Compatibility

The biggest change between Drupal 7 and Backdrop has to do with how content is displayed to the user. Any custom themes you may have may not be compatible with how Backdrop displays site data. This change allows for Backdrop to do fantastic things out of the box but it accomplishes it by adding a killer feature that Drupal 7 doesn’t have — layouts.

Check out the official theme conversion documentation for more details if your theme is not compatible with Backdrop’s theme system.

2. Test for Module Compatibility

Drupal modules will not work out of the box with Backdrop. Test each module you rely on to make sure that either the functionality it provides hasn’t either been included in Backdrop core or works as intended on the new version.

Many modules need only slight tweaks in order to work with Backdrop, but in the event you rely on some API features that have been altered you can find examples for how to use nearly any function and API call through Backdrop’s examples module.

The developer forum is also very friendly if you find yourself stuck anywhere along the way.

The Backdrop documentation also offers more detailed information regarding module conversion.

3. Create a Copy of Your Drupal 7 Site

Once you have made sure your themes and modules are compatible with Backdrop then Backdrop can handle migrating your database over pretty easily. To be as safe with your data as possible we’ll duplicate your Drupal site and migrate the duplicate over just in case something goes wrong somewhere along the way.

Create a New Database and Admin Account

You’ll need to create a new empty database, username, and password for Backdrop to use.

Usually this can be also be done in the server’s settings panel.

Clone the Old Database

Copy your old database into the new one that you just created for Backdrop. Use your new user with admin privileges.

You can accomplish this using a single command in the terminal.

mysqldump orig_drupal_db -u drupal_db_user --password=mYDrupalDBP@ssw0rd | mysql -u new_backdrop_user -p new_backdrop_db

You will be asked to verify the new password and boom — a duplicated database.

Clone the Old Drupal Site

Copy every file to the new Backdrop location. This ensures that your Drupal 7 site will still work after this update should you need to reference or fall back to it in the future.

Use cp with the -r flag to deep copy the site contents.

cp -r ./old_drupal_location ./new_backdrop_location

Update Database Credentials

In order to get the new copied Drupal site to access the new database you’ll need to use the new credentials you made. Do not run update.php. You’ll need to add the new database username and password to the settings.php file.

The default location for the site’s configuration file will be in:

new_backdrop_location/sites/default/settings.php

247 $databases = array (
248   'default' =>
249   array (
250     'default' =>
251     array (
252       'database' => 'new_backdrop_db',
253       'username' => 'new_backdrop_user',
254       'password' => 'newBackdropDBP@ssw0rd',
255       'host' => 'localhost',
256       'port' => '',
257       'driver' => 'mysql',
258       'prefix' => '',
259     ),
260   ),
261 );

Look for the above lines and update them with the new user and database credentials you created earlier.

4. Turn It Off

Login to your now duplicated Drupal 7 site using your old Drupal administration credentials. https://mynewbackdropsite.com/user

Make sure any installed modules are compatible with Backdrop and turn off any modules that aren’t.

Make sure the theme is set to Bartik.

Set site to Maintenance mode and kiss Drupal goodbye.

5. Replace Core Files

Add all files from the Backdrop repository replacing the core, themes, and modules folders with backdrop’s core, themes, and modules folders etc. Take care not to replace the sites folder in the update process.

Do not run update.php until the end of step 8.

6. Add Modules, Layouts, and Themes to Their Respective Folders

Any modules and themes that you want to use should now be moved to the new_backdrop_location/modules and new_backdrop_location/themes folder.

Backdrop changes the location of your contributed modules and themes directories to the site root instead of inside the sites folder. This means that going forward all core files will be located within the core directory.

7. Move files Location

Move any user files from new_backdrop_location/sites/default/files to new_backdrop_location/files

Create a soft link from new_backdrop_location/sites/default/files to new_backdrop_location/files

ln -s new_backdrop_location/sites/default/files new_backdrop_location/files

8. Update Backdrop’s Configuration File

Backdrop stores its configuration in a different location than Drupal.

new_backdrop_location/settings.php

  7 /**
  8  * Database configuration:
  9  *
 10  * Most sites can configure their database by entering the connection string
 11  * below. If using master/slave databases or multiple connections, see the
 12  * advanced database documentation at
 13  * https://api.backdropcms.org/database-configuration
 14  */
 15 $database = 'mysql://user:pass@localhost/database_name';
 16 $database_prefix = '';

Change Line 15 to include the correct database credentials.

While you’re in this file change update_free_access on Line 59 to TRUE.

 48 /**
 49  * Access control for update.php script.
 50  *
 51  * If you are updating your Backdrop installation using the update.php script
 52  * but are not logged in using either an account with the "Administer software
 53  * updates" permission or the site maintenance account (the account that was
 54  * created during installation), you will need to modify the access check
 55  * statement below. Change the FALSE to a TRUE to disable the access check.
 56  * After finishing the upgrade, be sure to open this file again and change the
 57  * TRUE back to a FALSE!
 58  */
 59 $settings['update_free_access'] = TRUE;

This will allow the update to proceed without needing to be logged in.

Save your changes to the configuration file and visit the update page:

http://mynewbackdropsite.com/core/update.php

Proceed with all the updates and before long you will be purring along with Backdrop.

9. Secure Your Site

After the update script finishes you’ll need to set update_free_access in the backdrop settings.php file back to FALSE.

Finally, enable your custom themes, layouts, and modules before turning off maintenance mode.

10. Fix CRON

If you have cron set up on your server you’ll need to update the location the cron job visits. The correct location will be listed at https://mynewbackdropsite.com/admin/config/system/cron

Because all of Backdrop’s core files exist in the core folder, you’ll need to remember to include /core in the cron.php and update.php paths.

For instance the cron path is https://mynewbackdropsite.com/core/cron.php?cron_key=abc123...

Conclusion

While Backdrop is very similar to Drupal 7, some key changes have been made to provide for the long term stability of the platform. By removing some of the cruft of Drupal 7 a few pain points in the update process may appear — particularly when using custom modules and themes. Overall though, the Backdrop foundation seeks to update the system while also maintaining as much compatibility with existing server infrastructure as possible.

The developers of Backdrop continue to add documentation to the site but sometimes you just need to talk to someone knowledgeable about the system. The forums are a great place to ask project specific questions and to get help with things that you may be stuck on.

If you like Backdrop you can also attend community meetings to get involved with the development process or contribute to the code base.

Adding React to Backdrop CMS: A guide for a progressively decoupled application.

Buckhorn Pond

Just because Backdrop CMS is a fork of Drupal doesn’t mean everything is the same. Fortunately adding React to a page is a fairly straight forward endeavor. You can walk through this project’s source code on GitHub.

Module Creation

There are only a few requirements to build a module for Backdrop. Inside our module’s project folder we need to make two files: a .info and a .module file

Our first two files will be backdrop_sample_react_module.info and backdrop_sample_react_module.module.

backdrop_sample_react_module.info

name = Sample React App
description = This module serves as an example of a progressively decoupled React app.
backdrop = 1.x

backdrop_sample_react_module.module

<?php

    /** Implements hook_permission().
     *  Defines permissions for your application.
     */
    function backdrop_sample_react_module_permission() {
        $permissions = array(
            'administer sample react app' => array(
                'title' => t('Administer sample React app.')),
            'sample react app user' => array(
                'title' => t('Authenticated user functions'),
            ),
        );
        return $permissions;
    }

    /**
     * Implements hook_menu().
     * AKA: Routes
     * Define your application's routes using hook_menu.
     * Define Application endpoints: POST, GET available.
     * Return JSON with: 'delivery callback' =>
'backdrop_json_output',
     */
    function backdrop_sample_react_module_menu() {
        $items['sample-react-app'] = array(
            'access arguments' => array('sample react app user'),
            'description' => t('Sample application built in React for Backdrop CMS.'),
            'page callback' => 'sample_react_application_main_controller',
            'title' => t('Sample React Application'),
        );

        $items['sample-react-admin'] = array(
            'access arguments' => 'administer sample react app',
            'description' => t('Sample administration page.'),
            'page callback' => 'sample_react_application_admin_controller',
            'title' => t('Sample Admin Page'),
        );

        $items['sample-react-shared'] = array(
            'access arguments' => 'access content',
            'description' => t('Sample administration page.'),
            'page callback' => 'sample_react_application_shared_controller',
            'title' => t('Sample Shared Page'),
        );

        return $items;
    }

    /**
     * Application API Controllers
     */

    function sample_react_application_main_controller() {
        // Page visible only to authenticated users
        $page = "<h1>Hello Html</h1>";
        return $page;
    }

    function sample_react_application_admin_controller() {
        // Page visible only to admin users
        $page = "<h1>Hello Admin</h1>";
        return $page;
    }

    function sample_react_application_shared_controller() {
        // Page with shared authenticated and unauthenticated user experience.
        $page = "<h1>Hello HTML</h1>";
       return $page;
    }

A couple things to note about our module so far is that. Our .module file has an opening PHP tag but no matching closing tag. This is intentional.

So far — we’re only doing three things with our module. First, we use hook_permission() to define the various access permissions for our content. Then we use hook_menu() to define our application’s routes. hook_menu() will output an array where the keys are our routes and the values are the properties associated with those routes.

We’re able to restrict access to any of our routes by including the ‘access arguments’ key set to a value either defined in hook_permissions() or given by Backdrop. To allow a route to be accessible to unauthenticated users — use the permission ‘access content’ as our route sample-react-shared does above.

Finally, we define our controllers. These functions are called when our authenticated users visits the routes we set up in hook_menu().

Backdrop allows for several ways to output code to the client. Right now our controllers are outputting a vanilla string of HTML — shortly we’ll be using Backdrop’s render arrays to take advantage of some handy built-in functionality.

Test out your handiwork by enabling the module at admin/modules/list then visit the routes we made: /sample-react-app, /sample-react-admin, and /sample-react-shared.

Building the React App

While create-react-app is convenient, it isn’t the best way to build an app that is ready to be embedded into Backdrop. Fortunately setting up React from scratch isn’t terribly difficult.

Installing the Dependencies

Inside our module folder we’ll make a couple new folders that will house our app.

Lets put our app in:
backdrop_sample_react_module/js/react/sampleapp

Inside the terminal, navigate to the sampleapp folder and type: npm init

This will build out a basic package.json file that lists our application dependencies and scripts.

React needs a toolchain to build and render your code. We’ll start by installing the development dependencies.

npm install --save-dev @babel/cli @babel/core @babel/preset-env @babel/preset-react babel-loader webpack webpack-cli

After NPM installs the required dev dependencies we can install React.

npm install react react-dom

Add Webpack Config File

The webpack config file contains the settings that tell webpack how to handle and compile JSX.

Place this code below in a file named webpack.config.js

const path = require('path');
 
const config = {
 entry: './src/index.js',
 devtool: (process.env.NODE_ENV === 'production') ? false : 'inline-source-map',
 mode: (process.env.NODE_ENV === 'production') ? 'production' : 'development',
 output: {
   path: path.resolve(__dirname, 'build'),
   filename: 'app.bundle.js'
 },
 module: {
   rules: [
     {
       test: /\.js$/,
       exclude: /(node_modules)/,
       use: {
         loader: 'babel-loader'
       }
     }
   ]
 },
};
 
module.exports = config;

Edit package.json

We need to add a few items to our package.json file in order to be able to build our app.

 "scripts": {
   "build": "NODE_ENV=production webpack",
   "watch": "webpack --watch --progress"
 },

Add the build and watch scripts to your package.json scripts key.

Configure Babel

We’ll need to add a babel key to our package.json file to tell Babel how to handle our application.

 "babel": {
   "presets": [
     [
       "@babel/preset-env",
       {
         "targets": {
           "browsers": [
             "IE >= 11",
             "last 3 versions"
           ]
         }
       }
     ],
     "@babel/preset-react"
   ]
 }

Build Your App

Create a folder named src and add a file name index.js. This is the file that our toolchain will start the build process from.

import React from 'react';
import { render } from 'react-dom';

const App = () => {
    return (
        <div>Hello React</div>
    )
}

render(<App />, document.querySelector('#myapp'));

You should be able to run npm run watch to compile your app using development settings. Webpack will automatically watch your app’s files and recompile when they’re changed. When ready to deploy however it’s best to run npm run build to properly minimize the app for production.

Once built, you’ll see a new folder named build. Inside it will contain your app.bundle.js that we will include in our Backdrop module.

Include Your App in Backdrop

Back in our .module file we will need to change the output of our controller from HTML to a render array.

    function sample_react_application_main_controller() {
        // Page visible only to authenticated users
        $module_path = backdrop_get_path('module','backdrop_sample_react_module');
        $js_path = $module_path . '/js/react/sampleapp/build/app.bundle.js';
        $css_path = $module_path . '/css/styles.css';
        $page = array();
        $page['content'] = array(
            '#type' => 'markup',
            '#markup' => '<div id="myapp">Hello Html</div>',
            '#attached' => array(
                'js' => array(
                    array(
                        'data' => $js_path,
                        'every_page' => FALSE,
                        'group' => JS_THEME,
                        'type' => 'file',
                        'preprocess' => FALSE,
                        'scope' => 'footer',
                    )
                ),
                'css' => array(
                    array(
                        'data' => $css_path,
                        'every_page' => FALSE,
                        'group' => CSS_THEME,
                        'type' => 'file',
                        'preprocess' => FALSE,
                        )
                    ),
                ),
            );
        return $page;
    }

Instead of outputting HTML we’ve refactored our controller to output a backdrop render array. Importantly, we need to specify our scope as ‘footer’ in order to have our JavaScript load after the DOM elements have been loaded.

Conclusion

We’ve walked through the basic process to add React components to Backdrop CMS using progressive decoupling. This approach allows you to integrate your app without losing any of the features that make using a content management system so appealing. We don’t have to go fully headless just to use React.