I was rinsing my hair in the shower trying to think of what to do with myself the next two weeks.
I'm usually horrible with vacations. If I don't give myself a task on which to focus, I'll end my time off feeling exhausted, unfulfilled, and angry at myself for "wasting" so much precious time. I've wanted to contribute to Drupal 8 so badly these last few months that sometimes I'd go to bed after a long day of work and household duties tearful. So when my vacation time started, I decided I wanted to work on Drupal 8, but what specifically?
The first thing that naturally came to my mind was to contribute directly. "I only need to find the right issue," I told myself; much easier said than done. Drupal core is moving so fast that it would require considerable ramping in order for me to sort out what was even happening, let alone find an issue approachable enough for me to work on without some more experienced developer swooping in and fixing it before I had a chance to get a quarter of the way through. (This actually happened to me once already, leading to another tearful march to my bed that night.) Trying to work on core in this manner is like trying to build a skyscraper from the pinnacle down. Sure, you can do it, but it's going to be painful, confusing, and much more time consuming.
Then I remembered a few things I read the last few weeks. While Drupal 8's API is "freezing", there's still considerable time to find and fix issues that affect module contributors. Webchick put out the call that we needed module maintainers to step forward and try to port modules to D8. Another prominent Drupal developer put out a call for more Drupal-related blog posts as posts in the issue queues can be quite stale. Finishing up my shower, it hit me.
Maybe I should try to port Flag to Drupal 8.
I actually maintain two modules, Flag, and Flag_Friend. With all my recent work on Flag_Friend, I've often neglected the Flag module. Thankfully, I'm not the only maintainer on that project. I share it with two others who have much more time and experience than I. I took up Flag_Friend maintainership as it seemed like a useful module on which I could expand, as well as learn about how Flag module worked. Presently, Flag_Friend is also stuck in the review stage of an extensive rewrite, leaving me available to direct my attention elsewhere.
After thinking about it, the most amount of good I could do for the community would be to attempt to port Flag and blog about it.
And here we are.
Porting First Steps
There's an excellent video on the first steps you need to do to port your module to Drupal 8. First of all, you'll want to set up your development environment for Drupal 8. If you're a module developer for Drupal 7, you're most of the way there already. Just set up a new virtual server for Drupal 8, clone the Drupal 8 repo. If you are familiar with the Drush, the Drupal command line utility, you'll want to hit up Github and download the latest master branch. If you're an Arch Linux user, you can use your favorite AUR wrapper and install my drush-git package.
After you have your new Drupal 8 site set up:
- Change to the modules directory in the Drupal 8 installation directory.
- Clone your module's repository into the modules directory.
Yes, that's exactly the opposite thing that Drupal admins have been telling you years. All of Drupal 8 core now resides in the core directory. Do not change anything in the core directory unless you're working on a core patch!
- Rename your module's *.info file to yourModuleName.info.yml.
Drupal 8 has a new configuration file format based on the YAML. Since *.info files are basically configuration, the old *.info parser was removed and replaced with the YAML parser. As you might expect:
- Convert the contents of your old *.info file to YAML.
This is actually quite easy. The new *.info.yml file format is very similar to the original *.info format. Basically, replace all of the equal signs (=) with full colons (:). Dependencies and stylesheets are now taken as a list. See the change record for full details. Not everything is quite the same, however:
- Remove all, yes all, of your file entires.
Drupal 8 now has a new PSR-0 compatible class loader in core! This means you no longer need those file declarations in your *.info.yml file, Drupal will find them all automagically. Note that this isn't actually a Symphony thing, but a PHP 5.4 feature.
- Change the core key to read core: 8.x.
- Add type: module to your *.info.yml file.
This is necessary for Drupal 8 to recognize your module as...well...a module. With that finished, save your *.info.yml file.
Testing and Enabling
At this point, Drupal 8 should be able to recognize your module by going to Admin > Modules. If you did everything above correctly, you should see your new module in the list. You can even use the fancy new search feature on the modules page to find it without all that scrolling.
You can choose to enable the module at this point. It's likely, however, you'll get a WSOD or worse, a 500 error. If you do, change the web server error logs. I ran into an issue in my *.install file that the get_t() function no longer existed. It turns out that get_t() and st() are just t() now.
The next problem I ran into was that cache_get() no longer exists. This is because there's a new, cleaner Cache API in Drupal 8.
Once you work out the initial API changes, you should be able to get your module to enable. Some of the configuration pages and menu options may even show up. Note that unless if your module is very simple, it probably won't work. Flag, for example, is still mostly non-functional at this point. Considerable work remains to be done.
Branching and a Word about Version Numbers
"If it's not in the repo, it doesn't exist."
Now that you have part of your module ported, you should create a new branch and commit it back to your repository. If you are working on a module hosted on D.O, you'll want to do this ASAP so you can start posting issues and sharing your changes.
A word about version numbers: The biggest problem I had at this stage was to settle on a version number. While the video I linked to earlier in this post suggests using 8.x-1.x, discussion on IRC lead me to a different conclusion. Most major modules do not reset the module version back to 1.x when ported to a new core version (8.x). Instead, it's considered best practice to use the current version number. For example, Flag had a 7.x-3.x version. When I branched for Drupal 8, I used 8.x-3.x. This not only indicates that the code is for 8.x, but that it's a feature-for-feature port of the existing version.
There's still a lot of work left to do. Currently, Flag module's classes do not load correctly. Routing also needs to be converted to Drupal 8 standards.