During regular update with our public Drupal distribution, I just discover that reCAPTCHA module is now embeding recaptcha-php library within source code, which belongs to MIT license. According to my understanding we should only check-in contribution code into Drupal's CVS repository licensed with GPLv2, so I try to patch and contribute reCAPTCHA module with Library API support. Here I would like to give some sharing about how to add Library API support into your module.
Add the library path option within admin UI
It is always a good idea to let end-user choose where to store its libraries, even module support with Library API. Code below patch reCAPTCHA with such additional option. It will also check the target path during "Save configuration" so guarantee the target file is exists.
Index: recaptcha.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/recaptcha/Attic/recaptcha.admin.inc,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 recaptcha.admin.inc
--- recaptcha.admin.inc 19 May 2010 17:29:37 -0000 1.1.2.2
+++ recaptcha.admin.inc 22 Dec 2010 13:11:06 -0000
@@ -14,6 +14,14 @@ function recaptcha_admin_settings() {
_recaptcha_load_library();
$form = array();
+ $form['recaptcha_library_path'] = array(
+ '#type' => 'textfield',
+ '#title' => t('recaptcha-php library path'),
+ '#default_value' => variable_get('recaptcha_library_path', RECAPTCHA_DEFAULT_LIBRARY_PATH),
+ '#description' => t('The location where recaptcha-php is installed. Relative paths are from the Drupal root directory.'),
+ '#required' => TRUE,
+ '#after_build' => array('_recaptcha_admin_settings_check_library_path'),
+ );
$form['recaptcha_public_key'] = array(
'#type' => 'textfield',
'#title' => t('Public Key'),
@@ -84,3 +92,11 @@ function recaptcha_admin_settings_valida
form_set_error('recaptcha_tabindex', t('The Tab Index must be an integer.'));
}
}
+
+function _recaptcha_admin_settings_check_library_path($form_element) {
+ $library_path = $form_element['#value'];
+ if (!is_dir($library_path) || !(file_exists($library_path .'/recaptchalib.php'))) {
+ form_set_error($form_element['#parents'][0], t('The recaptcha-php files <em>recaptchalib.php</em> could not be found in the %library_path directory.', array('%library_path' => $library_path)));
+ }
+ return $form_element;
+}
Check if library file exists before require_once
Next we should check the target path before require_once. The original code utilize module_load_include() so will only check with local path; after patch we will check with follow cases:
- The pre-configured library path by end-user, as mentioned in previous section.
- The module local path, e.g. sites/all/modules/recaptcha.
- The library path fetch from libraries_get_path() if this function exists.
Why don't we just use Library API's libraries_get_path() but give such complicated handling? Sometime you may not hope to enforce end-user to install Library API, sometime you may hope to write your own installation profile where Library API not yet install and so module will report with library path not found, etc.
Index: recaptcha.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/recaptcha/Attic/recaptcha.module,v
retrieving revision 1.13.2.4.2.11.2.14
diff -u -p -r1.13.2.4.2.11.2.14 recaptcha.module
--- recaptcha.module 24 Sep 2010 02:25:51 -0000 1.13.2.4.2.11.2.14
+++ recaptcha.module 22 Dec 2010 13:11:07 -0000
@@ -215,5 +229,31 @@ EOT;
* Load the recaptcha library.
*/
function _recaptcha_load_library() {
- module_load_include('php', 'recaptcha', 'recaptcha/recaptchalib');
+ static $library_path = NULL;
+
+ if ($library_path == NULL) {
+ $recaptcha_path = variable_get('recaptcha_library_path', RECAPTCHA_DEFAULT_LIBRARY_PATH);
+ if (!$library_path && file_exists("$recaptcha_path/recaptchalib.php")) {
+ $library_path = $recaptcha_path;
+ }
+
+ $module_path = drupal_get_path('module', 'recaptcha');
+ if (!$library_path && file_exists("$module_path/recaptcha-php/recaptchalib.php")) {
+ $library_path = $module_path;
+ }
+
+ if (function_exists('libraries_get_path')) {
+ $libraries_get_path = libraries_get_path('recaptcha-php');
+ if (!$library_path && file_exists("$libraries_get_path/recaptchalib.php")) {
+ $library_path = $libraries_get_path;
+ }
+ }
+ }
+
+ if ($library_path !== NULL) {
+ require_once "$library_path/recaptchalib.php";
+ }
+ else {
+ drupal_set_message(t('The recaptcha-php files <em>recaptchalib.php</em> could not be found in any possible directories.'));
+ }
}
Conclusion
Adding Library API support into module shouldn't be too complicated, but increase the flexiblity for end-user to choose the suitable library version; moreover, this can escape from the license conflict nor hijacking when contribute code to Drupal CVS responsity; finally, it can also decrease the overall module package size for download :P
P.S. Above changes are already included within our pantarei-siren-6.20-dev.tar.gz. Please feel free to test it :D