<?php

/**
 * Implements hook_permission()
 */
function me_node_creation_permission() {
  return array(
    'see menu_editor placeholder pages' => array(
      'title' => t('See menu_editor placeholder pages'),
    ),
  );
}

/**
 * Implements hook_menu()
 */
function me_node_creation_menu() {
  $items = array();
  /* @see node_type_load() */
  /* @see menu_editor_menu_link_load() */
  $items['node/add/%node_type/mlid/%menu_editor_menu_link'] = array(
    'load arguments' => array(2, 4),
    'title' => 'Create a node',
    /* @see me_node_creation_create_node() */
    'page callback' => 'me_node_creation_create_node',
    'page arguments' => array(2, 4),
    'file' => 'me_node_creation.create.inc',
    /* @see me_node_creation_create_node_access() */
    'access callback' => 'me_node_creation_create_node_access',
    'access arguments' => array(2),
  );
  /* @see menu_editor_menu_link_load() */
  $items['mlid/%menu_editor_menu_link/under-construction'] = array(
    'title' => 'Under Construction',
    /* @see menu_editor_placeholder_title() */
    'title callback' => 'menu_editor_placeholder_title',
    'title arguments' => array(1),
    /* @see menu_editor_placeholder_page() */
    'page callback' => 'menu_editor_placeholder_page',
    'page arguments' => array(1),
    'file' => 'me_node_creation.placeholder.inc',
    'access arguments' => array('see menu_editor placeholder pages'),
    'weight' => 0,
  );
  return $items;
}

/**
 * Implements hook_form_alter()
 *
 * @param array $form
 * @param array $form_state
 * @param string $form_id
 */
function me_node_creation_form_alter(array &$form, array &$form_state, $form_id) {
  if (empty($form['#node_edit_form']) || empty($form['#node'])) {
    return;
  }
  $node = $form['#node'];
  if (empty($node->me_node_creation_menu_item)) {
    return;
  }
  module_load_include('create.inc', 'me_node_creation');
  form_load_include($form_state, 'inc', 'node', 'node.pages');
  _me_node_creation_form_alter($form, $node);
}

/**
 * Implements hook_node_insert()
 *
 * @param object $node
 */
function me_node_creation_node_insert($node) {
  $menu_item = @$node->me_node_creation_menu_item;
  if (!$menu_item) {
    return;
  }
  $mlid = $menu_item['mlid'];
  $nid = $node->nid;
  switch ($menu_item['link_path']) {
    case "node/add/$node->type/mlid/$mlid":
    case "mlid/$mlid/under-construction":
      $menu_item['link_path'] = "node/$nid";
      $menu_item['router_path'] = "node/%";
      $menu_item['options'] = array();
      menu_link_save($menu_item);
  }
}

/**
 * Implements hook_crumbs_plugins()
 *
 * @param crumbs_InjectedAPI_hookCrumbsPlugins $api
 *
 * @throws \Exception
 */
function me_node_creation_crumbs_plugins($api) {
  $api->monoPlugin();
}


// Wildcard loaders
// -----------------------------------------------------------------------------

/**
 * Wildcard loader for %menu_editor_menu_link
 * This is similar to menu_link_load(), but we do some loop prevention.
 *
 * TODO: Test if the by-reference does not explode in some edge cases.
 *
 * @param int $mlid
 *
 * @return bool
 */
function menu_editor_menu_link_load($mlid) {
  static $_cache = array();
  if (is_numeric($mlid) && $mlid) {
    if (isset($_cache[$mlid])) {
      return $_cache[$mlid];
    }
    $query = db_select('menu_links', 'ml');
    $query->leftJoin('menu_router', 'm', 'm.path = ml.router_path');
    $query->fields('ml');
    // Weight should be taken from {menu_links}, not {menu_router}.
    $query->addField('ml', 'weight', 'link_weight');
    $query->fields('m');
    $query->condition('ml.mlid', $mlid);
    /** @noinspection NullPointerExceptionInspection */
    if ($item = $query->execute()->fetchAssoc()) {
      $_cache[$mlid] =& $item;
      $item['weight'] = $item['link_weight'];
      // The data being unserialized here is not coming from user input.
      /** @noinspection UnserializeExploitsInspection */
      $item['load_functions'] = unserialize($item['load_functions']);
      _menu_link_translate($item);
      return $item;
    }
  }
  return FALSE;
}


// Title callbacks
// -----------------------------------------------------------------------------

/**
 * Title callback for mlid/%menu_link/under-construction
 *
 * @param array $item
 *   The menu link, as returned by menu_link_load()
 * @return string
 *   The title, to be used in tabs, breadcrumbs and menus
 */
function menu_editor_placeholder_title($item) {
  // _menu_link_translate($item);
  return $item['link_title'];
}

/**
 * Title for menu links or tabs.
 * The page title can be different!
 *
 * @param string $type_arg
 * @param array|mixed $item
 *
 * @return string
 *
 * @todo This is currently not in use anywhere, and not useful as-is.
 */
function me_node_creation_title($type_arg, $item) {
  // @todo This is a stupid way to get a node type label.
  foreach (node_type_get_types() as $type_name => $type_object) {
    if ($type_name === $type_arg) {
      // @todo This should use t() with @placeholder.
      return "New $type_object->name";
    }
  }
  return t('Create node of unknown type');
}


// Access callbacks
// -----------------------------------------------------------------------------

/**
 * Access callback for node/add/%node_type/mlid/%menu_editor_mlid
 *
 * @param object|mixed $type
 *   A node type object, as returned from @see node_type_load()
 *
 * @return bool
 */
function me_node_creation_create_node_access($type) {
  if (!is_object($type)) {
    // One should assume that this case never happens..
    return FALSE;
  }
  return node_access('create', $type->type);
}


// Utility
// -----------------------------------------------------------------------------

/**
 * @return string[]
 *   Array of placeholders
 */
function me_node_creation_menu_editor_placeholders() {
  $placeholders = array(
    '<new>' => 'mlid/@mlid/under-construction',
    '<new page>' => NULL
  );
  foreach (node_type_get_types() as $type_name => $type_info) {
    $placeholders["<new $type_name>"] = "node/add/$type_name/mlid/@mlid";
  }
  // we want that <new page> is first, if this content type exists.
  // if not, we remove this placeholder.
  if (!isset($placeholders['<new page>'])) {
    unset($placeholders['<new page>']);
  }
  return $placeholders;
}
