<?php
/**
 * @file
 * The jQuerymenu module parses hierarchical link arrays and renders them as click and expand menu blocks.
 */

/**
 * Implements of hook_init().
 */
function jquerymenu_init() {
  drupal_add_css(drupal_get_path('module', 'jquerymenu') . '/jquerymenu.css');

  if (!variable_get('jquerymenu_animate', 0)) {
    drupal_add_js(drupal_get_path('module', 'jquerymenu') . '/jquerymenu.js');
  }
  else {
    drupal_add_js(drupal_get_path('module', 'jquerymenu') . '/jquerymenu_no_animation.js');
  }
}


/**
 * Implements hook_permission
 */
function jquerymenu_permission() {
  return array(
    'administer jquerymenu' => array(
      'title' => t('Administer jQuery Menu'), 
      'description' => t('Perform administration tasks for my jQuery Menu.'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function jquerymenu_menu() {
  $items = array();

  // Create the admin form link.
  $items['admin/config/user-interface/jquerymenu/settings'] = array(
    'title' => 'jQuery Menu Settings',
    'description' => 'Set the options for the jQuery Menu Module',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('jquerymenu_admin_settings'),    
    'access arguments' => array('administer jquerymenu'),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'jquerymenu.admin.inc',
  );

  return $items;
}

/**
 * Implements hook_block_info().
 */
function jquerymenu_block_info() {
  // create array to hold blocks
  $blocks = array();

  // get a list of enabled jquerymenus
  $result = db_query("SELECT mid, menu_name FROM {jquerymenus}");
  $enabledmenus = array();
  foreach ($result as $enabled) {
    $enabledmenus[$enabled->mid] = $enabled->menu_name;
  }

  // loop through each jquerymenu
  foreach ($enabledmenus as $mid => $name) {
    // get the title of the menu
    //$title = db_query("SELECT title FROM {menu_custom} WHERE menu_name = :name", array(':name'=> $name))->fetchCol('title');
    $title = db_query("SELECT title FROM {menu_custom} WHERE menu_name = :name", array(':name' => $name))->fetchField();

    // If menu has no title, delete it.
    if (empty($title)) {
      db_delete('jquerymenus')
        ->condition('menu_name', $name)
        ->execute();

      db_delete('block')
        ->condition('module', 'jquerymenu')
        ->condition('delta', $mid)
        ->execute();
    }

    // Create a block.
    $blocks[$mid] = array(
      'info' => t($title . ' - jQuery Menu'),
      'status' => TRUE,
      'region' => 'sidebar_first',
      'weight' => 0,
      'visibility' => 'BLOCK_VISIBILITY_NOTLISTED',
      'cache' => 'DRUPAL_NO_CACHE'
    );
  }

  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function jquerymenu_block_view($delta = '') {
  global $user;

  $block = array();
  // List of enabled jquerymenus.
  $result = db_query("SELECT mid, menu_name FROM {jquerymenus}");
  $enabledmenus = array();

  foreach ($result as $enabled) {
    $enabledmenus[$enabled->mid] = $enabled->menu_name;
  }

  // create variable to hold current active menu
  $old_activemenu = menu_get_active_menu_names();

  // loop through all jquerymenus
  foreach ($enabledmenus as $mid => $menuname) {

    // gets the data structure representing a named menu tree
    $menutree = menu_tree_all_data($menuname);
    if (!empty($menutree)) {
      if ($delta == $mid) {
        if ($menuname == 'navigation' && !empty($user->uid)) {
          // D6 to D7 conversion: ?? use the associative array or not?
          $title = theme('username', (array)$user);
          //$title = theme('username', array('user' => $user));
        }
        else {
          $title = db_query("SELECT title FROM {menu_custom} WHERE menu_name = :name", array(':name' => $menuname))->fetchField();          
        }
        menu_set_active_menu_names($menuname);
        // get the path to root menu root
        $trail = jquerymenu_trail_creator();
        $block['subject'] = t($title);
        // create the block content
        $block['content'] = theme('jquerymenu_menu', array('tree' => $menutree, 'trail' => $trail));
      }
    }
  }
  // return active menu to what it was originally
  menu_set_active_menu_names($old_activemenu);

  return $block;
}

function jquerymenu_trail_creator() {
  $activetrail = menu_get_active_trail();
  $url_array = array();
  foreach ($activetrail as $trail) {
    // Create an array of only the paths for easy evaluation.
    if (isset($trail['href'])) {
      $url_array[] = $trail['href'];
    }
  }
  return $url_array;
}

function recursive_link_creator($items = array(), $trail, $parentid = '') {
  static $menucount = 0;

  $count = 0;
  $output = '';
  $nextlevel = '';

  if (!isset($edit_access)) {
    $edit_access = 'administer menu'; //http://drupal.org/node/911726
  }

  if ($parentid == '') {
    $menucount++;
    $parentid = $menucount;
  }

  $url_array = $trail;
  
  global $active;
  /*foreach ($items as $item) {
    if(in_array($item['link']['href'], $url_array)) {
        for($i=1; $i<10; $i++) {
            if($item['link']['p'.$i] != 0) { //if item is active tail, get a list of it's parents.
                $active  .= ' ' . $item['link']['p' . $i];
            }
          }
      }
  }*/
	
  $i = 0;
  if (!empty($items)) {
    foreach ($items as $item) {
      $count++;
      $id = $parentid . '-' . $count;
      $classes = array();
      $state = 'closed';
      // If there are submenu items we assign the parent a class.
      if (!empty($item['link']['has_children'])) {
        $nextlevel = '';
        $nextlevel = recursive_link_creator($item['below'], $url_array, $id);
        if (!empty($nextlevel)) {
          $classes[] = 'parent';
        }
      }

      // If the menu item is expanded or in the active trail and if has children add the "open" class.
			if (
			  (!empty($item['link']['mlid']) && in_array($item['link']['mlid'], $url_array)) || 
				($item['link']['expanded'] != 1) || 
				((in_array($item['link']['href'], $url_array) || ($_GET['q'] == $item['link']['href'])) && !empty($item['link']['has_children']) && !empty($nextlevel))
				) {
			  $classes[] = 'open';
        $state = 'open';
      }
      elseif (!empty($item['below']) && !empty($nextlevel)) {
        $classes[] = 'closed';
      }

      if (in_array($item['link']['href'], $url_array)) {
        $classes[] = 'active-trail';
      }

      if ($_GET['q'] == $item['link']['href'] || ($item['link']['href'] == '<front>' && $_GET['q'] == variable_get('site_frontpage', 'node'))) {
        $classes[] = 'active';
      }

      if ($count == 1) {
        $classes[] = 'first';
      }
      if ($count == count($items)) {
        $classes[] = 'last';
      }

      $options = array();
      if (isset($item['link']['options'])) {
        $options = $item['link']['options'];
      }

      if (variable_get('jquerymenu_edit_link', 1) == 1) {
        if (empty($item['link']['edit_path'] )) {
          if (!empty($item['link']['mlid'])) {
            $edit_path = 'admin/build/menu/item/' . $item['link']['mlid'] . '/edit';
          }
        }
        else {
          $edit_path = $item['link']['edit_path'];
        }
      }
      else {
        $edit_path = '';
      }

      if (empty($item['link']['edit_access'])) {
        $edit_access = 'administer menu';
      }
      else {
        $edit_access = $item['link']['edit_access'];
      }

      if (empty($item['link']['edit_text'])) {
        $edit_text = t('Edit this link');
      }
      else {
        $edit_text = $item['link']['edit_text'];
      }

      if (!empty($item['link']['to_arg_functions'])) {
        $toarg_array = array();
        $patharray = explode('/', $item['link']['href']);
        foreach ($patharray as $chunk) {
          if ($chunk != '%') {
            $toarg_array[] = $chunk;
          }
          else {
            $function = $item['link']['to_arg_functions'];
            $function = explode('"', $function);
            $function = $function[1];
            $toarg_array[] = $function('%');
          }
        }
        $path = implode('/', $toarg_array);
      }
      else {
        $path = $item['link']['href'];
      }

      if ($item['link']['hidden'] == 1 && !empty($item['link']['has_children'])) {
        $output .= recursive_link_creator($item['below'], $url_array, $id);
      }

      if ($item['link']['hidden'] != 1 && $item['link']['hidden'] != -1) {
        $output .= theme('jquerymenu_listitem', array(
          'item' => $item,
          'title' => $item['link']['title'],
          'path' => $path,
          'options' => $options,
          'state' => $state,
          'classes' => $classes,
          'has_children' => $item['link']['has_children'],
          'edit_path' => $edit_path,
          'edit_text' => $edit_text,
          'edit_access' => $edit_access,
          'nextlevel' => $nextlevel,
        ));
      }
    }
  }
  return $output;
}

/**
 * Implements hook_theme().
 */
function jquerymenu_theme() {
  return array(
    'jquerymenu_menu' => array(
      'variables' => array(
        'tree' => NULL,
        'trail' => NULL,
      ),
    ),

    'jquerymenu_listitem' => array(
      'variables' => array(
        'item' => NULL,

        'title' => NULL,
        'path' => NULL,
        'options' => NULL,
        'state' => NULL,
        'classes' => NULL,
        'has_children' => NULL,
        'edit_path' => NULL,
        'edit_text' => NULL,
        'edit_access' => NULL,
        'nextlevel' => NULL,
      ),
    ),
  
    'jquerymenu_links' => array(
      'variables' => array(
        'title' => NULL,
        'path' => NULL,
        'options' => NULL,
        'state' => NULL,
        'classes' => NULL,
        'has_children' => NULL,
        'edit_path' => NULL,
        'edit_text' => NULL,
        'edit_access' => NULL,
      ),
    ),
  );
}

function theme_jquerymenu_menu($variables) {
  $tree = $variables['tree'];
  $trail = $variables['trail'];
  $menu_output = recursive_link_creator($tree, $trail);
  if (!empty($menu_output)) {
    // We create the shell to hold the menu outside the recursive function.
    // Add a div that only shows up for that pesky IE so that we can style it into obedience.
    $output  = '<!--[if IE]><div class="ie"><![endif]-->';
    $output .= '<ul class="menu jquerymenu">';
    $output .= $menu_output;
    $output .= '</ul>';
    $output .= '<!--[if IE]></div><![endif]-->';
    return $output;
  }
}

/**
 * Render a list item containing one or more links.
 */
function theme_jquerymenu_listitem($variables) {
  $item         = $variables['item'];
  $title        = $variables['title'];
  $path         = $variables['path'];
  $options      = $variables['options'];
  $state        = $variables['state'];
  $classes      = $variables['classes'];
  $nextlevel    = $variables['nextlevel'];
  $has_children = $variables["has_children"];
  $edit_path    = $variables["edit_path"];
  $edit_text    = $variables["edit_text"];
  $edit_access  = $variables["edit_access"];
  
  if (!isset($output)) {
    $output = '';
  }

  $output .= '<li ' . (variable_get('jquerymenu_insert_list_item_id', 0) ? 'id="jquerymenu-' . $id . '" ' : '') . (empty($classes) ? '>' : ' class="' . implode(' ', $classes) . '">');

  $output .= theme('jquerymenu_links', array(
    'title' => $item['link']['title'],
    'path' => $path,
    'options' => $options,
    'state' => $state,
    'classes' => $classes,
    'has_children' => $item['link']['has_children'],
    'edit_path' => $edit_path,
    'edit_text' => $edit_text,
    'edit_access' => $edit_access,
  ));

  if (!empty($item['link']['has_children'])) {
    if (!empty($nextlevel)) {
      $output .= '<ul>';
      // If the link has children call the function on itself.
      $output .= $nextlevel;
      $output .= '</ul>';
    }
  }

  $output .= '</li>';
  return $output;
}

/**
 * Render a single link, possibly with open/close link and/or edit button.
 */
function theme_jquerymenu_links($variables) {
  // create values from the parameter array
  $title        = $variables["title"];
  $path         = $variables["path"];
  $options      = $variables["options"];
  $state        = $variables["state"];
  $classes      = $variables["classes"];
  $has_children = $variables["has_children"];
  $edit_path    = $variables["edit_path"];
  $edit_text    = $variables["edit_text"];
  $edit_access  = $variables["edit_access"];

  $output = '';
  // This is the span that becomes the little plus and minus symbol.
  $plus = '<span' . (empty($classes) ? '>' : ' class="' . implode(' ', $classes) . '">') . '</span>';
  if ($edit_path != NULL && user_access($edit_access)) {
    $edit_box = jquerymenu_edit_box($edit_path, $edit_text);
    if ($has_children != 0) {
      $output .= $edit_box . $plus . l($title, $path, $options);
    }
    else {
      $output .= $edit_box . l($title, $path, $options);
    }
  }
  else {
    if ($has_children != 0) {
      $output .= $plus . l($title, $path, $options);
    }
    else {
      $output .= l($title, $path, $options);
    }
  }
  return $output;
}

/**
 * Render edit link for a menu item.
 */
function jquerymenu_edit_box($edit_path, $edit_title = NULL) {
  $options['html'] = TRUE;
  if (!empty($edit_title)) {
    $options['attributes']['title'] = $edit_title;
  }
  else {
    $options['attributes']['title'] = t('Edit');
  }
  $path = base_path() . drupal_get_path('module', 'jquerymenu');
  $editimage = '<img src="' . $path . '/images/edit.png" alt="edit menu" />';
  return '<span class="jquerymenu_link_edit">' . l($editimage, $edit_path, $options) . '</span>';
}

