Hard-coded directory reference fix for CiviCRM 4.0 and Drupal 7

So, while playing with the membership role updates in Civi, I noticed that my cron job was running, but the membership status wasn’t updating as it should be. A look at the logs told me:

PHP Warning: include_once(): Failed opening '/opt/prod/mei.edu/drupal-7.12/sites/all/modules/contrib/civicrm/../../../default/civicrm.settings.php' for inclusion (include_path='.:/usr/share/pear:/usr/share/php') in /opt/prod/mei.edu/drupal-7.12/sites/all/modules/contrib/civicrm/civicrm.config.php on line 110 

Well that’s an odd way to reach the directory. Sure enough, that step back up the directory structure is hard-coded based on what you’re integrating Civi with.

/**
 * We are within the civicrm module, the drupal root is 2 links * above us, so use that
 */
 $currentDir = dirname( __FILE__ ) . DIRECTORY_SEPARATOR;
 if ( file_exists( $currentDir . 'settings_location.php' ) ) {
   include $currentDir . 'settings_location.php'; 
 }
 if ( defined( 'CIVICRM_CONFDIR' ) && ! isset( $confdir ) ) {
   $confdir = CIVICRM_CONFDIR; 
 } else {
   // make it relative to civicrm.config.php, else php makes it relative 
   // to the script that invokes it 
   // simple check to see if this is under sites/all or just modules
   if ( strpos( $currentDir, 'sites' . DIRECTORY_SEPARATOR . 'all' . DIRECTORY_SEPARATOR . 'modules' ) !== false ) {
     // seems like this is in drupal5 dir location $confdir = $currentDir . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..''; 
   } else {
     $confdir = $currentDir . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'sites'; 
   }
 } 

For Drupal, this assumes that you’ve put your Civi install in either /sites/all/modules/civicrm or /modules/civicrm. It then bumps up the expected number of directory levels to reach the config file, which is going to be at /sites/default/civicrm.settings.php. I split my modules into /modules/contrib/ and /modules/custom/ or use an installation profile. Unfortunately, this leaves me hanging. The quick fix is to simply change the catch-all and add another directory level or match where your actual directory is.

if ( strpos( $currentDir, 'sites' . DIRECTORY_SEPARATOR . 'all' . DIRECTORY_SEPARATOR . 'modules' ) !== false ) {
  // seems like this is in drupal5 dir location
  $confdir = $currentDir . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..'; //Changed to match custom directory structure
}

One could also specify the civi custom php directory in the admin UI, but I didn’t feel like splitting my config files, since it’s currently just a symlink to my versioned file in the installation profile anyway. Although that’s a quick fix, I’ll be back with the better solution, going and finding the civi config file.