Aug 04 2016
Aug 04

When you use Drush, especially in crontabs, you may sometimes be bitten by RAM or duration limits. Of course, running Drush with the "-d" option will provide this information, but it will only do so at the end of an annoyingly noisy output debugging the whole command run.

On the other hand, just running the Drush command within a time command won't provide fine memory reporting. Luckily Drush implements hooks to make acquiring this information easily, so here is a small gist you can use as a standalone Drush plugin or add to a module of your own:

Aug 04 2016
Aug 04

When you use Drush, especially in crontabs, you may sometimes be bitten by RAM or duration limits. Of course, running Drush with the "-d" option will provide this information, but it will only do so at the end of an annoyingly noisy output debugging the whole command run.

On the other hand, just running the Drush command within a time command won't provide fine memory reporting. Luckily Drush implements hooks to make acquiring this information easily, so here is a small gist you can use as a standalone Drush plugin or add to a module of your own:

Jun 30 2016
Jun 30

These are the slides of the presentation I gave last week at DrupalDevDays Milan about the ways using Queue API can help you speed up Drupal sites, especially in connected mode.

This is an updated for Drupal 8 version of the presentation we gave at DrupalCon Barcelona with Yuriy Gerasimov.
Nov 04 2015
Nov 04

The problem

When running tests on a server using the recent versions of the MongoDB module for Drupal, and more specifically the MongoDB simpletests, the simpletest runner may leave droppings in your MongoDB Drupal database, which have no business remaining there. How to remove them while keeping the good collections ?

The typical case will be after a failed test runs, looking like this:

> use drupal
switched to db drupal
> show collections
cache
cache_admin_menu
cache_block
cache_bootstrap
cache_field
cache_filter
cache_image
cache_menu
cache_page
cache_path
cache_token
cache_views
simpletest129468watchdog
simpletest13031cache
simpletest13031cache_bootstrap
simpletest13031cache_field
simpletest13031cache_form
simpletest13031cache_menu
simpletest311707cache
simpletest311707cache_bootstrap
simpletest311707cache_field
simpletest311707cache_menu
simpletest315780cache
simpletest315780cache_bootstrap
simpletest315780cache_field
simpletest315780cache_menu
simpletest324614watchdog
simpletest885830cache
simpletest885830cache_bootstrap
simpletest885830cache_field
simpletest885830cache_form
simpletest885830cache_menu
simpletest983006watchdog
system.indexes
system.profile
watchdog

The fix

Of course, in most cases, you will just do a db.dropDatabase() and be done with it, but sometimes you want to keep your cache, path, sessions, or watchdog eollections. Here is a simple script to do it. It's normally a one-liner, but I indented it in the gist for readability

The little trick is the use of db[e] : in such a loop, using the usual Mongoshell-style e.drop() or db.e.drop() won't work, because at this point e is a variable containing the name of the collection, not an actual collection object, so it does not carry methods like drop() (hence failing the former syntax), and is not itself the name of the collection (hence failing the latter syntax).

Aug 22 2015
Aug 22

One nice thing during Drupal 7/8 development is the ability, thanks to the devel module, to get a list of all SQL queries ran on a page. As I've been working quite a bit on MongoDB in PHP recently, I wondered how to obtain comparable results when using MongoDB in PHP projects. Looking at the D7 implementation, the magic happens in the Database class:

<?php
// Start logging on the default database.
define(DB_CHANNEL, 'my_logging_channel');
\
Database::startLog(DB_CHANNEL);// Get the log contents, typically in a shutdown handler.
$log = \Database::getLog(DB_CHANNEL);
?>

With DBTNG, that's all it takes, and devel puts it to good use UI-wise. So is there be an equivalent mechanism in MongoDB ? Of course there is !

The answer turns out to lie in the little-used, optional, third parameter to MongoClient::__construct($server, $options, $driver_options).

These driver_options can contain a context, which is a hash in which one valid key happens to be mongodb, the data for which is a hash of logging callbacks by loggable events.

Of course, there is this little issue of the PHP doc not mentioning some of the most useful events, like log_query and log_batchinsert, but once this is cleared, the logging becomes almost as simple as in Drupal:

  1. create a stream context containing these callbacks
  2. pass it to the MongoClient constructor
  3. that's it : events are now directed to your logging callbacks

This turns out not to be so much fun, though, because each of the callbacks has a specific signature, so I wrote a helper package wrapping a set of logging callbacks in a single class, and converting all of the callbacks to log to a standard PSR-3 logger. Using it, all it takes to send your MongoDB logs to your PSR-3 logger of choice is something like:

<?php
$emitter
= new Emitter();
$emitter->setLogger($logger);
$context = $emitter->createContext();
$client = new \MongoClient($server, $options, ['context' => $context];
?>

The code is available on Packagist/Composer, as fgm/mongodb_logger, or straight on Github as FGM/mongodb_logger. I'm quite interested in feedback on this one, as we have a pending feature request on this topic for Drupal, so feel free to comment on the Drupal issue, or send pull requests if you feel this is useful but needs some improvements.

Jan 25 2013
Jan 25

The issue

These last few days, I had noticed a problem with Drush Make and patches: some patches, be they rolled by our team or from elsewhere, would apply without a glitch, but some others, which worked normally according to the test bot on Drupal.org, would fail to apply without any obvious reason.

I had mostly put it out of my list of pressing issues when I really had to use an old version of OpenLayers, 7.x-2.0-alpha2 to be specific, AND apply a patch fixing one of the bugs in that module: behaviors plugin not being located correctly (http://drupal.org/node/1898662 if you want details). So I rolled the patch, tested it locally, the qa.d.o bot applied it and did not report more errors than expected for that old version.... and my Drush Make install refused to apply it.

Here was the relevant excerpt:

projects[domain] = 3.7
projects[domain][patch][] = "http://drupal.org/files/domain-foreach_argument-1879502-1.patch"
; ...snip...
projects[openlayers] = 2.0-alpha2
projects[openlayers][patch][] = "http://drupal.org/files/0001-Fix-the-path-file-declaration-for-behaviors.patch"
The Domain patch applied normally, but the OpenLayers patch would't apply. What could be wrong ?

The diagnostic

After tracing my way into DrushMakeProject::applyPatches(), I got a more explicit message: neither git patch nor trusted old patch could locate the patched file, includes/openlayers.behaviors.inc. Why ?

Comparing a standalone checkout of OpenLayers 7.x-2.0-alpha2 and the one in /tmp/make_tmp_(some id)__build__/sites/all/modules/contrib/openlayers, the problem became more obvious: that file was missing, as well as a good number of others. What ? Download failure ?

Not in the least: checking openlayers.info, I noticed the version downloaded by OpenLayers was no longer the chosen 7.x-2.0-alpha2 specified in the Makefile and which it previously downloaded normally, but the currently latest 7.x-2.0-beta3. Ahah...

The fix

After digging a bit more into Drush, it appeared that whenever you specify an extra info bit about a project download, lines in the short format like projects[openlayers] = 2.0-alpha2 are ignored, so Drush downloads the latest published version. The fix became obvious: use the "extended syntax", like this, for the same excerpt:

projects[domain][type] = module
projects[domain][version] = 3.7
projects[domain][patch][] = "http://drupal.org/files/domain-foreach_argument-1879502-1.patch"
; ... snip ...
projects[openlayers][type] = module
projects[openlayers][version] = 2.0-alpha2
projects[openlayers][patch][] = "http://drupal.org/files/0001-Fix-the-path-file-declaration-for-behaviors.patch"

This also explained why the other patches applied normally: each of them had been rolled against the latest module version, so the specified version was ignored, but the version actually being downloaded ended up being the same, and the patch applied normally.

Mar 27 2010
fgm
Mar 27

I noticed today that one of my sites returned 403 Access denied on various pages with URLs like format/<foo>, although it was an alias for a taxonomy/term/<tid> taxonomy path which was actually available when not aliased. What could be going on ?

It turned out that this issue is caused by the http://drupal.org/node/28776 patch introduced in DRUPAL-6-7 to protect various VCS paths.

That patch introduced by this issue modifies the FilesMatch clause to match on ^format$ (for SVN), which causes any path containing the format string to be denied, causing that problem. Which gives the solution if this is a problem for you: either modify the relavant FilesMatch clause or rename every path containing format on your site.

Note that this specific subpattern has been rolled back and reworked after http://drupal.org/node/581706 for DRUPAL-7-0-ALPHA2, so Drupal 7 does not have this problem.

Feb 23 2010
fgm
Feb 23

Received this Harris Interactive poll today, on behalf of Tarsus, the french company organizing the Solutions Linux expo.

One of the choices was a list of the top 30 Internet Technologies. And guess what ? For once, Drupal was on the list: first time I see it mentioned in this type of business context. Interesting.

Drupal among the top 30 internet technologies

Dec 11 2009
fgm
Dec 11

Most of the time, when working on some piece of code, I'll resort to the configured debugger in my current Zend Studio configuration. And you probably do too :-)

However, I often have to access debug-type information on live sites where installing a debugger is out of the question, and I find myself often resorting to parameter dumps like the following:

<?php
// lazy version for simple cases
function foo_bar($x, $y, $z) {
 
dsm(func_get_args());
 
// [...]// less lazy version for more hairy cases
function foo_baz($x, $y, $z) {
 
dsm(array('in foo_baz, x' => $x, 'y' => $y, 'z' => $z));
 
// ...
?>

You've probably being using it too and, of course, after the first few dozen times, it becomes a bit used. So here's a tiny snippet that makes such dumps simpler to type and use :

<?php
function foo_quux($x, $y, $z) {
 
dsm(func_get_args_hash());
 
// [...]/**
* Provide a better func_get_args()
*
* @return array
*   Hash of parameters, keyed by parameter name
*/
function func_get_args_hash() {
 
$stack = debug_backtrace();
 
$stack = $stack[1];
 
$rf = new ReflectionFunction($stack['function']);
 
$params = $rf->getParameters();
 
$ret = array();
  foreach (
$params as $index => $param) {
   
$ret[$param->name] = $stack['args'][$index];
  }
  return
$ret;
}
?>
Nov 16 2009
fgm
Nov 16

Sometimes, you want to delete a whole bunch of users, terms, or nodes, say to cleanup a site while developing and still keep its configuration, so reinstalling is not really an option, and the normal content- or user-administration pages get in your way because they only show a limited number of entries, meaning you have to delete page after page of entries.

Of course, you could just use node_delete or user_delete in D6, user_cancel in D7, and loop on all values. But there is a simpler way: just install devel module, and enable its devel_generate submodule.

The main purpose of devel_generate, as its name indicates, is to create content, be it nodes, terms or users. However, much like you use the Start button on Windows to Stop the OS, you can use devel generate to delete content instead of creating it, by enabling its optional Delete all content in these node types before generating new content checkbox. If you then choose to generate 0 entries, you'll get just a nice cleanup, without content generation, and nothing to write.

And for you Drush users, there's even an additional bonus: devel_generate has a Drush plugin implementing three equivalent commands: drush generate users|content|taxonomy. These three commands take as parameter the number of entries to generate, plus a "kill" option, which is here to remove existing content in the same way the checkbox specifies in the UI.

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web