If you're reading this message, you use Open Source software. The last fifteen years has seen the meteoric rise of tools like Linux, Apache, Firefox, WordPress, Drupal and more; simplyusing Open Source is old hat. When it comes to building your company's web strategy around open source tools, though, the decisions can be fuzzier. The best-known arguments for Open Source are often ideological rather than pragmatic, and fail to account for the different needs of different projects and businesses.
In this Do it with Drupal session, Jeff Eaton will explain the no-nonsense pros and cons of Open Source, covering the big wins as well as the tradeoffs and common pain points. Whether your business is testing the Open Source water, betting the farm on community-maintained software, or open-sourcing its own creations, you'll learn how to avoid common pitfalls and set yourself up for success.
In Drupal's Appearance UI, all themes get a theme settings form. As a theme developer, you can customize the theme settings form, enabling site administrators to have more control over the appearance of the theme.
In this tutorial, we'll show you how to add admin-configurable settings to your theme. In the process of doing this, we'll use a variety of theme and module development skills and assume you have some familiarity with using Drupal's Form API, Configuration API, and theme system (see Prerequisites).
By the end of this tutorial, you will be able to provide custom theme settings that an administrator can use to modify the appearance of the theme.
Because current versions of Drupal are so much different from older versions like Drupal 7 upgrading to the latest version requires creating a new site using the latest version of Drupal and then migrating your old site's content and configuration into it.
There is no one right way to tackle a Drupal-to-Drupal migration. Instead, it's like walking down a path and coming to a fork in the trail and then choosing a direction over and over and over. Since every site is different, every path to a finished migration will be different, too. I know nobody wants to hear it, but every migration is its own unique adventure. Every successful migration will require its own custom code, weird shell scripts, and detailed lists of the exact order of things. But that doesn't mean there's no plan to follow.
A successful migration charts a course through the maze, while leveraging existing tools and experience to help find the shortest route and the right path at each fork--with minimal backtracking due to wrong choices.
In this tutorial we'll:
- Look at what makes a Drupal-to-Drupal migration (a major version upgrade) so tricky, and how to think about performing one
- Define 3 high-level approaches to performing a Drupal-to-Drupal migration
- Get a better idea of what the migration work entails, so you go into it with a proper mental model.
By the end of this tutorial you should be able to explain the different approaches to performing a Drupal-to-Drupal migration in broad strokes, and have a better picture of the work that will be involved.
In this video Joe looks at using hook_views_data()
in order to describe a database table to views such that views is capable of making queries to that table. We’ll talk about describing the table itself, and how to get it to appear in the views UI as an option that can be used as a base table.
Additional resources
Modules Needed
Unraveling the Drupal 8 Plugin System
Blog postPlugins play an important role in Drupal 8, and understanding how the entire plugin system works will help us better understand how, when, where, and why we use plugins.
In this chapter Joe will take a look at where to get a copy of the databasics code and what it does already. Throughout the rest of this series we will be working towards replacing functionality from the databasics modules with views integration in order to allow for greater flexibility in the ways that our module can be used. We'll talk about each of this pieces of functionality in this chapter.
Additional resources
Databasics module on GitHub
Overview of the Database Layer in Drupal 7
Before we can start building a search application we need some sample data that we can index and use for testing, not to mention a site we can use to test this all out on. In this tutorial we'll walk through installing Drupal 7 and importing some sample data.
In order for this to work I built a Drupal 7 site with a content type named Fish, and then imported a whole bunch of descriptions of various fish from Wikipedia. You should be able to use the provided database dump in order to get up and running with a sample Drupal site pre-populated with some sample data.
If you're not planning on following along and building the fish finder application in the Search API and Solr series, or are planning on implementing Solr search on your own site instead you can probably skip this tutorial. Just note that the rest of the tutorials in the series assume you've got a working Drupal 7 site with some content.
By the end of this tutorial you should have a working Drupal 7 site with sample content running on your localhost for playing with while watching the rest of the series.
So far all the data we've been migrating has come from a MySQL database but Migrate supports a number of other data sources which we can access by using a different source migration class. In this lesson we'll look at the source migration classes that are available with the migrate module and talk about what each one could be used for. Then we'll implement a migration that imports data from a CSV file since that's another common way of receiving source data.
For your convenience, we've included a copy of the sample data in the companion files. This is a duplicate of the data from lesson Set Up Migrate Demo Site and Source Data. If you've been following the lessons in order, you should not need to download the sample data set again.
Additional resources
Migrate Source Class documentation
Deploying Your Code
FreeIn this lesson we will take the code we have committed to our remote repository and manually push it to our production server. We will cover how to setup deployments on beanstalkapp.com and the some of the advantages of using a tool like this.
A question we are commonly asked is: how did your production environment recognize the new feature?
Answer: Reverting a feature reverts it back to what is in code. So by updating the code it always looks to the code so there is no need to revert it. You usually revert a feature if you have made changes that are stored in the database and you need it to look back to the code as your database changes are not what you wanted or are wrong. If the changes you made in the database are what you want, then you update/recreate the feature.
There are two main areas of translation for your Drupal site: the user interface and the content. The user interface text is mostly provided by the software, stored in the code itself. This is sometimes referred to as "hard-coded." While content is generated by users of the site, and stored in the database. Drupal core comes with the Locale module, which works with the user interface text and gives you a nice set of tools that lets you import existing translations, create or edit your own, or export your site’s translations for use on other sites. In this lesson we'll take a tour of the Locale module and discuss translation files, translating strings, language switching, and how to get a localized installation.
Additional resources
Due to the tightly coupled nature of much of Drupal 7's code most of the test suite is based around functional tests and not unit tests. However, there are a handful of unit tests in core as well as the DrupalUnitTestCase
class that we can extend to write our own unit tests. Since unit tests are an important part of a complete test suite lets take a look at how we can extend the DrupalUnitTestCase
class and add some unit tests to our module. While functional tests do a good job of telling us that something is broken and we should fix it they often are not very helpful for locating the exact problem. Unit tests on the other hand are much more specific and can generally tell us both that something is wrong, and what is wrong.
Unit tests don't have access to the database or the file system since they are not run in the context of a fully bootstrapped Drupal environment. Note that calling any Drupal functions which attempt to access the database will result in an exception being thrown and cause your tests to fail. This includes functions like watchdog()
, and module_implements()
. However, because Drupal doesn't have to be bootstrapped, and we don't have to create an entirely new environment, unit tests are a whole lot faster to execute than functional tests.
In this lesson we're going to take a look at writing a unit test for a function in our module that is used to convert a length of time in seconds to a string like 1 hour 6 minutes. We'll start by looking at the code that does the conversion, and then come up with a list of known inputs and their expected outputs. Finally, we'll write a unit test by adding a new .test file that contains our unit tests and bombarding our conversion function to make sure it's working properly.
Additional resources
In order to make the most of the entity APIs integration with other modules, such as Views, we need to describe the properties of our entity in more detail. The API can infer some information about a property based on our schema but we need to tell it that the integer stored in the updated_at column is actually a timestamp. We will do this by implementing hook_entity_property_info()
and describing each of our entities properties. With these definitions in place you will be able to use the formatters in Views much like you would for individual fields on content types provided by core.
Note: Before you implement hook_entity_property_info()
the API makes an educated guess about each property but once you've defined a single property, the API expects you to define all of the properties for your entity. Use the .install
file in your module to get a complete list of the properties you need to define with hook_property_entity_info
. You can also define additional properties that aren't mapped to fields in the database (these can be used for static properties).
Additional resources
Create a custom block with details from the database containing information about user preferences.
One of the best ways to improve both the speed, and relevancy, of search results for a Drupal site is to stop using the Drupal core search module and start using Apache Solr. Solr is a Java-based application that provides an API for interacting with Apache Lucene via HTTP to facilitate the creation of excellent applications for performing full-text content searches, with a special focus on internet-based search applications. The quick pitch for why you should use Solr is it's insanely fast, especially when compared with Drupal's default Search module, and it can be scaled to handle millions of search queries per second and huge piles of data.
Since Solr is a third party application we need a way to bridge the gap between Solr and Drupal. Really, there are two parts to this puzzle: getting the data out of Drupal and into Solr so it can be processed and indexed, and passing a search query from Drupal to Solr in order to retrieve, and display, search results. For that, we'll use the Search API module, and the Search API Solr module.
In order to demonstrate a real-world use case we'll pretend that we're the owner of a website that contains a database of fish species. As the database has grown over time we've begun to feel the limits of Drupal's MySQL full-text search and want to improve our search tools. Using Solr will allow for better matches in full-text search, faster searches, and a lot of additional functionality like partial word matches, spell checking, facets, and more.
In this series we'll cover:
- What Apache Solr is and why you should consider using it
- Installing Solr and configuring it to work well with Drupal content
- The contributed Search API module
- The contributed Search API Solr module
- Configuring Drupal to send content to Solr for indexing
- Retrieving search results from Solr and displaying them in Drupal on both a stand-alone page and with the Views module
- Using Solr field boosting to influence result relevancy
- Using the contributed Facet API module with Solr to allow for faceted search results
- Configuring stop words, synonyms, and promoted search results in Solr
This series is for anyone that wants to improve the quality of the search functionality of their Drupal-powered site. There is some system administration required to install Solr, but it's pretty straightforward. Almost everything else is done via configuration in Drupal's, or Solr's, user interface and by editing simple XML configuration files. So, no PHP, or module development experience required. We do however assume that you're already familiar with basic Drupal administration.
Additional resources
Revisions are an important concept in a content management system. Keeping track of all the edits that have been made to a particular entity over the course of its lifetime. A paper trail or sorts. This lesson takes a look at what is required in order to make our Entities support revisions.
If you've worked with Drupal's node system and enabled revisions then you've seen Drupal's basic revision handling in action. Every time you save a node, it creates a new version of that node. You can roll back to previous versions and keep track of how a piece of content has changed over time. Entity API also supports the concept of revisions and in this lesson we're going to take a look at adding revision support for our video entities.
In order to take advantage of this feature, we'll need to modify our database schema to accommodate storing multiple versions of the same entity. We'll move all fields that we want to make "revisionable" into a separate table and set up a new unique version ID field so that we can keep track of revisions.
Then we will update our hook_entity_info
implementation to tell the API that we want to use the revision system and make some changes to the code in our VideoEntityController
so that when an entity is updated we save a revision instead of overwriting the current data.
Finally we'll need to write a simple UI for viewing older versions of our video entity because the Entity API does not provide us with this code by default.
There's a reason views is the most popular module on drupal.org and it's pointy-clickly user interface is only a part of that. In this series we cover the ins and outs of writing modules that implement the Views API. Once you’ve realized the power of creating complex lists of nodes, users and other content via the views UI the next logical desire is to allow people to do that with the content provided by your custom module as well. This series will take an in-depth look at exposing your own database tables to the Views module so that users can use them as a place to pull content from including the fields themselves and meta-data about how they can be used to create relationships to other content on your site.
After getting the basics out of the way we’ll also take a look at writing our own custom field handlers to expose our module’s data to views so that it can be sorted, filtered, and queried in new ways. We’ll also look at implementing views plugins to do things like add custom access control options to views and to add new output styles.
Once you understand a bit more about how views works under the hood and how easy it is to tie in to that system you’ll be reimaging your solutions for all sorts of different problems.
Apache Solr is a world class search application built on top of the Lucene indexer. Before we start trying to integrate Solr with Drupal lets talk about what Solr is, and what makes it so good, as well as how Solr differs from the Drupal core database-backed Search module. This tutorial is a short presentation explaining Solr, Lucene, and things to consider when choosing Solr as a search technology.
Lucene is an open-source search indexer written in Java and governed by the Apache foundation. It is the underlying library that handles storing indexed content, and does so in a way that makes it extremely flexible. By treating each record as a document made up of any number of different fields Lucene is capable of storing just about anything you throw at it, as long as the resource can be broken up into fields and the textual data can be extracted from those fields. This makes it a good choice for indexing web based content where you might be dealing with HTML, PDF, XML, Microsoft Word, and all kinds of other document formats.
Solr, is an HTTP API for interacting with the Lucene application that makes it easier to create custom search applications. Like Lucene it is also open source, written in Java, and governed by the Apache foundation. Solr's extensive use of XML configuration files allows you to modify almost everything about how Solr works without having to write any Java. This makes it a great choice for anyone that's familiar with PHP but doesn't have Java experience.
When compared with Drupal core's Search module, or any MySQL full-text search tool, Solr has some distinct advantages. Including:
- Best-in-class stemming and tokenization
- Scalability; it's designed to scale both vertically and horizontally as needed
- Built-in support for facets, geospatial searches, and other advanced query options
In addition to these advantages, using Solr for your search can dramatically improve your Drupal site's performance by eliminating costly full-text queries, which can quickly turn MySQL into a bottleneck for sites with even a modest amount of content.
By the end of this tutorial you should be able to explain the advantages that Solr provides over Drupal core's search module and why it's a good choice for building ultra-fast, and accurate, search applications.
Additional resources
Development environments provide a sandbox where you can work on your application without affecting the live site.
So far all the tests that we've written are testing the functionality of our module in the context of a fresh Drupal install. However, in the real world we're also going to want to have tests that test the content of our application. As well as other things that it's unrealistic to assume we'll also have the time and resources to write a complete installation routine to replicate. Instead, it would be nice if we could test against a clone of our site rather than a from scratch installation of Drupal.
The SimpleTest module included with Drupal 7 core doesn't support this feature. However, the 7.x-2.x version of the module in contrib has a DrupalCloneTestCase
class that we can extend instead of the usual DrupalWebTestCase that operates on a clone of the database from our existing site. Allowing us to test things like, "Does the about page exist.", and other mission critical features of our site. In this lesson we'll take a look at installing the SimpleTest module from contrib, and writing some new tests using the 2.x version of the API in order to test an existing website.
Note that after you install the 2.x version of the SimpleTest module none of the tests we've written so far, or any of the tests from core will be in the list of available tests to run. This is because each tests needs to explicitly declare that it is compatible with the 2.x version of the test suite. This is done in the .info file of the module that provides the tests.
Add this to your .info file:
testing_api = 2.x
As of the time that this video was recorded you also need to apply the patch in this SimpleTest issue. The current version of the patch to use is https://www.drupal.org/files/issues/983266-10-simletest-clone.patch. Without it the DrupalCloneTestCase setup method won't properly clone the tables from your existing site. You should always use whatever the latest working patch is from that issue.
Here's how I patched it:
curl -O https://www.drupal.org/files/issues/983266-10-simletest-clone.patch
patch -p1 < 983266-10-simletest-clone.patch
Additional resources
Patched with patch from issue #983266