<?php

/**
 * @file
 * Drupal tweaks settings to improve your functionality on your website
 *
 * @version
 *   $Id: drupal_tweaks.module,v 1.1.2.14 2009/09/27 17:29:09 kenorb Exp $
 *
 * @developers
 *   Rafal Wieczorek <kenorb@gmail.com>
 */

/**
 * Minimum recommended value of PHP memory_limit.
 */
define('DRUPAL_MINIMUM_PHP_MEMORY_LIMIT', '16M'); 
/**
 * Minimum recommended value of PHP max_execution_time limit.
 */
define('DRUPAL_MINIMUM_MAX_EXECUTION_TIME', '30'); 

/**
 * Implementation of hook_menu().
 */
function drupal_tweaks_menu() { 
  $items['admin/drupal_tweaks'] = array(
    'title' => 'Drupal Tweaks',
    'description' => "Administer items related to Drupal tweaks.",
    'position' => 'left',
    'weight' => 0,
    'page callback' => 'system_admin_menu_block_page',
    'access arguments' => array('access administration pages'),
    'file' => 'system.admin.inc',
    'file path' => drupal_get_path('module', 'system'), 
  ); 

  /* GENERAL PAGE */
  $items['admin/drupal_tweaks/general'] = array(
    'title' => 'General',
    'description' => t('General module and node operations.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('drupal_tweaks_general_op_form'),
    'access arguments' => array('administer drupal_tweaks'),
    'file' => 'includes/drupal_tweaks.admin.inc',
    'type' => MENU_NORMAL_ITEM | MENU_DEFAULT_LOCAL_TASK,
  );

  /* OPERATION PAGE */
  $items['admin/drupal_tweaks/op'] = array(
    'title' => 'Operations',
    'description' => t('Flush operations (clear cache, rebuild permissions, etc.)'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('drupal_tweaks_op_form'),
    'access arguments' => array('administer drupal_tweaks'),
    'file' => 'includes/drupal_tweaks.admin.op.inc',
    'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK,
    'weight' => 2,
  );
  $items['admin/drupal_tweaks/op/rebuild_perm'] = array(
    'title' => 'Rebuild permissions',
    'page arguments' => array('drupal_tweaks_rebuild_perm_confirm'),
    'file' => 'includes/drupal_tweaks.admin.op.inc',
    'access arguments' => array('administer drupal_tweaks'),
    'type' => MENU_CALLBACK,
  ); 
  $items['admin/drupal_tweaks/op/clear_cache'] = array(
    'title' => 'Rebuild cache',
    'page arguments' => array('drupal_tweaks_clear_cache_submit'),
    'file' => 'includes/drupal_tweaks.admin.op.inc',
    'access arguments' => array('administer drupal_tweaks'),
    'type' => MENU_CALLBACK,
  ); 
  if (module_exists('db_tweaks')) {
    /* BLOCK PAGE */
    $items['admin/drupal_tweaks/block'] = array(
      'title' => 'Block',
      'description' => t('Convert any form or node into block.'),
      'page callback' => 'drupal_get_form',
      'page arguments' => array('form2block_settings_form'),
      'access arguments' => array('administer drupal_tweaks'),
      'file' => 'form2block.admin.inc', 
      'file path' => drupal_get_path('module', 'form2block'), 
      'type' => MENU_LOCAL_TASK,
      'weight' => 3,
    );
  }

  $items['admin/drupal_tweaks/msgs'] = array(
    'title' => 'Msgs',
    'description' => t('Configure drupal messages behaviour'),
    'page callback' => 'drupal_get_form', 
    'page arguments' => array('drupal_tweaks_msgs_settings_form'), 
    'access arguments' => array('administer drupal_tweaks'),
    'file' => 'includes/drupal_tweaks.admin.msgs.inc', 
    'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK,
    'weight' => 4,
  );

  /* PHP SETTINGS PAGE */
  $items['admin/drupal_tweaks/php'] = array(
    'title' => 'PHP',
    'description' => t('PHP Settings.'),
    'page callback' => 'drupal_get_form', 
    'page arguments' => array('drupal_tweaks_php_settings_form'), 
    'access arguments' => array('administer drupal_tweaks'),
    'file' => 'includes/drupal_tweaks.admin.php.inc', 
    'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK,
    'weight' => 5,
  );

  if (module_exists('db_tweaks')) {
    /* DB SETTINGS PAGE */
    $items['admin/drupal_tweaks/db'] = array(
      'title' => 'DB',
      'description' => t('Database Settings.'),
      'page callback' => 'drupal_get_form', 
      'page arguments' => array('db_tweaks_settings_form'), 
      'access arguments' => array('administer drupal_tweaks'),
      'file' => 'db_tweaks.admin.inc', 
      'file path' => drupal_get_path('module', 'db_tweaks'), 
      'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK,
      'weight' => 6,
    );
  }

  /* TWEAKS MODULE PAGE */
  $items['admin/drupal_tweaks/module_tweaks'] = array(
    'title' => 'Tweaks',
    'description' => t('Tweaks settings for Drupal modules.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('drupal_tweaks_general_tweaks_form'),
    'access arguments' => array('administer drupal_tweaks'),
    'file' => 'includes/drupal_tweaks.admin.tweaks.inc',
    'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK,
    'weight' => 7,
  );

  /* SETTINGS PAGE */
  $items['admin/drupal_tweaks/settings'] = array(
    'title' => 'Settings',
    'description' => t('Drupal Tweaks module settings.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('drupal_tweaks_general_settings_form'),
    'access arguments' => array('administer drupal_tweaks'),
    'file' => 'includes/drupal_tweaks.admin.settings.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 8,
  );

  /* BOOTSTRAP PAGE */
  $items['admin/drupal_tweaks/bootstrap'] = array(
    'title' => 'Bootstrap',
    'description' => t('Execute bootstrap PHP code.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('drupal_tweaks_bootstrap_form'),
    'access arguments' => array('administer drupal_tweaks'),
    'file' => 'includes/drupal_tweaks.admin.bootstrap.inc',
    'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK,
    'weight' => 9,
  );

  /* REPORT PAGE */
  $items['admin/drupal_tweaks/suggestions'] = array(
    'title' => 'Suggestions',
    'description' => t('Check for problems or suggestions with your website.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('drupal_tweaks_report_form'),
    'access arguments' => array('administer drupal_tweaks'),
    'file' => 'includes/drupal_tweaks.admin.suggestions.inc',
    'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK,
    'weight' => 10,
  );

  /* AJAX CALLBACKS */
  $items['admin/drupal_tweaks/autocomplete/enabled_modules'] = array(
    'title' => 'Enable the module.',
    'page callback' => 'drupal_tweaks_autocomplete_modules',
    'access callback' => 'user_access',
    'access arguments' => array('administer drupal_tweaks'),
    'type' => MENU_CALLBACK,
    'file' => 'includes/drupal_tweaks.ajax.inc',
  );
  $items['admin/drupal_tweaks/autocomplete/disabled_modules'] = array(
    'title' => 'Disable the module.',
    'page callback' => 'drupal_tweaks_autocomplete_modules',
    'access callback' => 'user_access',
    'access arguments' => array('administer drupal_tweaks'),
    'type' => MENU_CALLBACK,
    'file' => 'includes/drupal_tweaks.ajax.inc',
  );
  $items['admin/drupal_tweaks/autocomplete/nodes'] = array(
    'title' => 'Find the node.',
    'page callback' => 'drupal_tweaks_autocomplete_nodes',
    'access callback' => 'user_access',
    'access arguments' => array('administer drupal_tweaks'),
    'type' => MENU_CALLBACK,
    'file' => 'includes/drupal_tweaks.ajax.inc',
  );
  $items['admin/drupal_tweaks/autocomplete/form_id'] = array(
    'title' => 'Find the node.',
    'page callback' => 'drupal_tweaks_autocomplete_form_id',
    'access callback' => 'user_access',
    'access arguments' => array('administer drupal_tweaks'),
    'type' => MENU_CALLBACK,
    'file' => 'includes/drupal_tweaks.ajax.inc',
  );

  return $items;
}


/**
 * Implementation of hook_init().
 */
function drupal_tweaks_boot() {
  /* LOAD BOOTSTRAP CODE */
  if (variable_get('drupal_tweaks_bootstrap_code_activated', FALSE) && $code = variable_get('drupal_tweaks_bootstrap_code', '')) {
    eval($code);
  }

  /* PHP TWEAKS */
  if (variable_get('drupal_tweaks_php_activated', FALSE)) {
    /* LOAD INCLUDES */
    include_once './includes/common.inc'; // for t() called from menu_get_item() AND drupal_get_path() called from module_load_include()
    include_once './includes/path.inc';   // for arg() called from menu_get_item()
    include_once './includes/unicode.inc';   // for drupal_strtolower() called from parse_size()
    module_load_include('inc', 'drupal_tweaks'); // load additional function from included file

    /* LOAD DB SETTINGS */
    $php_conf = drupal_tweaks_get_php_configuration(TRUE);

    /* validate PHP */
    foreach ($php_conf as $var_name => $var_values) {
        // update mysql settings if necessary
        if ($var_values['conf'] <> $var_values['php']) {
            if (!ini_set($var_name, $var_values['conf'])) {
              include_once './includes/theme.inc';   // for theme() called from t()
              drupal_set_message(t('Cannot set variable `%variable` to `%value` in your PHP configuration!', array('%variable' => $var_name, '%value' => $var_values['conf'])). t('<br>') . t('Probably you do not have proper privileges.'), 'error');
              variable_set($var_name, $var_values['php']); // reverting changes in settings (to prevent showing error message)
            }
        }
    }
  }
}

/**
 * Implementation of hook_form_alter().
 */
function drupal_tweaks_form_alter(&$form, $form_state, $form_id) {
  //drupal_set_message($form_id);
  /* MODULE TWEAKS */
  switch ($form_id) {
    case 'node_admin_content':
      // TODO: something here?
      break;
    case 'filter_admin_format_form':
      if (variable_get('drupal_tweaks_filter_tweak', TRUE)) {
        /* add module name on each filter name (See: admin/settings/filters/1) */
        foreach (filter_list_all() as $filter_key => $filter_data) {
          if (array_key_exists($filter_key, $form['filters'])) {
            $form['filters'][$filter_key]['#title'] .= " ($filter_data->module)";
          }
        }
      }
      break;
    case 'views_ui_list_views_form':
      if (variable_get('drupal_tweaks_views_tweak', TRUE)) {
        views_include_default_views(); 
        // Invoke hook_views_default_views for all modules.
        foreach (module_implements('views_default_views') as $module) {
          $default_views = module_invoke($module, 'views_default_views');
          $view_names = $default_views ? array_keys($default_views) : array();
          foreach ($view_names as $view_name) {
            if (array_key_exists($view_name, $form['#parameters'][1]['views'])) {
              $desc = &$form['#parameters'][1]['views'][$view_name]->description;
              $desc = t('Module: ') . $module . '; ' . $desc;
            }
          }
        } 
      }
      break;
  }
}

/**
 * Implementation of hook_perm().
 */
function drupal_tweaks_perm() {
   return array('administer drupal_tweaks', 'show all status messages', 'show all warning messages', 'show all error messages');
}

/**
 * Implementation of hook_exit().
 */
function drupal_tweaks_exit() {
}

/**
 * Implementation of hook_theme_registry_alter().
 * Adds our own preprocess functions to some templates.
 */
function drupal_tweaks_theme_registry_alter(&$items) {
  variable_set('drupal_tweaks_status_messages_theme_callback', $items['status_messages']['function']); // FIXME: later we can restore it in case if it's different than default
  $items['status_messages']['function'] = 'drupal_tweaks_msg2log_theme_status_messages'; // take over theme_status_messages
}

/**
 * Return a themed set of status and/or error messages. The messages are grouped
 * by type.
 *
 * @param $display
 *   (optional) Set to 'status' or 'error' to display only messages of that type.
 *
 * @return
 *   A string containing the messages.
 */
function drupal_tweaks_msg2log_theme_status_messages($display = NULL) {
  if (variable_get('drupal_tweaks_msg2log_activated', FALSE) && $messages_all = drupal_get_messages($display, FALSE)) {
    foreach ($messages_all as $type => &$messages) {
      foreach ($messages as $key => &$message) {
        if (strlen($message) > variable_get('drupal_tweaks_msg2log_max_length', 1000)) {
          continue;
        }
        if (user_access('administer drupal_tweaks')) { // store all messages in separate session variable (used on settings page)
            $_SESSION['drupal_tweaks_messages'][$type][] = $_SESSION['messages'][$type][$key]; 
            module_load_include('inc', 'drupal_tweaks'); // load additional function from included file
            drupal_tweaks_msgs_give_advice($message, $type); // check if there is some advice regarding current message
        }
        if (!user_access("show all $type messages") && drupal_tweaks_msg2log_check_rule($message, $type)) {
          watchdog($type, $message);
          unset($_SESSION['messages'][$type][$key]);
        }
      }
      if (empty($_SESSION['messages'][$type])) {
        unset($_SESSION['messages'][$type]);
      }
    }
  }
  $org_callback = variable_get('drupal_tweaks_status_messages_theme_callback', 'theme_status_messages');
  return $org_callback($display);
}

/**
 * Check rule for single message if user should see it
 *
 * @param string $message
 *   message to check
 * @param string $type (optional)
 *   The type of the message. One of the following values are possible:
 *   - 'status'
 *   - 'warning'
 *   - 'error'
 *
 * @return
 *   TRUE if rule was found (log the message), FALSE if rule wasn't found (ignore the message)
 */
function drupal_tweaks_msg2log_check_rule($message, $type = NULL) {
  $msg_rules = explode("\n", variable_get('drupal_tweaks_msgs_' . $type . '_regex', implode("\n", drupal_tweaks_msg2log_settings_default_regex_rules($type))));
  foreach ($msg_rules as $key => $msg_rule) {
    if (!empty($msg_rule) && preg_match(trim($msg_rule), $message) != FALSE) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Get list of RegEx rules for messages of specified type
 *
 * @param string $type (optional)
 *   The type of the message. One of the following values are possible:
 *   - 'status'
 *   - 'warning'
 *   - 'error'
 *
 * @return
 *   Return default RegEx rules for messages
 */
function drupal_tweaks_msg2log_settings_default_regex_rules($type) {
  switch ($type) {
    case 'error':
      $msgs = array(
        '@Fatal error:@',
        '@ on line @',
        '@MySQL@',
      );
      break;
    case 'warning':
      $msgs = array(
        '@warning:@',
        '@Fatal error:@',
        '@ on line @',
        '@MySQL@',
      );
      break;
    case 'status':
      $msgs = array(
      );
      break;
  }
  return $msgs;
}

