array( 'title' => t('Administer Module Missing Message Fixer'), ), ); } /** * Implements hook_menu(). */ function module_missing_message_fixer_menu() { $items = array(); $items['admin/config/system/module-missing-message-fixer'] = array( 'title' => 'Missing Module Message Fixer', 'description' => 'This module display a list of missing module that appear after the Drupal 7.50 release and lets you fix the entries.', 'type' => MENU_NORMAL_ITEM, 'page callback' => 'drupal_get_form', 'page arguments' => array('module_missing_message_fixer_form'), 'access arguments' => array('administer module missing message fixer'), 'file' => 'includes/module_missing_message_fixer.admin.inc', ); return $items; } /** * @return string[] * Format: $[$column_key] = $cell */ function _module_missing_message_fixer_get_table_header() { return array( 'name' => 'Name', 'type' => 'Type', 'filename' => 'Filename', ); } /** * Produces one table row for each missing module. * * The table rows are suitable for drush and for the admin UI. * * @return array[] * Format: $[$extension_name][$column_key] = $cell */ function _module_missing_message_fixer_get_table_rows() { // These are special modules that have their own patches already. // This will help eliminate some of the brute force of this module. $special = array( 'adminimal_theme' => 'https://www.drupal.org/node/2763581', 'content' => 'https://www.drupal.org/node/2763555', 'field_collection_table' => 'https://www.drupal.org/node/2764331', ); // Grab all the modules in the system table. /** @var \DatabaseStatementBase|\DatabaseStatementInterface $query */ $query = db_query("SELECT filename, type, name FROM {system}"); $rows = array(); // Go through the query and check to see if the module exists in the directory. foreach ($query->fetchAll() as $record) { if ($record->name === 'default') { continue; } // Add exception to this since content module seems to be ubercart sad only. if ($record->name === 'content' && !module_exists('ubercart')) { $rows[$record->filename] = array( 'name' => $record->name, 'type' => $record->type, 'filename' => $record->filename, ); continue; } if (array_key_exists($record->name, $special)) { // Everyone else fails into here. // Set the message. $msg = t('The @module module has a patch. See this issue for more information. It WILL NOT be removed by Module Missing Message Fixer.', array( '@module' => $record->name, '@link' => $special[$record->name], )); // Now print it! drupal_set_message($msg, 'status', FALSE); continue; } // Grab the checker. $filename = drupal_get_filename( $record->type, $record->name, $record->filename, FALSE); if ($filename === NULL) { // Report this module in the table. $rows[$record->filename] = array( 'name' => $record->name, 'type' => $record->type, 'filename' => $record->filename, ); continue; } $message = NULL; $replacements = array( '@name' => $record->name, '@type' => $record->type, '@file' => $filename, ); if (!file_exists($filename)) { // This case is unexpected, because drupal_get_filename() should take care // of it already. $message = 'The file @file for @name @type is missing.'; } elseif (!is_readable($filename)) { // This case is unexpected, because drupal_get_filename() should take care // of it already. $message = 'The file @file for @name @type is not readable.'; } else { // Verify if *.info file exists. See https://www.drupal.org/node/2789993#comment-12306555 $info_filename = dirname($filename) . '/' . $record->name . '.info'; $replacements['@info_file'] = $info_filename; if (!file_exists($info_filename)) { $message = 'The *.info file @info_file for @name @type is missing.'; } elseif (!is_readable($info_filename)) { $message = 'The *.info file @info_file for @name @type is not readable.'; } } if ($message !== NULL) { // This case should never occur. drupal_set_message( t($message, $replacements), 'warning', FALSE); } } return $rows; }