<?php

/**
 * @file classes/navigationMenu/NavigationMenuItemAssignmentDAO.inc.php
 *
 * Copyright (c) 2014-2021 Simon Fraser University
 * Copyright (c) 2000-2021 John Willinsky
 * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
 *
 * @class NavigationMenuItemAssignment
 * @ingroup navigationMenuItem
 * @see NavigationMenuItem
 *
 * @brief Operations for retrieving and modifying NavigationMenuItemAssignment
 *  objects
 */

import('lib.pkp.classes.navigationMenu.NavigationMenu');
import('lib.pkp.classes.navigationMenu.NavigationMenuItem');
import('lib.pkp.classes.navigationMenu.NavigationMenuItemAssignment');

class NavigationMenuItemAssignmentDAO extends DAO {

	/**
	 * Retrieve a navigation menu item assignment by ID.
	 * @param $navigationMenuItemAssignmentId int
	 * @return NavigationMenuItemAssignment?
	 */
	function getById($navigationMenuItemAssignmentId) {
		$result = $this->retrieve(
			'SELECT	* FROM navigation_menu_item_assignments WHERE navigation_menu_item_assignment_id = ?',
			[(int) $navigationMenuItemAssignmentId]
		);
		$row = (array) $result->current();
		return $row?$this->_fromRow($row):null;
	}

	/**
	 * Get a new data object.
	 * @return NavigationMenuItemAssignment
	 */
	public function newDataObject() {
		return new NavigationMenuItemAssignment();
	}

	/**
	 * Retrieve items by menu id
	 * @param $menuId int
	 * @return DAOResultFactory
	 */
	public function getByMenuId($menuId) {
		$result = $this->retrieve(
			'SELECT nmi.*,nmh.navigation_menu_id,nmh.parent_id,nmh.seq, nmh.navigation_menu_item_assignment_id
				FROM navigation_menu_item_assignments as nmh
				LEFT JOIN navigation_menu_items as nmi ON (nmh.navigation_menu_item_id = nmi.navigation_menu_item_id)
				WHERE nmh.navigation_menu_id = ?
				ORDER BY nmh.seq',
			[(int) $menuId]
		);
		return new DAOResultFactory($result, $this, '_fromRow');
	}

	/**
	 * Retrieve items by menu item id
	 * @param $menuItemId int
	 * @return DAOResultFactory
	 */
	public function getByMenuItemId($menuItemId) {
		$result = $this->retrieve(
			'SELECT nmi.*, nmh.navigation_menu_id, nmh.parent_id, nmh.seq, nmh.navigation_menu_item_assignment_id
				FROM navigation_menu_item_assignments as nmh
				LEFT JOIN navigation_menu_items as nmi ON (nmh.navigation_menu_item_id = nmi.navigation_menu_item_id)
				WHERE nmh.navigation_menu_item_id = ?
				ORDER BY nmh.seq',
			[(int) $menuItemId]
		);
		return new DAOResultFactory($result, $this, '_fromRow');
	}

	/**
	 * Retrieve items by navigationMenuItemId menu item id and ParentId
	 * @param $navigationMenuItemId int
	 * @param $menuId int
	 * @param $parentId int
	 * @return NavigationMenuItemAssignment
	 */
	public function getByNMIIdAndMenuIdAndParentId($navigationMenuItemId, $menuId, $parentId = null) {
		$params = [(int) $menuId, (int) $navigationMenuItemId];
		if ($parentId) $params[] = (int) $parentId;
		$result = $this->retrieve(
			'SELECT nmh.*
				FROM navigation_menu_item_assignments as nmh
				WHERE nmh.navigation_menu_id = ?
				AND nmh.navigation_menu_item_id = ?' .
				($parentId?' AND nmh.parent_id = ?':''),
			$params
		);
		$row = (array) $result->current();
		return $row?$this->_fromRow($row):null;
	}

	/**
	 * Retrieve items by navigationMenu id and ParentId
	 * @param $menuId int
	 * @param $parentId int 0 if we want to return NMIAssignments with no parents
	 */
	public function getByMenuIdAndParentId($menuId, $parentId) {
		$result = $this->retrieve(
			'SELECT nmh.*
				FROM navigation_menu_item_assignments as nmh
				WHERE nmh.navigation_menu_id = ?
				AND nmh.parent_id = ?',
			[(int) $menuId, (int) $parentId]
		);
		return new DAOResultFactory($result, $this, '_fromRow');
	}

	/**
	 * Internal function to return a NavigationMenuItemAssignment object from a
	 * row.
	 * @param $row array
	 * @return NavigationMenuItemAssignment
	 */
	public function _fromRow($row) {
		$assignment = $this->newDataObject();
		$assignment->setId($row['navigation_menu_item_assignment_id']);
		$assignment->setMenuId($row['navigation_menu_id']);
		$assignment->setMenuItemId($row['navigation_menu_item_id']);
		$assignment->setParentId($row['parent_id']);
		$assignment->setSequence($row['seq']);

		$this->getDataObjectSettings('navigation_menu_item_assignment_settings', 'navigation_menu_item_assignment_id', $row['navigation_menu_item_assignment_id'], $assignment);

		return $assignment;
	}

	/**
	 * Update an existing NavigationMenuItemAssignment.
	 * @param $navigationMenuItemAssignment NavigationMenuItemAssignment
	 * @return boolean
	 */
	function updateObject($navigationMenuItemAssignment) {
		$returner = $this->update(
			'UPDATE navigation_menu_item_assignments
			SET
				navigation_menu_id = ?,
				navigation_menu_item_id = ?,
				parent_id = ?,
				seq = ?,
			WHERE navigation_menu_item_assignment_id = ?',
			[
				(int) $navigationMenuItemAssignment->getMenuId(),
				(int) $navigationMenuItemAssignment->getMenuItemId(),
				(int) $navigationMenuItemAssignment->getParentId(),
				(int) $navigationMenuItemAssignment->getSequence(),
				(int) $navigationMenuItemAssignment->getId(),
			]
		);
		$this->updateLocaleFields($navigationMenuItemAssignment);
		$this->unCacheRelatedNavigationMenus($navigationMenuItemAssignment->getId());
		return (boolean) $returner;
	}

	/**
	 * Insert a new NavigationMenuItemAssignment.
	 * @param $assignment NavigationMenuItemAssignment
	 * @return int
	 */
	public function insertObject($assignment) {
		$this->update(
			'INSERT INTO navigation_menu_item_assignments
			(navigation_menu_id, navigation_menu_item_id, parent_id, seq)
			VALUES
			(?, ?, ?, ?)',
			[
				(int) $assignment->getMenuId(),
				(int) $assignment->getMenuItemId(),
				(int) $assignment->getParentId(),
				(int) $assignment->getSequence(),
			]
		);
		$assignment->setId($this->getInsertId());

		// Add default title (of the navigationMenuItem)
		$navigationMenuItemDao = DAORegistry::getDAO('NavigationMenuItemDAO'); /* @var $navigationMenuItemDao NavigationMenuItemDAO */
		$navigationMenuItem = $navigationMenuItemDao->getById($assignment->getMenuItemId());

		$assignment->setTitle($navigationMenuItem->getTitle(null), null);

		$this->updateLocaleFields($assignment);

		$this->unCacheRelatedNavigationMenus($assignment->getId());

		return $assignment->getId();
	}

	/**
	 * Delete all assignments by NavigationMenu ID
	 * @param $menuId NavigationMenu id
	 * @return boolean
	 */
	function deleteByMenuId($menuId) {
		$navigationMenuItemAssignments = $this->getByMenuId($menuId);
		while ($navigationMenuItemAssignment = $navigationMenuItemAssignments->next()) {
			$this->deleteObject($navigationMenuItemAssignment);
		}

		return true;
	}

	/**
	 * Delete all assignments by NavigationMenuItem ID
	 * @param $menuItemId NavigationMenuItem id
	 * @return boolean
	 */
	function deleteByMenuItemId($menuItemId) {
		$navigationMenuItemAssignments = $this->getByMenuItemId($menuItemId);
		while ($navigationMenuItemAssignment = $navigationMenuItemAssignments->next()) {
			$this->deleteObject($navigationMenuItemAssignment);
		}

		return true;
	}

	/**
	 * Delete a NavigationMenuItemAssignment.
	 * @param $navigationMenuItemAssignment NavigationMenuItemAssignment
	 * @return boolean
	 */
	function deleteObject($navigationMenuItemAssignment) {
		return $this->deleteById($navigationMenuItemAssignment->getId());
	}

	/**
	 * Delete a NavigationMenuItemAssignment by NavigationMenuItemAssignment ID.
	 * @param $navigationMenuItemAssignmentId int
	 * @return boolean
	 */
	function deleteById($navigationMenuItemAssignmentId) {
		$this->unCacheRelatedNavigationMenus($navigationMenuItemAssignmentId);

		$this->update('DELETE FROM navigation_menu_item_assignment_settings WHERE navigation_menu_item_assignment_id = ?', [(int) $navigationMenuItemAssignmentId]);
		$this->update('DELETE FROM navigation_menu_item_assignments WHERE navigation_menu_item_assignment_id = ?', [(int) $navigationMenuItemAssignmentId]);
	}

	/**
	 * Get the list of localized field names for this table
	 * @return array
	 */
	function getLocaleFieldNames() {
		return ['title'];
	}

	/**
	 * Get the ID of the last inserted navigation menu item assignment.
	 * @return int
	 */
	function getInsertId() {
		return $this->_getInsertId('navigation_menu_item_assignments', 'navigation_menu_item_assignment_id');
	}

	/**
	 * Update the settings for this object
	 * @param $navigationMenuItemAssignment object
	 */
	function updateLocaleFields($navigationMenuItemAssignment) {
		$this->updateDataObjectSettings('navigation_menu_item_assignment_settings', $navigationMenuItemAssignment, [
			'navigation_menu_item_assignment_id' => $navigationMenuItemAssignment->getId()
		]);
	}

	/**
	 * Uncache the related NMs to the NMIA with $id
	 * @param mixed $id
	 */
	function unCacheRelatedNavigationMenus($id) {
		if ($navigationMenuItemAssignment = $this->getById($id)) {
			$navigationMenuDao = \DAORegistry::getDAO('NavigationMenuDAO');
			$cache = $navigationMenuDao->getCache($navigationMenuItemAssignment->getMenuId());
			if ($cache) $cache->flush();
		}
	}
}

