<?php
// $Id$
/**
 * @file
 * Exclude Node Title
 *
 * @author Gabriel Ungureanu
 * gabriel.ungreanu@ag-prime.com
 */

/**
 * Implements hook_permission().
 */ 
function exclude_node_title_permission() {
  return array(
    'administer exclude node title' => array(
      'title' => t('Administer exclude node title'),
    ),
    'exclude any node title' => array(
      'title' => t('Exclude any node title'),
    ),
    'exclude own node title' => array(
      'title' => t('Exclude own node title'),
    ),
    'use exclude node title' => array(
      'title' => t('Use exclude node title')
    ),
  );
}

/**
 * Implements hook_menu().
 */
function exclude_node_title_menu() {
  $items = array();
  $items['admin/config/content/exclude_node_title'] = array(
    'title' => 'Exclude Node Title',
    'description' => 'Exclude Node Title from display',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('exclude_node_title_admin_settings'),
    'access arguments' => array('administer exclude node title'),
    'type' => MENU_LOCAL_TASK,
    'file' => 'exclude_node_title.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_preprocess_page().
 */
function exclude_node_title_preprocess_page(&$vars) {
  if (!user_access('use exclude node title')) {
    return;
  }
  if (arg(0) == 'node' && is_numeric(arg(1))) {
    switch (arg(2)) {
      case 'edit':
        $view_mode = 'nodeform';
        break;
      case 'delete':
        return; // delete pages show you all information in title, we should not remove it
      default:
        $view_mode = 'full';
        break;
    }
    if (_exclude_node_title(arg(1), $view_mode)) {
      $vars['title'] = '';
    }
  }
  elseif (arg(0) == 'search' && variable_get('exclude_node_title_search', 0)) {
    $vars['title'] = '';
  }
}

/**
 * Implements hook_node_view()
 */ 
function exclude_node_title_node_view($node, $view_mode) {
  if (user_access('use exclude node title')) {
    if (_exclude_node_title($node, $view_mode)) {
      $node->title = '';
    }
  }
}

/**
 * Implements hook_node_update()
 */
function exclude_node_title_node_update($node) {
  if (isset($node->exclude_node_title) && exclude_node_title_check_perm($node)) {
    exclude_node_title_set_flag($node, $node->exclude_node_title);
  }
}

/**
 * Implements hook_node_insert()
 */
function exclude_node_title_node_insert($node) {
  if (isset($node->exclude_node_title) && exclude_node_title_check_perm($node)) {
    exclude_node_title_set_flag($node, $node->exclude_node_title);
  }
}

/**
 * Implements hook_node_delete()
 */
function exclude_node_title_node_delete($node) {
  if (isset($node->exclude_node_title) && $node->exclude_node_title == 1 ) {
    exclude_node_title_set_flag($node, 0);
  }
}

/**
 * Check permission to change node title exclusion.
 */
function exclude_node_title_check_perm($node) {
  global $user;
  if (user_access('exclude any node title'))
    return TRUE;
  if (!user_access('exclude own node title'))
    return FALSE;
  return !strcmp($node->name, $user->name);
}

/**
 * Implements hook_form_alter().
 */
function exclude_node_title_form_alter(&$form, &$form_state, $form_id) {
  if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] . '_node_form' == $form_id) {
    // exclude for title
    if (user_access('use exclude node title')) {
      if (_exclude_node_title($form['#node'], 'nodeform')) {
        drupal_set_title('');
      }
    }
    // --------------
    // make sure user have permissions correct
    if (!exclude_node_title_check_perm($form['#node'])) {
      return FALSE;
    }
    
    // don't bother to add form element if the content type isn't configured
    // to be excluded by user...
    if (variable_get('exclude_node_title_content_type_value_' . $form['#node']->type) == 'user') {
      $weight = $form['title']['#weight'] + 0.1;
      $form['exclude_node_title'] = array(
        '#type' => 'checkbox',
        '#title' => t('Exclude title from display'),
        '#required' => FALSE,
        '#default_value' => (!empty($form['nid']['#value']) ? in_array($form['nid']['#value'], variable_get('exclude_node_title_nid_list', array())) : FALSE ),
        '#weight' => $weight,
      );
      if (module_exists('translation') && variable_get('exclude_node_title_translation_sync', TRUE) == TRUE && translation_supported_type($form['#node']->type) && !empty($form['nid']['#value'])) {
        // get tnid
        $tnid = db_select('node', 'n')
          ->fields('n', array('tnid'))
          ->condition('nid', $form['nid']['#value'])
          ->execute()
          ->fetchAssoc();
        if ($tnid['tnid'] != $form['nid']['#value']) {
          $form['exclude_node_title']['#description'] = t('Check !here if you don`t have title disabled in the source language of this node.', array('!here' => l(t('here'), 'node/' . $tnid['tnid'] . '/edit')));
        }
      }
    }
  }
}

/**
 * Set exclude_node_title flag for the given node.
 */
function exclude_node_title_set_flag($node, $value = 1) {
  $exclude_list = variable_get('exclude_node_title_nid_list', array());
  $is_excluded = array_search($node->nid, $exclude_list);
  if ($value == 1 && $is_excluded === FALSE) {
    $exclude_list[] = $node->nid;
    variable_set('exclude_node_title_nid_list', $exclude_list);
    return;
  }
  if ($value == 0 && $is_excluded !== FALSE) {
    unset($exclude_list[$is_excluded]);
    variable_set('exclude_node_title_nid_list', $exclude_list);
    return;
  }
}

/**
 * Implements hook_field_attach_delete_bundle().
 */
function exclude_node_title_field_attach_delete_bundle($entity_type, $bundle, $instances) {
  // when deleting a content type, we make sure and clean our variable :)
  if ($entity_type == 'node') {
    variable_del('exclude_node_title_content_type_value_' . $bundle);
    variable_del('exclude_node_title_content_type_modes_' . $bundle);
  }
}

/**
 * Tells if node should get hidden or not.
 * @param $param
 *   Can be a node object or integer value (nid)
 * @return
 *   Returns boolean TRUE if should be hidden, FALSE when not
 */
function _exclude_node_title($param, $view_mode = 'full') {
  
  // we accept only integer and object
  if (!is_object($param) && !is_numeric($param)) {
    return FALSE;
  }
  
  // if numeric, load the node with nid
  if (is_numeric($param)) {
    $node = node_load(intval($param));
    if (!is_object($node)) {
      return FALSE;
    }
  }
  elseif (is_object($param)) {
    $node = $param;
    unset($param); // memory cleanup
  }
  // Check that the node exists 
  if (!isset($node) || !isset($node->type)) return FALSE;
  $node_type = $node->type;
  $nid = isset($node->nid)?$node->nid:FALSE;
  unset($node); // memory cleanup
  
  // get exclude settings
  static $exclude_settings;
  if (!isset($exclude_settings)) {
    foreach (_node_types_build()->names as $key => $val) {
      $exclude_settings[$key] = array(
        'type'  => variable_get('exclude_node_title_content_type_value_' . $key, 'none'),
        'modes' => variable_get('exclude_node_title_content_type_modes_' . $key, array()),
      );
    }
  }
  switch ($exclude_settings[$node_type]['type']) {
    case 'all':
      return !empty($exclude_settings[$node_type]['modes'][$view_mode]);
    case 'user':
      // we look for the nid list
      $nid_exclude_list = variable_get('exclude_node_title_nid_list', array());
      $nid_list = array($nid => $nid);
      if (module_exists('translation') && variable_get('exclude_node_title_translation_sync', TRUE) == TRUE && translation_supported_type($node_type)) {
        // get tnid
        $tnid = db_select('node', 'n')
          ->fields('n', array('tnid'))
          ->condition('nid', $nid)
          ->execute()
          ->fetchAssoc();
        $tlist = translation_node_get_translations($tnid['tnid']);
        if (is_array($tlist)) {
          foreach ($tlist as $tlang => $tnode) {
            $nid_list[$tnode->nid] = $tnode->nid;
          }
        }
      }
      foreach ($nid_list as $item_nid) {
        if (in_array($item_nid, $nid_exclude_list)) {
          return !empty($exclude_settings[$node_type]['modes'][$view_mode]);
        }
      }
      return FALSE;
      
    case 'none':
    default:
      return FALSE;
      break;
  }
}
