<?php
/**
 * Children pages plugin: Shows links to children pages in the page menu
 *
 * @license    BSD 2-Clause
 * @author     Antoine Le Gonidec <vv221.dokuwiki@dotslashplay.it>
 */

// must be run within Dokuwiki
if ( ! defined('DOKU_INC') ) {
	die();
}

use dokuwiki\plugin\childrenpages\MenuItem;

class action_plugin_childrenpages extends DokuWiki_Action_Plugin {
	/**
	 * Registers a callback function for a given event
	 *
	 * @param Doku_Event_Handler $controller
	 */
	public function register(Doku_Event_Handler $controller) : void {
		$controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addMenuItems');
	}

	/**
	 * Add new items to the page menu
	 *
	 * @param Doku_Event $event
	 */
	public function addMenuItems(Doku_Event $event) : void {
		// Check that this method has been called in the expected context
		if ( $event->name !== 'MENU_ITEMS_ASSEMBLY' ) {
			$message = "Children pages plugin error:";
			$message .= "addMenuItem method should only be called by \"MENU_ITEMS_ASSEMBLY\" event";
			$message .= ", but it has been called by \"$event->name\".";
			throw new Exception($message);
		}
		// Only add content to the page menu
		if ( $event->data['view'] !== 'page' ) {
			return;
		}
		// Check if all links should be shown, or if the one to the current page shoud be excluded
		$show_all_links = (bool) $this->getConf('show_link_to_current_page');
		// If the current page is included in a reserved namespace, add a link back to main page
		$children_types = $this->getConf('children_list');
		$top_namespace = $this->getTopLevelNamespace();
		$is_child_page = in_array($top_namespace, $children_types);
		if ( $show_all_links || $is_child_page ) {
			$main_label = $this->getLang('btn_main');
			$this->addMenuItem($event, '_main', $main_label, $top_namespace);
		}
		// Add menu items for each child page
		foreach ( $children_types as $child_type ) {
			if ( $show_all_links || $child_type !== $top_namespace ) {
				$child_label = $this->getLang("btn_$child_type");
				$this->addMenuItem($event, $child_type, $child_label, $is_child_page);
			}
		}
	}

	/**
	 * Add a new item to the page menu
	 *
	 * @param Doku_Event $event
	 * @param string     $type
	 * @param string     $name
	 * @param bool       $strip_namespace
	 */
	protected function addMenuItem(
		Doku_Event $event,
		string     $type,
		string     $name            = '',
		bool       $strip_namespace = false
	) {
		$event->data['items'][] = new MenuItem($type, $name, $strip_namespace);
	}

	/**
	 * Get the top level namespace for the current page
	 * Exclude namespace added by the "translate" plugin
	 */
	protected function getTopLevelNamespace() : ?string {
		global $INFO;
		global $plugin_controller;
		$language = null;
		// If one of the "translate" or "translation" plugins is activated, get the language code for the current page
		if ( ! $plugin_controller->isdisabled('translate') ) {
			$translate_plugin =& $plugin_controller->load('helper', 'translate');
			$language = $translate_plugin->getPageLanguage();
		} elseif ( ! $plugin_controller->isdisabled('translation') ) {
			$translation_plugin =& $plugin_controller->load('helper', 'translation');
			$language = $translation_plugin->getLangPart($INFO['id']);
		}
		// Skip top-level language namespace if one is in use
		if ( $language !== null && preg_match("/^$language:/", $INFO['id']) ) {
			return explode(':', $INFO['namespace'])[1];
		} else {
			return explode(':', $INFO['namespace'])[0];
		}
	}
}