<?php

/**
 * 
 * This module allows you to define a custom memory limit for individual paths.
 * 
 * Developed by ProjectRicochet (www.projectricochet.com)
 *
 * If the system isn't setting the memory early enough, you may need to lower the
 * weight of this module in the system table to < -10
 * 
 */

function path_memory_boot() {

  if ($mem_limit = path_memory_get_limit()) {
    ini_set('memory_limit', $mem_limit);
  }
}


/**
* Implementation of hook_perm().
*/
function path_memory_permission() {

  return array(
    'path_memory configure' => array(
      'title' => t('Configure Path Memory'),
      'description' => t('Setting to give access to Path Memory config.'),
    ),
  );
}


/**
* Menu for this module
* @return array An array with the various menus for this module
*/
function path_memory_menu() {
  $items = array();

  // For the default local task, we need very little configuration, as the
  // callback and other conditions are handled by the parent callback.
  $items['admin/config/system/path-memory'] = array(
    'type' => MENU_NORMAL_ITEM,
    'title' => 'Path Memory Config',
    'description' => 'Configure memory requirements for different paths.',
    'page callback' => 'path_memory_settings',
    'access arguments' => array('path_memory configure'),
    'weight' => 2,
  );

  $items['admin/config/system/path-memory/add'] = array(
    'type' => MENU_CALLBACK,
    'title' => 'Add Path Memory',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('path_memory_add_form'),
    'access arguments' => array('path_memory configure')
  );

  $items['admin/config/system/path-memory/edit/%'] = array(
    'type' => MENU_CALLBACK,
    'title' => 'Edit Path Memory',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('path_memory_add_form', 5),
    'access arguments' => array('path_memory configure')
  );

  $items['admin/config/system/path-memory/delete/%'] = array(
    'type' => MENU_CALLBACK,
    'page callback' => 'path_memory_delete',
    'page arguments' => array(5,6),
    'access arguments' => array('path_memory configure')
  );

  return $items;
}

function path_memory_get_limit($path = NULL) {

  $path = $_GET['q'];

  $result = db_select('path_memory', 'p')
    ->fields('p')
    ->execute();

  while ( $row = $result->fetchAssoc() ) {

    $wildcard = stripos($row['path'], '*');

    if ( $wildcard ) {
      if ( substr($row['path'], 0, $wildcard) == substr($path, 0, $wildcard) ) {
        return $row['mem_limit'];
      }
    }
    else {
      if ( $row['path'] == $path) {
        return $row['mem_limit'];
      }
    }
  }
  
  return FALSE;
}


function path_memory_delete($id, $token) {
  
  if ( $token == drupal_get_token($id) ) {

    $result = db_delete('path_memory')
      ->condition('id', $id)
      ->execute(); 
      
    drupal_set_message(t('Path successfully removed.'));
  }
  else {
    drupal_set_message(t('Authentication error and possible xss attack! Path not deleted.'), 'error');
  }

  drupal_goto('admin/config/system/path-memory');
}

function path_memory_settings() {

  $result = db_select('path_memory', 'p')
    ->fields('p')
    ->execute();

  $header = array(t('Path'), t('Memory Limit'), '');

  $rows=array();

  while ( $row = $result->fetchAssoc() ) {

    $rows[] = array(
      check_plain($row['path']),
      check_plain($row['mem_limit']),
      l(t('Edit'), 'admin/config/system/path-memory/edit/' . $row['id']) . ' / ' . l(t('Delete'), 'admin/config/system/path-memory/delete/' . $row['id'] 
      . '/' . drupal_get_token($row['id']), array('attributes' => array('onclick' => 'return confirm(' . t('Are you sure you want to delete this path entry?') . ')')))
    );
  }
  
  $output = '';
  
  if ( count($rows) ) {
    $output = theme('table', array('header' => $header, 'rows' => $rows));
  }
  else{
    $output = t('No Path Memory entries yet added...') . '<br /><br />';
  }
  
  return $output . l(t('Add New Path'), 'admin/config/system/path-memory/add');
}


function path_memory_add_form($form, &$form_state, $id=NULL) {

  $form['settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Path Settings'),
    '#collapsible' => FALSE,
    '#collapsed' => FALSE,
  );

  if ( $id || $id===0 ) {

  $form['settings']['id'] = array(
    '#type' => 'hidden',
    '#default_value' => $id
  );

  $defaults = db_select('path_memory', 'p')
    ->fields('p')
    ->execute()
    ->fetchAssoc();
  }

  $form['settings']['path'] = array(
    '#type' => 'textfield',
    '#title' => t('Path'),
    '#description' => 'A single wild cards * is accepted.',
    '#default_value' => isset($defaults['path']) ? $defaults['path']:"",
    '#size' => 50,
    '#maxlength' => 128,
    '#required' => TRUE,
  );

  $form['settings']['mem_limit'] = array(
    '#type' => 'textfield',
    '#title' => t('Memory Limit'),
    '#description' => t('Please make sure to add M for Megabytes, G for Gigabytes, etc for each memory limit.'),
    '#default_value' => isset($defaults['mem_limit']) ? $defaults['mem_limit']:"",
    '#required' => TRUE,
    '#size' => 10,
    '#maxlength' => 10,
  );

  // Submit button:
  $form['settings']['settings_submit'] = array(
    '#prefix' => '<br>',
    '#type' => 'submit',
    '#value' => t('Save'),
  );

  return $form;
}


function path_memory_add_form_validate($form, &$form_state) {

  if ( isset($form_state['values']['mem_limit']) ) {

    $form_state['values']['mem_limit'] = strtoupper($form_state['values']['mem_limit']);

    $last_char = substr($form_state['values']['mem_limit'], -1);   

    if ( !ctype_alpha($last_char) ) {
      form_set_error('mem_limit', t('You need to have a letter at the end of your memory limit (M, G, etc...)'));
    }
  }
}

function path_memory_add_form_submit($form, &$form_state) {

  if ( !isset($form_state['values']['id']) ) {

    $result = db_insert('path_memory')
      ->fields(array(
        'path' => $form_state['values']['path'],
        'mem_limit' => $form_state['values']['mem_limit'],
      ))
      ->execute();

  }
  else {

    $result = db_update('path_memory')
      ->fields(array(
        'path' => $form_state['values']['path'],
        'mem_limit' => $form_state['values']['mem_limit'],
      ))
      ->condition('id', $form_state['values']['id'])
      ->execute();
  }

  drupal_goto('admin/config/system/path-memory');
}