Problem/Motivation

The module cannot be installed because it hits an error in google_tag_requirements().

The error is:

Error: Class 'GTMSettings' not found in google_tag_requirements() (line 91 of /app/wwwroot/sites/all/modules/google_tag/google_tag.install).

It can't find the class because the module is not yet installed.

Proposed resolution

Remove $phase == 'install' from the if. Or fix the $phase == 'install' ? require_once __DIR__ . '/google_tag.module' : '';

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

alexpott created an issue. See original summary.

preethi_warrier’s picture

StatusFileSize
new1.75 KB
preethi_warrier’s picture

Status: Active » Needs review
alexpott’s picture

Status: Needs review » Needs work

Thinking about this again - I'm not sure that doing the directory creation in hook_requirements on install is correct. I think the directory creation should happen in google_tag_enable() as hook_requirements runs before a module is installed.

That said the fix in #2 looks like it will work.

Note all you have to do is make the requirement hook do nothing on install because \GTMContainerManager::createAssets() is already called from google_tag_enable() and that will create the directory if necessary - and also output messages if it fails.

alexpott’s picture

Also I'd change
if ($phase == 'runtime' || $phase == 'update' || $phase == 'install') {
to
if ($phase == 'runtime') {

There's no need for this to prevent updating your site if it fails.

Which means you could change the requirements hook to:

/**
 * Implements hook_requirements().
 */
function google_tag_requirements($phase) {
  // This hook only makes runtime checks.
  if ($phase !== 'runtime') {
    return array();
  }

  $requirements = array();
  $manager = \GTMContainerManager::getInstance();
  $containers = $manager->loadContainers();
  if (empty($containers)) {
    // Google Tag Manager container ID has not been set.
    $args = array(
      '@url1' => '/admin/config/system/google_tag/settings',
      '@url2' => '/admin/config/system/google_tag',
    );
    $description = t('Configure default settings on the <a href="@url1">module settings page</a>. Afterwards, add a container on the <a href="@url2">container management page</a>.', $args);
    $requirements['google_tag'] = array(
      'title' => t('Google Tag Manager'),
      'description' => $description,
      'severity' => REQUIREMENT_WARNING,
      'value' => t('Not configured'),
    );
  }

  // Adapted from system_requirements().
  $directory = \GTMSettings::getInstance()->get('uri');
  if (empty($directory)) {
    $requirements['google_tag_snippet_parent_directory'] = array(
      'title' => t('Google Tag Manager'),
      'description' => t('The snippet parent directory is not set. Configure default settings on the <a href="@url1">module settings page</a>.', array('@url1' => '/admin/config/system/google_tag/settings')),
      'severity' => REQUIREMENT_ERROR,
      'value' => t('Not configured'),
    );
    return $requirements;
  }
  $directory .= '/google_tag';
  if (!is_dir($directory) || !_google_tag_is_writable($directory) || !_google_tag_is_executable($directory)) {
    _file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
  }
  $is_executable = _google_tag_is_executable($directory);
  $is_writable = _google_tag_is_writable($directory);
  $is_directory = is_dir($directory);
  if (!$is_executable || !$is_writable || !$is_directory) {
    // The snippet directory does not exist or is not writable or searchable.

    // If applicable, get the directory path of stream wrapper.
    $wrapper = file_stream_wrapper_get_instance_by_uri($directory);
    if (method_exists($wrapper, 'getDirectoryPath') && ($path = $wrapper->getDirectoryPath())) {
      // getDirectoryPath() is not defined in StreamWrapperInterface; it
      // exists in LocalStream and the local storage replacement classes in
      // google_appengine; s3fs returns an empty string.
      $path .= '/google_tag';
    }
    elseif (!($path = $wrapper->getExternalUrl())) {
      $path = $directory;
    }

    if (!$is_directory) {
      $error = t('The directory %directory does not exist.', array('%directory' => $path));
      $description = t('An automated attempt to create the directory failed, possibly due to a permissions problem. Create the directory and make it writable.');
      $value = t('Does not exist');
    }
    elseif (!$is_writable) {
      $error = t('The directory %directory is not writable.', array('%directory' => $path));
      $description = t('An automated attempt to make the directory writable failed, possibly due to a permissions problem. Make the directory writable.');
      $value = t('Not writable');
    }
    else {
      $error = t('The directory %directory is not searchable.', array('%directory' => $path));
      $description = t('An automated attempt to make the directory searchable failed, possibly due to a permissions problem. Make the directory searchable.');
      $value = t('Not searchable');
    }
    if ($phase == 'install') {
      $description .= t(' For more information, see INSTALL.txt or the <a href="!handbook_url">online handbook</a>.', array('!handbook_url' => 'https://www.drupal.org/server-permissions'));
      $value = '';
    }
    $requirements['google_tag_snippet_directory'] = array(
      'title' => t('Google Tag Manager snippet directory'),
      'title' => t('Google Tag Manager snippet directory'),
      'description' => "$error $description",
      'severity' => REQUIREMENT_ERROR,
      'value' => $value,
    );
  }
  return $requirements;
}

As there's less conditionals and indentation and the intentions of the implementation are easier to grok. You can also lose the $t = get_t() as that is not necessary.

preethi_warrier’s picture

StatusFileSize
new8.22 KB
preethi_warrier’s picture

Status: Needs work » Needs review

  • solotandem committed 8450c1c on 7.x-2.x
    Issue #3101773 by preethi_warrier, solotandem Set directory on install...
solotandem’s picture

Assigned: Unassigned » solotandem
Status: Needs review » Fixed

Thanks for reporting this.

A more interesting question at this point is, "How exactly did the tests pass if this was a blocker to the install?"

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

sarahwbs’s picture

Is this actually fixed?

alphex’s picture

Umm, nope.

I just DRUSH DL
Project google_tag (7.x-2.x-dev) downloaded to /app/sites/all/modules/contrib/google_tag. [success]

And I'm still getting the error.

Error: Class 'GTMSettings' not found in google_tag_requirements() (line 91 of /app/sites/all/modules/contrib/google_tag/google_tag.install).

solotandem’s picture

@alphex If you can provide repeatable steps AND demonstrate where and how the code in this module generates the error, then start a new issue and provide the details. Include your OS and PHP version.
@sarahwbs Ditto.

I installed 7.x-2.x from command line using drush and from the UI; no errors in either case.

sdelplanque’s picture

I got the error and found the solution.

Only updaters (not fresh install of the module) are involved.

You just have to flush the cache after replacing the old version files of the module.

The Google Tag Manager .info file has new files referenced :
files[] = includes/entity/container.inc
files[] = includes/entity/manager.inc
files[] = includes/entity/manager_interface.inc
files[] = includes/entity/settings.inc

Without flushing cache, if your module is already installed, the updater can't find them.

A good old drush cc all fix the problem.

chrisgross’s picture

Clearing the cache did not work for me (or did not work alone), but running database updates did.

drush updb should do it since you can't get to update.php via the UI due to the error. A patch still may be needed, but you should always run db updates after upgrading a module.

mindaugasd’s picture