Preamble
Drupal Considerations
Backdrop and Drupal Are Highly Similar
Backdrop is very similar to Drupal 7 by dint of the fact that it started off as a "fork" of Drupal 7. This significantly eases the work involved with porting a Module, because radical changes (like those required to port to WordPress, Wix or Shopify) are seldom required to get a Drupal module to work in Backdrop.
Drupal 7 Modules Only Please
If the module you intend to port was written for Drupal 7, it must first be either upgraded or downgraded to 100% Drupal 7 compatibility before proceeding with a Backdrop port!
Don't ignore the Module Ecosystem
It's often very worthwhile to do a bit of detective work before securing that download link and grinding away. You might find fixes and collaborators just waiting to be called upon to make that Module (and its future) so much better. Many contributed Drupal 7 modules have languished without active maintenance for several years. As a consequence of this Module users have turned to the discussion area to post patches, workarounds and sometimes even entire sections of re-written code. In the issues area, it's not a rare thing to see prospective Co-Maintainers volunteering to help out with the Module..all too often without any response whatsoever from the current Maintainer. Don't let all of these opportunities go to waste when porting a Drupal 7 module to Backdrop. Try to bring as much value over as you possibly can.
There is More Than One Type of Backdrop Port
Partial Port: Advantages & Drawbacks
To make things easier for people coming over from Drupal 7 with a lot of unported modules, Backdrop has an in-built Drupal Compatibility Layer that enables even the most Drupal-specific functions (like drupal_set_message
), to "just work". This means that a Drupal 7 Module may often be activated within a few seconds of being uploaded to Backdrop CMS by changing a single line of code in its .install
file!
There are serious drawbacks to this approach; speed, portability, complexity and reliability all suffer from having to move everything through the Drupal Compatibility Layer, so it's wise to listen to the advice of the Backdrop Core Team that produced the Drupal Compatibility Layer when they say:
It's OK to run your site in Compatibility Mode until your modules can all be fully ported, but it's not the greatest idea to run your site in Compatibility Mode indefinitely, because we are seriously considering removing the Drupal Compatibility Layer in Backdrop 2.0
Full Port: Advantages and Drawbacks
Backdrop has developed significant advantages over Drupal as it has been improved through time - but those advantages may only be accessed once a Module has been fully ported. Fully ported modules are faster, more portable, less complicated and more reliable than partially ported Modules, because they do not depend on the Drupal Compatibility Layer, which imposes overhead and represents another possible point of failure, to work.
It's Wise to Study Already Ported Modules
You can learn a lot from studying previously converted modules. Many of the modules that compose the Backdrop Core were critical, but very complicated and difficult to port. Some modules (Views) were famously difficult to port, especially when it came to converting the way that they stored configuration settings. You are free to choose any modules listed at the Backdrop Modules page to get started. Just follow the link to the "Project page" on Github to obtain production-grade code. An equally (if not more) valuable exercise is to trace the code commits that converted it from being a Drupal Module to being a Backdrop Module, step-by-step.
Don't Forget to Join the Contrib Team!
It is almost certain these days that if a Module is being ported, it's for the Contributed Modules (contrib) area of the Backdrop ecosystem. You are more than welcome to contribute to the Contrib area; you just have to read (and agree to) the the Contributed Project Agreement. It contains the information you need regarding how to join the Contrib Group and what the rights and obligations of a Contrib Group member are in the eyes of the larger Backdrop community.
Where to Go To Get Help
Sometimes, strange things happen. If you feel you have encountered something new, like an unlisted API change, first perform a search for it (or its error message) using the search function available at the Backdrop Change Records Area. This resource contains the canonical list of API changes.
If you have been searching fruitlessly and have run out of avenues leading to a resolution to your problem, you can report the API-related error message to the Backdrop Issue Queue to let people know you need some help.
How to Fully Port a Drupal 7 Module
TIP: This video by @quicksketch covers many of the topics in this document
This guide provides an overall workflow that enables a moderately skilled programmer to convert a Drupal 7 Modules into a Backdrop CMS Module in a minimum amount of time.
Table of Contents
- Communicate
- Use the Coder Upgrade Module
- Determine the Backdrop Version
- Create the Module Backdrop GitHub Repository
- Reorganize the Files
- Updating the README
- Modifying Your Module's .info File
- Organization of Module Files
- Configuration Management
- Classed Entities
- Default Views
- Core Modules Removed
- Features Added to Core
- Install and Uninstall Hooks
- Without Drupal Compatibility
- Testing
- Summary
- Tagging for Release
Communicate
Before you begin porting a module, we strongly recommend that you inform everyone of what you are doing. Please create:
- An issue in the Drupal 7 Module Issue Queue
- An issue in the Backdrop Contributed Modules Issue Queue
How to go about doing this is covered in the Communicating section of the Converting Drupal code page.
Use the Coder Upgrade Module
The Coder Upgrade module can carry out many of the required changes automatically. You should still, however, read through all of the below even if using Coder Upgrade, because there will likely need to be some "touch-up" changes to the code after Coder Upgrade does its conversion.
Determine the Backdrop Version
Backdrop uses semantic numbering, meaning the version number is composed of:
Major.Minor.Patchlevel-Devlevel
- The Major number, for the forseeable future, should be
1.x
- The Minor number should mirror that of the source Drupal Module (i.e.
4.15
in the above example) - The Patchlevel should reflect the application of little non-breaking bug fixes
- The Devlevel is to tag pre-release versions of the Module in order to solicit feedback
NOTE1: When you post a ported Drupal Module to GitHub as a Backdrop Module, please be sure to use the same version number as the Drupal module. If you are porting the 7.x-4.15 version of a Drupal Module, its version as a Backdrop module should be 1.x-4.15.0.
NOTE2: If you are posting pre-release versions to Github, be sure to note that in the tag. Popular Devlevel
tags for this purpose include alphaN
(where N is some incrementing integer), betaN
(where N is some incrementing integer), release_candidateN
(where N is some incrementing integer), etc...
When a new version of the Drupal module comes out (7.x-4.16) the minor-version number of the backdrop version should be updated to match (1.x-4.16.0), and the Backdrop version should contain as many of the commits from the Drupal project that you can safely incorporate.
If the Backdrop and Drupal version numbers do not match for any reason, the Backdrop release description should contain the Drupal version that is comparable.
Create the Backdrop Module GitHub Repository
The porting process typically starts by creating a new repository on GitHub for the Backdrop version, based on the Drupal 7 module codebase. This can be done using git
commands.
WARNING: If you are not (yet) a member of the backdrop contrib group you will not be able to push code into the github.com:backdrop-contrib repository. Instead, you may have to push code into a personal repository until you are approved into the contrib group.
# Checkout from drupal.org:
git clone --branch 7.x-2.x http://git.drupal.org/project/[project_name].git
cd [project_name]
# Rename the branch.
git branch -m 7.x-2.x 1.x-2.x
# Remove the old origin and point at Github instead.
git remote remove origin
git remote add origin git@github.com:backdrop-contrib/[project_name].git
# Push to the new repository.
git push origin 1.x-2.x
(Please note that the above example featured a 7.x-2.x Drupal Module)
You can now see all of releases that are on the Drupal project page (e.g., https://www.drupal.org/project/[project_name]/releases) in your repository.
Reorganize the Files
Backdrop has a more formal definition of where files should go than does Drupal. There are now recommended locations for common module files. The overall organization remains very similar, but there are some important differences. Please review the developer documentation for Backdrop modules for an explanation of the differences and the reasoning behind them.
Also, refer to the Sample Module Template to use as a handy reference for whenever you want to refresh your memory as to the "Backdrop Way" of doing things.
Here is a high-level overview:
Backdrop recommends the following file organization with respect to the module root folder:
modulename.info
modulename.module
modulename.admin.inc
modulename.pages.inc
modulename.theme.inc
modulename.api.php
config
css
js
templates
tests
Using this structure makes certain things more obvious: (A) That this module provides theme functions; (B) That this module has a settings page; and (C) That this module provides user-facing pages.
(if a module has many, many additional .inc files, it would be reasonable to place them in an includes
folder)
- Javascript related files should be kept in a
js
folder - Cascading Style Sheets (css) related files should be kept in a
css
folder - Templates related files should be kept in a
templates
folder - Tests related files should be kept in a
tests
folder
A Special Case: Tests
Remember, if your module contains tests, they should live within the tests
directory.
Moreover, information about them should be moved out of the getInfo()
method in the test class, and moved into a new tests/modulename.tests.info
.
Check out the Book test info file for an example.
Another example:
Old:
class MenuImportTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Menu export/import',
'description' => 'Perform various tests on menu_import module.',
'group' => 'Menu',
);
}
...
In the tests/menu_import.tests.info
:
[MenuImportTestCase]
name = Menu export/import
description = Perform various tests on menu_import module.
group = Menu
file = menu_import.test
Internal jQuery
If your module contains the jQuery core file, you should remove it. Backdrop currently ships with updated jQuery. If the Drupal 7 module uses third-party scripts, which are in DRUPAL_ROOT/sites/all/libraries
, then you can create a new directory BACKDROP_ROOT/libraries
, and place the script files inside this directory. The preferred method, though, is to integrate these files into your module: place inside the MODULE_ROOT/js
directory, and register it with hook_library_info()
in modulename.module
. If the library is likely to be used by others, you should create a separate module for the library, then include that module in your module's dependencies (and then others can do the same).
.make File (drush)
If your module contains a .make
file, you should consider that Drush make is no longer maintained. Composer is the supported solution.
Updating the README file
Most Drupal modules have a README.txt file.
Backdrop modules may contain a README.txt file, but they must have a README.md file that contains information about the Module in Markdown. The first (and easiest) porting task is to create a README.md file using the README.txt file.
The Backdrop README.md file has a recommended structure to follow to keep your new README.md in conformity with the "Backdrop Way". Backdrop README.md files are short summary documents.
Conversely, Drupal README.txt files can often contain voluminous and detailed documentation. This is because, at the time Drupal was being developed, there was nowhere else to keep such information. Backdrop uses GitHub as a distribution mechanism, and it features a Wiki page for every project it hosts, so that is where Backdrop prefers that "extra" Drupal README.txt information end up. If you come across extended documentation in the README.txt, be sure to move it into the Wiki area of the GitHub repository to keep README.md in conformity with the "Backdrop Way".
Modify the .info File
Here is an example Drupal .info file:
name = Book
description = Allows users to create and organize related content in an outline.
package = Core
version = VERSION
core = 7.x
files[] = book.test
files[] = includes/whatever.inc
stylesheets[all][] = book.css
configure = admin/content/book/settings
dependencies[] = node
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.34"
project = "drupal"
datestamp = "1416429488"
Here is an example Backdrop .info file:
type = module
name = Book
description = Allows users to create and organize related content in an outline.
package = Core
version = VERSION
backdrop = 1.x
stylesheets[all][] = book.css
configure = admin/content/book/settings
dependencies[] = node
At first glance, they appear quite similar...and they are!
But there are two very important differences:
type = module
backdrop = 1.x
First of all, Backdrop makes a distinction when it comes to the kind of asset being installed. The asset types include:
- modules
- themes
- layouts
If the type
of the asset is not mentioned in the .info file via:
type = module
The Backdrop packaging script at backdropcms.org will fail.
Another important change to the .info file is that it needs to be made Backdrop-specific.
The following line:
core = 7.x
Needs to be replaced by:
backdrop = 1.x
Other Changes to the .info File
In Backdrop the class registry has also been removed and replaced with a static class map (see the related change record). This means that you'll need to remove any lines in your info file that define files containing PHP classes: files[] = whatever.inc
. To have this class loaded you'll need to implement hook_autoload_info()
in your module file instead.
Test classes are an exception, however. The .test files are loaded with a .tests.info file and not listed in hook_autoload_info()
. For example: files = menu_import.test
. Read more in next section.
in the Drupal 7 .info file:
files[] = includes/whatever.inc
in the Backdrop .module file:
function hook_autoload_info() {
return array(
'ClassName' => 'includes/whatever.inc',
);
}
Finally, you can remove all of the information related to the Drupal packaging script, which usually looks like this:
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.34"
project = "drupal"
datestamp = "1416429488"
.info File Tags
There is a new feature in Backdrop: tags in the .info file. More details here.
Example:
name = Menu Export/Import
description = Import and export menu hierarchy using indented, JSON-like text files.
package = Development
tags[] = Menus
tags[] = Site Architecture
tags[] = Structure
backdrop = 1.x
dependencies[] = menu
type = module
configure = admin/structure/menu/import
Configuration Management
Drupal 7 stores most module configuration in the variables
table in the database. A trio of handy functions were provided to manipulate these variables: variable_get()
, variable_set()
, and variable_del()
.
In Backdrop, configuration is stored in flat files. These files are often called configuration (or config) files, and end in a .json extension. By default, active config files are saved into BACKDROP_ROOT/files/config_xxxx/active
(where xxxx is a long alphanumeric string generated during install and entered into settings.php). Backdrop provides the corresponding config_get()
and config_set()
functions to manage the retrieval and writing to disk.
For the purpose of backwards compatibility with Drupal 7, both the variables database table and the 'variable_
' functions still exist in Backdrop. They have been deprecated and will be removed in Backdrop 2.0, so conversion to 'config_
' is highly recommended.
In Drupal 7, the variables
table was something of a catch-all for small bits of data; it held not only configuration data (information that was typically set once and then never changed), but also environment-specific data that was regularly updated (for example, the last time that a particular cron function was called). In Backdrop, information of this latter type is called state data, is stored in the database, and is accessed using functions state_set()
and state_get()
.
In the discussion that follows, we will assume all variables are to be converted to config and will be accessed with config_set()
, and config_get()
. As you plan your conversion, though, some variables may be more appropriate for state_set()
/state_get()
. See this change record for a fuller description of the distinction.
Config Storage File(s)
To convert variables to config, first identify all the module's current variables: use your editor, search, or grep. The aim is to get an idea of the number or variables and type of configuration your module requires.
To store configuration, the module will need its own config file. Config files are commonly named 'modulename.settings.json
'.
Sometimes it is appropriate to have multiple config files, separated by type. For example, the settings for node module are saved by node type: node.type.article.json
, and node.type.page.json
.
For a module with very complex configuration, two separate settings files such as modulename.first_set_of.settings.json
, and modulename.second_set_of.settings.json
may be a better fit.
Think about how you would like to deploy this configuration. Would you prefer to deploy all the module's settings at once, or separately? It makes sense to deploy one node type at a time, but you usually want all the settings at once.
Changing the Code
Once you have decided on a single config file or several, you will need to replace every instance of a 'variable_
' function. The standard method is as follows:
Instead of
$variable = variable_get('foo', 'bar');
Use
$variable = config_get('modulename.settings', 'foo');
And instead of
variable_set('foo', $variable);
Use
config_set('modulename.settings', 'foo', $variable);
The above examples of config will read and write to a JSON file called modulename.settings.json
in the active config directory.
An alternative method for saving config, usually when getting or setting more than one value at a time, is to create a config object and use the object's get and set methods.
// Get the full config object
$config = config('modulename.settings');
// Get individual settings
$value_foo = $config->get('foo');
$value_next = $config->get('next');
This is especially useful when creating settings form arrays where you may need a '#default_value
' for many form elements. It's also the preferred method for saving values in a form submit handler, where config is being saved:
// Get the full config object
$config = config('modulename.settings');
// Set individual config settings
$config->set('setting_one', $form_state['values']['value_one']);
$config->set('setting_two', $form_state['values']['value_two']);
// Save
$config->save();
Create Config Defaults
The function variable_get()
has the useful capacity to declare default values; writing $setting = variable_get('my_setting', 'red')
allows the developer to initialize the value 'red' if 'my_setting' variable has not been set. Conversely, though, this required an initialization value to be provided every place variable_get()
was called, leading to lots of code duplication (or worse, non-duplication).
In Backdrop, there's no such thing as a variable that has not been set, and therefore config defaults need to be explicitly set at module enabling.
The simplest way to set default values for your config variables is to provide a default config file. This file should be placed into a config
directory within your module: config/modulename.settings.json
. When the module is enabled for the first time, the config file will be copied from this location into the active config directory.
BACKDROP_ROOT/modules
modulename
modulename.info
modulename.module
config
modulename.settings.json
Here is a sample config file to get started. Note the lack of a trailing comma after the last value; this is a JSON requirement.
{
"_config_name": "module_name.settings",
"setting_one": "default value 1",
"setting_two": 2,
"array_one": ["value_1", "value_2"],
"empty_array": []
}
Declare the Module's Config
Modules need to declare config files in hook_config_info()
in modulename.module
. This is how Backdrop knows that you have a config file that needs to automatically copied when the module is enabled, and removed when uninstalled. It's also how Backdrop compares changes in config during deployment.
/**
* Implements hook_config_info().
*/
function contact_config_info() {
$prefixes['modulename.first_set_of.settings'] = array(
'label' => t('First set of settings'),
'group' => t('Configuration'),
);
$prefixes['modulename.second_set_of.settings'] = array(
'label' => t('Second set of settings'),
'group' => t('Configuration'),
);
return $prefixes;
}
Create an Upgrade Path
At this stage the module should be nearly completely converted to CMI; new installs will use CMI exclusively for storing config. However, existing users with this module installed on a Drupal site and who wish to convert to Backdrop will still need a process to convert existing settings stored as variables to the config system.
Backdrop uses the hook_update_N()
system for upgrades and updates in modulename.install
. For initial porting to Backdrop 1.x, N should be in the 1000s; most commonly, modulename_update_1000()
is the update that converts variables to config.
Note that while the standard docblock summary line for implementation of a hook is "Implements hook_NAME()", the docblock for implementations of hook_update_N()
is special; it should describe what the update does, for example, "Migrate variables to config."
In this update, retrieve the values of existing variables and store them as config, then delete the variables. For example:
/**
* Move book settings from variables to config.
*/
function book_update_1000() {
// Migrate variables to config.
$config = config('book.settings');
$config->set('book_allowed_types', update_variable_get('book_allowed_types', array('book')));
$config->set('book_child_type', update_variable_get('book_child_type', 'book'));
$config->set('book_block_mode', update_variable_get('book_block_mode', 'all pages'));
$config->save();
// Delete variables.
update_variable_del('book_allowed_types');
update_variable_del('book_child_type');
update_variable_del('book_block_mode');
}
If you have renamed a column in a database table, you have to use the db_change_field()
function.
For example when 'drupal' string is replaced with 'backdrop' in the name of a column:
/**
* Rename a column in the 'book_records' table.
*/
function book_update_1001() {
db_change_field('book_records', 'drupal_user', 'backdrop_user',
array('type' => 'varchar', 'length' => 255, 'not null' => FALSE));
}
Note that when upgrading a module, all previous updates should be deleted. If a module has updates numbered 6xxx or 7xxx, be sure to remove all these updates.
When removing these updates, you should provide an implementation of hook_update_last_removed()
in modulename.install
to indicate which version of the module schema you're expecting when an upgrade is performed:
/**
* Implements hook_update_last_removed().
*/
function modulename_update_last_removed() {
return 7012;
}
Using system_settings_form()
Many settings forms use the system_settings_form()
function to finish off creating the form. From the API of system_settings_form()
:
"This function adds a submit handler and a submit button to a form array. The submit function saves all the data in the form, using variable_set(), to variables named the same as the keys in the form array."
Since variables are not used in Backdrop, system_settings_form()
has been updated to save to a single config file. If your module saves all the settings in its form to a single file, you'll need to add a new #config
key to the form array so system_settings_form()
knows where to save the values in the form build function. Such settings form functions are commonly located in either the modulename.module
or modulename.admin.inc
files.
Old:
function modulename_settings_form($form, $form_state) {
$form['modulename_my_setting'] = array(
'#type' => 'textfield',
'#title' => t('My setting'),
'#default_value' => variable_get('modulename_my_setting', ''),
);
return system_settings_form($form);
}
New:
function modulename_settings_form($form, $form_state) {
$form['#config'] = 'modulename.settings';
$form['my_setting'] = array(
'#type' => 'textfield',
'#title' => t('My setting'),
'#default_value' => config_get('modulename.settings', 'my_setting'),
);
return system_settings_form($form);
}
Note that config_get()
does not take a default value.
If you need to save values into multiple config files, we recommend that you add your own submit button, and submit handler for the form instead, as follows.
function modulename_settings_form($form, $form_state) {
$config = config('modulename.settings');
$form['my_setting'] = array(
'#type' => 'textfield',
'#title' => t('My setting'),
'#default_value' => $config->get('my_setting'),
);
// Add a submit button
$form['actions']['#type'] = 'actions';
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save configuration'),
);
return $form;
}
/**
* Submit handler for module_settings_form().
*/
function modulename_settings_form_submit($form, &$form_state) {
$config = config('modulename.settings');
$config->set('my_setting', $form_state['values']['my_setting']);
$config->save();
$config = config('modulename.other-settings');
$config->set('my_other_setting', $form_state['values']['my_other_setting']);
$config->save();
backdrop_set_message(t('The configuration options have been saved.'));
}
Notice how with the new approach, you can remove the module name from the name of your variables (if you like) since the variables are saved in individual config files that contain the module name.
Keep in mind, though, that it's common to keep the module name as part of the variable name when upgrading a Drupal 7 module to Backdrop. If other modules will be depending on your module and its settings, if you change the name of your variables in the move to config, modules that depend on yours will need to do so, too in their calls to your module's config settings.
Classed Entities
Several entities in Backdrop are now classed objects which extend the Entity Class. Users, nodes, comments, files, taxonomy terms and vocabularies have been converted to extend the new base class. Therefore programmatic creation of these objects has changed in Backdrop. For example:
Old
$node = new stdClass();
$node->type = 'blog';
$node->title = 'New Title';
...
node_save($node);
New
$node = entity_create('node', array ('type' => 'blog'));
$node->uid = $user->uid;
$node->title = 'New Title';
$node->save();
You should search for these functions in the code (further details):
node_save()
,node_load()
,node_delete()
user_save()
,user_load()
,user_delete()
file_save()
,file_load()
,file_delete()
comment_save()
,comment_load()
,comment_delete()
taxonomy_vocabulary_save()
,taxonomy_vocabulary_load()
,taxonomy_vocabulary_delete()
Node entity has a langcode
property instead of a language
property. Replace it:
Old:
$node = new stdClass();
$node->language = LANGUAGE_NONE;
New:
$node = entity_create('node', array ('type' => 'blog'));
$node->langcode = LANGUAGE_NONE;
Default Views
If your module contains any Default Views in PHP code, you might want to try the Default Views Convert to Config module.
In Drupal 7 default Views were provided by invoking hook_views_default_views()
, but this hook is absent in Backdrop. Default Views in Backdrop are provided as JSON configuration files instead. This module will allow you to drop in the PHP code for your Drupal 7 view, and it will generate a JSON file for the equivalent Backdrop view.
Core Modules Removed
There are several modules that were included in Drupal 7 that have been removed from Backdrop (see complete list). If your module implemented APIs for any of these modules, those hooks can be safely removed.
A commonly-used Drupal function was hook_help()
in modulename.module
. As the Help module was removed from Backdrop, this function no longer exists and so you should instead display any necessary help text on forms/pages directly, or in your module's GitHub Wiki.
Leaving these hooks in your code will not affect a Backdrop module in any way, since the code will simply not be called. You may leave them in place if you would like to be able run the same module on both Drupal and Backdrop sites.
Features Added to Core
The most commonly used Drupal 7 features are being added into Backdrop core. Check the list of modules those are added into Backdrop core or no longer necessary to include. If any of these is a dependency of your module, you should remove the dependencies[]
line from your modulename.info
file.
You should rewrite the dependencies[]
if the module has been replaced or its functionality integrated into an another module. In the latter case, the integrated modules' functions may have changed, in which case you may need to fix the function call. For example, the functions of the Libraries API module have been changed.
Install and Uninstall Hooks
If the module implements hook_schema()
, hook_install()
will create the schema. So, backdrop_install_schema()
is not needed to be called in hook_install()
(nor is drupal_install_schema()
). Similarly, backdrop_uninstall_schema()
(and drupal_uninstall_schema
) are unnecessary to call. Check the .install file to see if these hooks can be removed.
If your module provides separate configuration files, you should implement hook_config_info()
. This will allow the config files to be automatically removed during the module uninstallation, without having to specifically do that "manually" in an uninstall hook.
Without Drupal Compatibility
Drupal compatibility is enabled by default in the variable backdrop_drupal_compatibility
within BACKDROP_ROOT/settings.php
. The last step to completely port the module to Backdrop CMS, is to check that it works well with the Drupal compatibility disabled. To do that, you should replace
drupal
withbackdrop
,DRUPAL
withBACKDROP
,Drupal
withBackdrop
,
in all the files of the module and test its operation. Each is case sensitive. With this easy step we can avoid using deprecated functions (which could be the cause of warnings or errors). Note, however, these replacements should be done manually, not in bulk; there can be legitimate reasons for the continued existence of "Drupal" (for example, in comments explaining the difference between a Backdrop feature and its Drupal predecessor).
Testing
Some suggestions:
- Set the "All messages" option on the admin/config/development/logging page.
- Log page: admin/reports/dblog
- If your module contains a .test file, then you should enable the Testing module, and run the module's test on the admin/config/development/testing page. If you encounter an error message, you may need TestCase's classes descriptions.
Tagging for Release
Happy porting!