/** * Tests profile info caching in non-English languages. */ function testInstallerTranslationCache() { require_once 'core/includes/install.inc'; // Prime the drupal_get_filename() static cache with the location of the // testing profile as it is not the currently active profile and we don't // yet have any cached way to retrieve its location. // @todo Remove as part of https://www.drupal.org/node/2186491 drupal_get_filename('profile', 'testing', 'core/profiles/testing/testing.info.yml'); $info_en = install_profile_info('testing', 'en'); $info_nl = install_profile_info('testing', 'nl'); $this->assertFalse(in_array('locale', $info_en['dependencies']), 'Locale is not set when installing in English.'); $this->assertTrue(in_array('locale', $info_nl['dependencies']), 'Locale is set when installing in Dutch.'); }
/** * Returns the table definition for the URL alias fixtures. * * @return array * Table definitions. */ public function tableDefinition() { $tables = array(); // Prime the drupal_get_filename() cache with the location of the system // module as its location is known and shouldn't change. // @todo Remove as part of https://www.drupal.org/node/2186491 drupal_get_filename('module', 'system', 'core/modules/system/system.info.yml'); module_load_install('system'); $schema = system_schema(); $tables['url_alias'] = AliasStorage::schemaDefinition(); $tables['key_value'] = $schema['key_value']; return $tables; }
/** * Example custom function. * * This function will be called if the Authcache:ajax JSON object contains * { 'funcname' : 'var' } Use hook_authcache_ajax() in your Drupal module * to modify the Authcache:ajax JSON object for the cached page. * * @see modulename */ function _authcache_funcname($vars) { global $user; // current user // For core or contributed modules, it's best to try to include // the module file and call the required function. Example: include_once dirname(drupal_get_filename('module', 'module_name')) . '/module_name.module'; return module_name_display_info(); // You can return an array or a single value. This will be converted into // JSON and sent back to the browser. Create a JavaScript function called // _authcache_funcname(var) to handle the return value. See authcache_example.module/.js return array(2, 3, 5, 7 => array(11, 17, 19)); }
/** * Verifies that the exception message in the profile step is correct. */ public function testSetUpWithMissingDependencies() { // Prime the drupal_get_filename() static cache with the location of the // testing profile as it is not the currently active profile and we don't // yet have any cached way to retrieve its location. // @todo Remove as part of https://www.drupal.org/node/2186491 drupal_get_filename('profile', 'testing_missing_dependencies', 'core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml'); $info = drupal_verify_profile([ 'parameters' => ['profile' => 'testing_missing_dependencies'], 'profile_info' => install_profile_info('testing_missing_dependencies'), ]); $message = $info['required_modules']['description']->render(); $this->assertContains('Missing_module1', $message); $this->assertContains('Missing_module2', $message); }
/** * {@inheritdoc} */ public function getContainerDefinition() { FileCacheFactory::setConfiguration(array('default' => array('class' => '\\Drupal\\Component\\FileCache\\NullFileCache'))); $container_builder = new ContainerBuilder(); $yaml_loader = new YamlFileLoader($container_builder); foreach (module_list() as $module) { $filename = drupal_get_filename('module', $module); $services = dirname($filename) . "/{$module}.services.yml"; if (file_exists($services)) { $yaml_loader->load($services); } } // Disabled for now. // $container_builder->compile(); $dumper = new PhpArrayDumper($container_builder); return $dumper->getArray(); }
/** * Tests that drupal_get_filename() works when the file is not in database. */ function testDrupalGetFilename() { // drupal_get_profile() is using obtaining the profile from state if the // install_state global is not set. global $install_state; $install_state['parameters']['profile'] = 'testing'; // Assert that this test is meaningful. $this->assertNull($this->container); $this->assertNull(\Drupal::getContainer()); // Retrieving the location of a module. $this->assertIdentical(drupal_get_filename('module', 'system'), 'core/modules/system/system.info.yml'); // Retrieving the location of a theme. $this->assertIdentical(drupal_get_filename('theme', 'stark'), 'core/themes/stark/stark.info.yml'); // Retrieving the location of a theme engine. $this->assertIdentical(drupal_get_filename('theme_engine', 'phptemplate'), 'core/themes/engines/phptemplate/phptemplate.info.yml'); // Retrieving the location of a profile. Profiles are a special case with // a fixed location and naming. $this->assertIdentical(drupal_get_filename('profile', 'standard'), 'core/profiles/standard/standard.info.yml'); // Searching for an item that does not exist returns NULL. $this->assertNull(drupal_get_filename('module', uniqid("", TRUE)), 'Searching for an item that does not exist returns NULL.'); }
/** * Tests that drupal_get_filename() works when the file is not in database. */ function testDrupalGetFilename() { // drupal_get_profile() is using obtaining the profile from state if the // install_state global is not set. global $install_state; $install_state['parameters']['profile'] = 'testing'; // Rebuild system.module.files state data. // @todo Remove as part of https://www.drupal.org/node/2186491 drupal_static_reset('system_rebuild_module_data'); system_rebuild_module_data(); // Retrieving the location of a module. $this->assertIdentical(drupal_get_filename('module', 'system'), 'core/modules/system/system.info.yml'); // Retrieving the location of a theme. \Drupal::service('theme_handler')->install(array('stark')); $this->assertIdentical(drupal_get_filename('theme', 'stark'), 'core/themes/stark/stark.info.yml'); // Retrieving the location of a theme engine. $this->assertIdentical(drupal_get_filename('theme_engine', 'twig'), 'core/themes/engines/twig/twig.info.yml'); // Retrieving the location of a profile. Profiles are a special case with // a fixed location and naming. $this->assertIdentical(drupal_get_filename('profile', 'testing'), 'core/profiles/testing/testing.info.yml'); // Generate a non-existing module name. $non_existing_module = uniqid("", TRUE); // Set a custom error handler so we can ignore the file not found error. set_error_handler(function ($severity, $message, $file, $line) { // Skip error handling if this is a "file not found" error. if (strstr($message, 'is missing from the file system:')) { \Drupal::state()->set('get_filename_test_triggered_error', TRUE); return; } throw new \ErrorException($message, 0, $severity, $file, $line); }); $this->assertNull(drupal_get_filename('module', $non_existing_module), 'Searching for an item that does not exist returns NULL.'); $this->assertTrue(\Drupal::state()->get('get_filename_test_triggered_error'), 'Searching for an item that does not exist triggers an error.'); // Restore the original error handler. restore_error_handler(); }
function module_list($refresh = FALSE, $sort = FALSE, $fixed_list = NULL) { static $list, $sorted_list; if ($refresh || $fixed_list) { $list = array(); $sorted_list = NULL; if ($fixed_list) { foreach ($fixed_list as $name => $module) { drupal_get_filename('module', $name, $module['filename']); $list[$name] = $name; } } else { $result = db_query("SELECT name, filename, throttle FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, filename ASC"); while ($module = db_fetch_object($result)) { if (file_exists($module->filename)) { // Determine the current throttle status and see if the module should be // loaded based on server load. We have to directly access the throttle // variables, since throttle.module may not be loaded yet. $throttle = $module->throttle && variable_get('throttle_level', 0) > 0; if (!$throttle) { drupal_get_filename('module', $module->name, $module->filename); $list[$module->name] = $module->name; } } } } } if ($sort) { if (!isset($sorted_list)) { $sorted_list = $list; ksort($sorted_list); } return $sorted_list; } return $list; }
/** * Tests DIC compilation. */ public function testCompileDIC() { // @todo: write a memory based storage backend for testing. $modules_enabled = array('system' => 'system', 'user' => 'user'); $request = Request::createFromGlobals(); $this->getTestKernel($request, $modules_enabled); // Instantiate it a second time and we should get the compiled Container // class. $kernel = $this->getTestKernel($request); $container = $kernel->getContainer(); $refClass = new \ReflectionClass($container); $is_compiled_container = !$refClass->isSubclassOf('Symfony\\Component\\DependencyInjection\\ContainerBuilder'); $this->assertTrue($is_compiled_container); // Verify that the list of modules is the same for the initial and the // compiled container. $module_list = array_keys($container->get('module_handler')->getModuleList()); $this->assertEqual(array_values($modules_enabled), $module_list); // Get the container another time, simulating a "production" environment. $container = $this->getTestKernel($request, NULL)->getContainer(); $refClass = new \ReflectionClass($container); $is_compiled_container = !$refClass->isSubclassOf('Symfony\\Component\\DependencyInjection\\ContainerBuilder'); $this->assertTrue($is_compiled_container); // Verify that the list of modules is the same for the initial and the // compiled container. $module_list = array_keys($container->get('module_handler')->getModuleList()); $this->assertEqual(array_values($modules_enabled), $module_list); // Test that our synthetic services are there. $class_loader = $container->get('class_loader'); $refClass = new \ReflectionClass($class_loader); $this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a class loader'); // We make this assertion here purely to show that the new container below // is functioning correctly, i.e. we get a brand new ContainerBuilder // which has the required new services, after changing the list of enabled // modules. $this->assertFalse($container->has('service_provider_test_class')); // Add another module so that we can test that the new module's bundle is // registered to the new container. $modules_enabled['service_provider_test'] = 'service_provider_test'; $this->getTestKernel($request, $modules_enabled); // Instantiate it a second time and we should not get a ContainerBuilder // class because we are loading the container definition from cache. $kernel = $this->getTestKernel($request, $modules_enabled); $container = $kernel->getContainer(); $refClass = new \ReflectionClass($container); $is_container_builder = $refClass->isSubclassOf('Symfony\\Component\\DependencyInjection\\ContainerBuilder'); $this->assertFalse($is_container_builder, 'Container is not a builder'); // Assert that the new module's bundle was registered to the new container. $this->assertTrue($container->has('service_provider_test_class'), 'Container has test service'); // Test that our synthetic services are there. $class_loader = $container->get('class_loader'); $refClass = new \ReflectionClass($class_loader); $this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a class loader'); // Check that the location of the new module is registered. $modules = $container->getParameter('container.modules'); $this->assertEqual($modules['service_provider_test'], array('type' => 'module', 'pathname' => drupal_get_filename('module', 'service_provider_test'), 'filename' => NULL)); // Check that the container itself is not among the persist IDs because it // does not make sense to persist the container itself. $persist_ids = $container->getParameter('persist_ids'); $this->assertIdentical(FALSE, array_search('service_container', $persist_ids)); }
$insecure_session_name = substr($sessname, 1); if (isset($_COOKIE[$sessname]) || isset($_COOKIE[$insecure_session_name])) { // Avoid later warnings about session-start : // session_start(): Cannot send session cache limiter - headers already sent // by emptying the session cache headers to send // The problem is that DRUPAL_BOOTSRAP_CONFIGURATION does a: // ini_set('session.cache_limiter', 'none'); // So we must do that after that this step is done session_cache_limiter(FALSE); // this include DRUPAL_BOOTSTRAP_VARIABLES drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION); } // Can't use module_load_include as it's not loaded yet, so fallback to // drupal_get_filename to find our module. $path = '/' . dirname(drupal_get_filename('module', 'mongodb')); require_once DRUPAL_ROOT . $path .'/mongodb.module'; // --> response is already sent, now back at work. Let's record everything if (variable_get('mongodb_statistics_count_content_views', 0)) { // We are counting content views. // A node has been viewed, so update the node's counters. $collectionname = variable_get('mongodb_node_counter_collection_name', 'node_counter'); $collection = mongodb_collection($collectionname); $nid = isset($_POST['nid']) ? (int) $_POST['nid'] : 0; $collection->update( array('_id' => $nid), array( '$inc' => array( 'totalcount' => 1,
/** * {@inheritdoc} */ function drupalGetFilename($type, $name) { return \Drupal::root() . '/' . drupal_get_filename($type, $name); }
/** * Returns a map of all config object names and their folders. * * The list is based on enabled modules and themes. The active configuration * storage is used rather than \Drupal\Core\Extension\ModuleHandler and * \Drupal\Core\Extension\ThemeHandler in order to resolve circular * dependencies between these services and \Drupal\Core\Config\ConfigInstaller * and \Drupal\Core\Config\TypedConfigManager. * * @return array * An array mapping config object names with directories. */ protected function getAllFolders() { if (!isset($this->folders)) { $this->folders = array(); $this->folders += $this->getCoreNames(); $install_profile = Settings::get('install_profile'); $profile = drupal_get_profile(); $extensions = $this->configStorage->read('core.extension'); // @todo Remove this scan as part of https://www.drupal.org/node/2186491 $listing = new ExtensionDiscovery(\Drupal::root()); if (!empty($extensions['module'])) { $modules = $extensions['module']; // Remove the install profile as this is handled later. unset($modules[$install_profile]); $profile_list = $listing->scan('profile'); if ($profile && isset($profile_list[$profile])) { // Prime the drupal_get_filename() static cache with the profile info // file location so we can use drupal_get_path() on the active profile // during the module scan. // @todo Remove as part of https://www.drupal.org/node/2186491 drupal_get_filename('profile', $profile, $profile_list[$profile]->getPathname()); } $module_list_scan = $listing->scan('module'); $module_list = array(); foreach (array_keys($modules) as $module) { if (isset($module_list_scan[$module])) { $module_list[$module] = $module_list_scan[$module]; } } $this->folders += $this->getComponentNames($module_list); } if (!empty($extensions['theme'])) { $theme_list_scan = $listing->scan('theme'); foreach (array_keys($extensions['theme']) as $theme) { if (isset($theme_list_scan[$theme])) { $theme_list[$theme] = $theme_list_scan[$theme]; } } $this->folders += $this->getComponentNames($theme_list); } if ($this->includeProfile) { // The install profile can override module default configuration. We do // this by replacing the config file path from the module/theme with the // install profile version if there are any duplicates. if (isset($profile)) { if (!isset($profile_list)) { $profile_list = $listing->scan('profile'); } if (isset($profile_list[$profile])) { $profile_folders = $this->getComponentNames(array($profile_list[$profile])); $this->folders = $profile_folders + $this->folders; } } } } return $this->folders; }
/** * {@inheritdoc} */ function drupalGetFilename($type, $name) { return DRUPAL_ROOT . '/' . drupal_get_filename($type, $name); }
/** * Example of customized block info being returned * @see authcache_example.module */ function _authcache_authcache_example($vars) { include_once './includes/common.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH); // Use FULL if needed for additional functions include_once dirname(drupal_get_filename('module', 'authcache_example')) . '/authcache_example.module'; return authcache_example_display_block_0(); }
/** * {@inheritdoc} */ public function listExtensionConfig($extension) { // Convert to Component object if it is a string if (is_string($extension)) { $pathname = drupal_get_filename('module', $extension); $extension = new Extension(\Drupal::root(), 'module', $pathname); } return array_keys($this->extensionStorage->getComponentNames([ $this->getExtensionName($extension) => $extension, ])); }
/** * Returns a map of all config object names and their folders. * * @return array * An array mapping config object names with directories. */ protected function getAllFolders() { if (!isset($this->folders)) { $this->folders = array(); $this->folders += $this->getCoreNames(); // Perform an ExtensionDiscovery scan as we cannot use drupal_get_path() // yet because the system module may not yet be enabled during install. // @todo Remove as part of https://www.drupal.org/node/2186491 $listing = new ExtensionDiscovery(\Drupal::root()); if ($profile = drupal_get_profile()) { $profile_list = $listing->scan('profile'); if (isset($profile_list[$profile])) { // Prime the drupal_get_filename() static cache with the profile info // file location so we can use drupal_get_path() on the active profile // during the module scan. // @todo Remove as part of https://www.drupal.org/node/2186491 drupal_get_filename('profile', $profile, $profile_list[$profile]->getPathname()); $this->folders += $this->getComponentNames(array($profile_list[$profile])); } } // @todo Remove as part of https://www.drupal.org/node/2186491 $this->folders += $this->getComponentNames($listing->scan('module')); $this->folders += $this->getComponentNames($listing->scan('theme')); } return $this->folders; }
/** * Sets up unit test environment. * * Unlike DrupalWebTestCase::setUp(), DrupalUnitTestCase::setUp() does not * install modules because tests are performed without accessing the database. * Any required files must be explicitly included by the child class setUp() * method. */ protected function setUp() { global $conf; // Store necessary current values before switching to the test environment. $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files'); // Reset all statics so that test is performed with a clean environment. drupal_static_reset(); // Generate temporary prefixed database to ensure that tests have a clean starting point. $this->databasePrefix = Database::getConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}'); // Create test directory. $public_files_directory = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10); file_prepare_directory($public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); $conf['file_public_path'] = $public_files_directory; // Clone the current connection and replace the current prefix. $connection_info = Database::getConnectionInfo('default'); Database::renameConnection('default', 'simpletest_original_default'); foreach ($connection_info as $target => $value) { $connection_info[$target]['prefix'] = array('default' => $value['prefix']['default'] . $this->databasePrefix); } Database::addConnectionInfo('default', 'default', $connection_info['default']); // Set user agent to be consistent with web test case. $_SERVER['HTTP_USER_AGENT'] = $this->databasePrefix; // If locale is enabled then t() will try to access the database and // subsequently will fail as the database is not accessible. $module_list = module_list(); if (isset($module_list['locale'])) { // Transform the list into the format expected as input to module_list(). foreach ($module_list as &$module) { $module = array('filename' => drupal_get_filename('module', $module)); } $this->originalModuleList = $module_list; unset($module_list['locale']); module_list(TRUE, FALSE, FALSE, $module_list); } $this->setup = TRUE; }
/** * Returns a map of all config object names and their folders. * * The list is based on installed modules and themes. The active * configuration storage is used rather than * \Drupal\Core\Extension\ModuleHandler and * \Drupal\Core\Extension\ThemeHandler in order to resolve circular * dependencies between these services and * \Drupal\Core\Config\ConfigInstaller and * \Drupal\Core\Config\TypedConfigManager. * * NOTE: This code is copied from ExtensionInstallStorage::getAllFolders() with * the following changes (Notes in CHANGED below) * - Load all modules whether installed or not * * @return array * An array mapping config object names with directories. */ public function getAllFolders() { if (!isset($this->folders)) { $this->folders = array(); $this->folders += $this->getCoreNames(); $install_profile = Settings::get('install_profile'); $profile = drupal_get_profile(); $extensions = $this->configStorage->read('core.extension'); // @todo Remove this scan as part of https://www.drupal.org/node/2186491 $listing = new ExtensionDiscovery(\Drupal::root()); // CHANGED START: Add profile directories for any bundles that use a profile. $profile_directories = []; if ($profile) { $profile_directories[] = drupal_get_path('profile', $profile); } if ($this->includeProfile) { // Add any profiles used in bundles. /** @var \Drupal\features\FeaturesAssignerInterface $assigner */ $assigner = \Drupal::service('features_assigner'); $bundles = $assigner->getBundleList(); foreach ($bundles as $bundle_name => $bundle) { if ($bundle->isProfile()) { // Register the profile directory. $profile_directory = 'profiles/' . $bundle->getProfileName(); if (is_dir($profile_directory)) { $profile_directories[] = $profile_directory; } } } } $listing->setProfileDirectories($profile_directories); // CHANGED END if (!empty($extensions['module'])) { // CHANGED START: Find ANY modules, not just installed ones. //$modules = $extensions['module']; $module_list_scan = $listing->scan('module'); $modules = $module_list_scan; // CHANGED END // Remove the install profile as this is handled later. unset($modules[$install_profile]); $profile_list = $listing->scan('profile'); if ($profile && isset($profile_list[$profile])) { // Prime the drupal_get_filename() static cache with the profile info // file location so we can use drupal_get_path() on the active profile // during the module scan. // @todo Remove as part of https://www.drupal.org/node/2186491 drupal_get_filename('profile', $profile, $profile_list[$profile]->getPathname()); } $module_list = array(); foreach (array_keys($module_list_scan) as $module) { if (isset($module_list_scan[$module])) { $module_list[$module] = $module_list_scan[$module]; } } $this->folders += $this->getComponentNames($module_list); } if (!empty($extensions['theme'])) { $theme_list_scan = $listing->scan('theme'); foreach (array_keys($extensions['theme']) as $theme) { if (isset($theme_list_scan[$theme])) { $theme_list[$theme] = $theme_list_scan[$theme]; } } $this->folders += $this->getComponentNames($theme_list); } if ($this->includeProfile) { // The install profile can override module default configuration. We do // this by replacing the config file path from the module/theme with the // install profile version if there are any duplicates. if (isset($profile)) { if (!isset($profile_list)) { $profile_list = $listing->scan('profile'); } if (isset($profile_list[$profile])) { $profile_folders = $this->getComponentNames(array($profile_list[$profile])); $this->folders = $profile_folders + $this->folders; } } } } return $this->folders; }
/** * Returns a list of the install storage items for an extension. * * @param string $type * Type of extension ('module', etc.). * @param string $name * Machine name of extension. * @param bool $do_optional * FALSE (default) to list config/install items, TRUE to list * config/optional items. * * @return string[] * List of config items provided by this extension. */ protected function listProvidedItems($type, $name, $do_optional = FALSE) { $pathname = drupal_get_filename($type, $name); $component = new Extension(\Drupal::root(), $type, $pathname); if ($do_optional) { $names = $this->extensionOptionalConfigStorage->getComponentNames(array($component)); } else { $names = $this->extensionConfigStorage->getComponentNames(array($component)); } return array_keys($names); }
/** * {@inheritdoc} */ public function listExtensionConfig($extension) { // Convert to Component object if it is a string if (is_string($extension)) { // In case this is the short form machine name, convert to full form. $extension = $this->getAssigner()->getBundle()->getFullName($extension); $pathname = drupal_get_filename('module', $extension); $extension = new Extension(\Drupal::root(), 'module', $pathname); } return $this->extensionStorages->listExtensionConfig($extension); }
/** * Tests uninstalling a module that is a "dependency" of a profile. */ function testUninstallProfileDependency() { $profile = 'minimal'; $dependency = 'dblog'; $this->setSetting('install_profile', $profile); // Prime the drupal_get_filename() static cache with the location of the // minimal profile as it is not the currently active profile and we don't // yet have any cached way to retrieve its location. // @todo Remove as part of https://www.drupal.org/node/2186491 drupal_get_filename('profile', $profile, 'core/profiles/' . $profile . '/' . $profile . '.info.yml'); $this->enableModules(array('module_test', $profile)); drupal_static_reset('system_rebuild_module_data'); $data = system_rebuild_module_data(); $this->assertTrue(isset($data[$profile]->requires[$dependency])); $this->moduleInstaller()->install(array($dependency)); $this->assertTrue($this->moduleHandler()->moduleExists($dependency)); // Uninstall the profile module "dependency". $result = $this->moduleInstaller()->uninstall(array($dependency)); $this->assertTrue($result, 'ModuleHandler::uninstall() returns TRUE.'); $this->assertFalse($this->moduleHandler()->moduleExists($dependency)); $this->assertEqual(drupal_get_installed_schema_version($dependency), SCHEMA_UNINSTALLED, "{$dependency} module was uninstalled."); // Verify that the installation profile itself was not uninstalled. $uninstalled_modules = \Drupal::state()->get('module_test.uninstall_order') ?: array(); $this->assertTrue(in_array($dependency, $uninstalled_modules), "{$dependency} module is in the list of uninstalled modules."); $this->assertFalse(in_array($profile, $uninstalled_modules), 'The installation profile is not in the list of uninstalled modules.'); }
* Minimal statistic logger for jStats. * * This file should be placed at the root of your Drupal * installation, next to your index.php file. Doing this * allows to log the hits on your page without fully * bootstraping Drupal, only loading the minimum required * files to be able to access the database. */ // Output headers & data and close connection ignore_user_abort(TRUE); ob_start(); header("Content-type: text/javascript; charset=utf-8"); header("Expires: Sun, 19 Nov 1978 05:00:00 GMT"); header("Cache-Control: no-cache"); header("Cache-Control: must-revalidate"); header("Content-Length: 13"); header("Connection: close"); print "/* jstats */\n"; @ob_end_flush(); @ob_flush(); @flush(); define('DRUPAL_ROOT', getcwd()); require_once './includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); // Manually include common.inc to get access to drupal_write_record. require_once './includes/common.inc'; // Can't use module_load_include as it's not loaded yet, so fallback to // drupal_get_filename to find our module. $path = dirname(drupal_get_filename('module', 'jstats')); require_once $path . '/jstats.inc'; jstats_callback(TRUE);