<?php
/**
* @version	$Id: private_message_eh.php 16515 2017-01-20 14:12:04Z alex $
* @package	In-Bulletin
* @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license      GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/

	defined('FULL_PATH') or die('restricted access!');

	class PrivateMessageEventHandler extends kDBEventHandler {

		/**
		 * Allows to override standard permission mapping
		 *
		 * @return void
		 * @access protected
		 * @see kEventHandler::$permMapping
		 */
		protected function mapPermissions()
		{
			parent::mapPermissions();

			$permissions = Array (
				'OnItemBuild' => Array ('self' => true),
				'OnCreate' => Array ('self' => true),
				'OnDelete' => Array ('self' => true),
			);

			$this->permMapping = array_merge($this->permMapping, $permissions);
		}

		/**
		 * Applies folder & message owner filter to message list
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 * @see kDBEventHandler::OnListBuild()
		 */
		protected function SetCustomQuery(kEvent $event)
		{
			parent::SetCustomQuery($event);

			$folder_id = $this->Application->GetVar('folder_id');

			if ( $folder_id === false ) {
				$folder_id = PM_FOLDER_INBOX;
				$this->Application->SetVar('folder_id', $folder_id);
			}

			/** @var kDBList $object */
			$object = $event->getObject();

			$user_id = $this->Application->RecallVar('user_id');

			if ( $folder_id == PM_FOLDER_INBOX ) {
				$object->addFilter('owner_filter', '%1$s.ToId = ' . $user_id);
			}
			else {
				$object->addFilter('owner_filter', '%1$s.FromId = ' . $user_id);
			}

			$object->addFilter('folder_filter', '%1$s.FolderId = ' . $folder_id);
		}

		/**
		 * Puts message to Sent folder
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnBeforeItemCreate(kEvent $event)
		{
			parent::OnBeforeItemCreate($event);

			/** @var kDBItem $object */
			$object = $event->getObject();

			if ( $object->GetDBField('FolderId') != PM_FOLDER_SENT ) {
				// when creating "Inbox" message (from "Sent" message) don't reset folder & status
				return ;
			}

			$user_id = $this->Application->RecallVar('user_id');
			$object->SetDBField('FromId', $user_id);
			$object->SetDBField('FolderId', PM_FOLDER_SENT);
			$object->SetDBField('Status', PM_STATUS_READ);
		}

		/**
		 * Creates 1st post when topic is created
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterItemCreate(kEvent $event)
		{
			parent::OnAfterItemCreate($event);

			/** @var kDBItem $object */
			$object = $event->getObject();

			$this->Application->emailUser('PM.ADD', $object->GetDBField('ToId'));

			if ( $object->GetDBField('FolderId') != PM_FOLDER_SENT ) {
				// 1. create message in sender's "Sent" folder (this method only for this step)
				// 2. create message body (shared)
				// 3. create message copy in recipient's "Inbox" folder
				return ;
			}

			/** @var kDBItem $message_body */
			$message_body = $this->Application->recallObject($event->Prefix . '-body', null, Array ('skip_autoload' => true));

			// 1. create message body (for sender & recipient)
			$copy_fields = Array ('Subject', 'Body', 'ShowSignatures', 'DisableSmileys', 'DisableBBCodes');
			$message_body->SetDBFieldsFromHash($object->GetFieldValues(), $copy_fields);

			$body_created = $message_body->Create();
			if ( $body_created ) {
				// 2. link body with message
				$object->SetDBField('PMBodyId', $message_body->GetID());
				$object->Update();

				// 3. create message in recipient's Inbox folder
				$object->SetDBField('FolderId', PM_FOLDER_INBOX);
				$object->SetDBField('Status', PM_STATUS_UNREAD);
				$object->Create();
			}
		}

		/**
		 * Sets post options to virtual fields
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterItemLoad(kEvent $event)
		{
			parent::OnAfterItemLoad($event);

			/** @var kDBItem $object */
			$object = $event->getObject();

			/** @var PostHelper $post_helper */
			$post_helper = $this->Application->recallObject('PostHelper');

			$options_map = $post_helper->getOptionsMap();
			$post_options = $object->GetDBField('Options');

			foreach ($options_map as $option_name => $field_name) {
				$option_value = $post_helper->GetPostOption($option_name, $post_options);
				$object->SetDBField($field_name, (int)$option_value);
			}
		}

		/**
		 * Goes to next_template after post creation
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnCreate(kEvent $event)
		{
			parent::OnCreate($event);

			if ( $event->status == kEvent::erSUCCESS && !$this->Application->isAdmin ) {
				$event->SetRedirectParam('opener', 's');
				$event->redirect = $this->Application->GetVar('next_template');
			}
		}

		/**
		 * Prevents user from deleting other user private messages
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnBeforeItemDelete(kEvent $event)
		{
			parent::OnBeforeItemDelete($event);

			/** @var kDBItem $object */
			$object = $event->getObject();

			$user_id = $this->Application->RecallVar('user_id');
			$owner_field = ($object->GetDBField('FolderId') == PM_FOLDER_INBOX) ? 'ToId' : 'FromId';

			if ( $object->GetDBField($owner_field) != $user_id ) {
				$event->status = kEvent::erFAIL;
			}
		}

		/**
		 * Updates reference counter in message body record
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterItemDelete(kEvent $event)
		{
	    	parent::OnAfterItemDelete($event);

			/** @var kDBItem $object */
			$object = $event->getObject();

			$body_idfield = $this->Application->getUnitOption($event->Prefix . '-body', 'IDField');
			$body_table = $this->Application->getUnitOption($event->Prefix . '-body', 'TableName');

			$sql = 'UPDATE ' . $body_table . '
	    			SET ReferenceCount = ReferenceCount - 1
	    			WHERE ' . $body_idfield . ' = ' . $object->GetDBField('PMBodyId');
			$this->Conn->Query($sql);
		}

		/**
		 * Sets default values to posting options based on persistent session
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterConfigRead(kEvent $event)
		{
			parent::OnAfterConfigRead($event);

			if ( !$this->Application->LoggedIn() ) {
				return;
			}

			$virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
			$virtual_fields['DisableBBCodes']['default'] = (int)!$this->Application->RecallPersistentVar('bbcode');
			$virtual_fields['DisableSmileys']['default'] = (int)!$this->Application->RecallPersistentVar('smileys');
			$virtual_fields['ShowSignatures']['default'] = (int)$this->Application->RecallPersistentVar('show_sig');
			$this->Application->setUnitOption($event->Prefix, 'VirtualFields', $virtual_fields);
		}

		/**
		 * Checks, that current user is recipient or sender of viewed message
		 *
		 * @param kEvent $event
		 * @return bool
		 * @access protected
		 */
		protected function checkItemStatus(kEvent $event)
		{
			/** @var kDBItem $object */
			$object = $event->getObject();

			if ( !$object->isLoaded() ) {
				return true;
			}

			$user_id = $this->Application->RecallVar('user_id');
			return ($object->GetDBField('FromId') == $user_id) || ($object->GetDBField('ToId') == $user_id);
		}

		/**
		 * Prepares new reply & new message form
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnNew(kEvent $event)
		{
			parent::OnNew($event);

			$reply_to = $this->Application->GetVar('reply_to');
			$user_id = $this->Application->GetVar('user_id');

			/** @var kDBItem $object */
			$object = $event->getObject();

			if ( $reply_to > 0 ) {
				// reply to message
				/** @var kDBItem $source_msg */
				$source_msg = $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true));

				$source_msg->Load($reply_to);

				$object->SetDBField('ToId', $source_msg->GetDBField('FromId'));
				$object->SetDBField('Subject', 'Re: ' . $source_msg->GetDBField('Subject'));
			}
			elseif ( $user_id > 0 ) {
				// send message to any user by id
				$object->SetDBField('ToId', $user_id);
			}
		}
	}
