<?php
/**
* @version	$Id: listings_event_handler.php 16694 2021-08-31 09:24:52Z alex $
* @package	In-Link
* @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 ListingsEventHandler extends kDBEventHandler {

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

		$permissions = Array(
			// front
			'OnRequestEnhancement'	=>	Array ('self' => true),
			'OnCancelEnhancement' => Array ('self' => true),
			'OnExtendEnhancement' => Array ('self' => true),
		);

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

	/**
	 * Adds selected link to listing
	 *
	 * @param kEvent $event
	 */
	function OnProcessSelected($event)
	{
		$object = $event->getObject();

		$selected_ids = $this->Application->GetVar('selected_ids');
		if ($selected_ids['l']) {
			$link_id = $selected_ids['l'];
			$sql = 'SELECT ResourceId
					FROM '.$this->Application->getUnitOption('l', 'TableName').'
					WHERE '.$this->Application->getUnitOption('l', 'IDField').' = '.$link_id;

			$object->SetDBField($this->Application->RecallVar('dst_field'), $this->Conn->GetOne($sql));
			$object->IgnoreValidation = true;
		//	$this->RemoveRequiredFields($object);
			$object->Update();
		}

		$this->finalizePopup($event);
	}

	function OnPreSaveListing($event)
	{
		$event->redirect=false;
		$object = $event->getObject( Array('skip_autoload' => true) );
		$object->IgnoreValidation = true;
	//	$this->RemoveRequiredFields($object);
		$event->CallSubEvent('OnPreSave');
		$this->Application->SetVar($event->getPrefixSpecial(true).'_id', $object->GetId());
		return;
	}

	/**
	 * Occurs before updating item
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function OnBeforeItemUpdate(kEvent $event)
	{
		/** @var kDBItem $object */
		$object = $event->getObject();

		if ( $object->IgnoreValidation ) {
			$object->UpdateFormattersMasterFields();
		}
	}

	/**
	 * Occurs before creating item
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function OnBeforeItemCreate(kEvent $event)
	{
		parent::OnBeforeItemCreate($event);

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

		if ( $object->IgnoreValidation ) {
			$object->UpdateFormattersMasterFields();
		}
	}

	/**
	 * Occurs before an item is deleted from live table when copying from temp
	 * (temp handler deleted all items from live and then copy over all items from temp)
	 * Id of item being deleted is passed as event' 'id' param
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function OnBeforeDeleteFromLive(kEvent $event)
	{
		parent::OnBeforeDeleteFromLive($event);

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

		$sql = 'SELECT *
				FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
				WHERE ListingId = ' . $object->GetId();
		$original_values = $this->Conn->GetRow($sql);

		$type_modified = ($object->GetDBField('ListingTypeId') != $original_values['ListingTypeId']);
		$link_modified = ($object->GetDBField('ItemResourceId') != $original_values['ItemResourceId']);
		$status_modified = ($object->GetDBField('Status') != $original_values['Status']);

		if ( $status_modified ) {
			$email_event = $object->GetDBField('Status') ? 'LINK.ENHANCE.APPROVE' : 'LINK.ENHANCE.DENY';
			$sql = 'SELECT CreatedById
					FROM ' . $this->Application->getUnitOption('l', 'TableName') . '
					WHERE ResourceId = ' . $object->GetDBField('ItemResourceId');
			$user_id = $this->Conn->GetOne($sql);

			$this->Application->emailUser($email_event, $user_id);
			$this->Application->emailAdmin($email_event);
		}

		if ( $type_modified || $link_modified ) {
			$this->ResetLink($original_values);
		}

		if ( $status_modified || $type_modified || $link_modified ) {
			$this->EnhanceLink($object, $original_values);
		}

		if ( $status_modified && !($type_modified || $link_modified) ) {
			$this->ResetLink($original_values);
		}
	}

	function EnhanceLink(&$object, $original_values)
	{
		if ($object->GetDBField('Status') != STATUS_ACTIVE) {
			return false;
		}

		if ($object->GetDBField('ExpiresOn') < adodb_mktime()) {
			$object->SetDBField('Status', STATUS_PENDING);
			$object->Update();
			$this->ResetLink($original_values);
			return false;
		}

		list($link_object, $listtype_object) = $this->UpdateLink(
			'OnPurchase',
			$object->GetDBField('ItemResourceId'),
			$object->GetDBField('ListingTypeId')
		);

		if ( $listtype_object->GetDBField('OnPurchaseAddToCatEnabled') )
		{
			$add_to_cat = (int)$listtype_object->GetDBField('OnPurchaseAddToCat');
			$sql = 'DELETE FROM '.$this->Application->getUnitOption('l-ci', 'TableName').'
					WHERE CategoryId = '.$add_to_cat.'
					AND ItemResourceId = '.$link_object->GetDBField('ResourceId').'
					AND PrimaryCat = 0';
			$this->Conn->Query($sql);
			$sql = 'INSERT INTO '.$this->Application->getUnitOption('l-ci', 'TableName').'
					(CategoryId, ItemResourceId, PrimaryCat)
					VALUES ('.$add_to_cat.', '.$link_object->GetDBField('ResourceId').', 0)';
			$this->Conn->Query($sql);
		}
	}

	function ResetLink($original_values)
	{
		static $has_been_reset = Array();

		if(	$original_values['Status'] != STATUS_ACTIVE ||
			getArrayValue($has_been_reset, $original_values['ListingId']) )
		{
			return;
		}

		$has_been_reset[$original_values['ListingId']] = 1;

		list (, $listtype_object) = $this->UpdateLink(
			'OnExpire',
			$original_values['ItemResourceId'],
			$original_values['ListingTypeId']
		);

		if( $listtype_object->GetDBField('OnExpireRemoveFromCatEnabled') )
		{
			$remove_from_cat = $listtype_object->GetDBField('OnExpireRemoveFromCat');
			$sql = 'DELETE FROM '.$this->Application->getUnitOption('l-ci', 'TableName').'
					WHERE ItemResourceId = '.$original_values['ItemResourceId'].'
					AND CategoryId = '.$remove_from_cat.'
					AND PrimaryCat = 0';
			$this->Conn->Query($sql);
		}
	}

	function UpdateLink($action_prefix, $resource_id, $listtype_id)
	{

		$link_object = $this->Application->recallObject('l', null, Array('skip_autoload' => true));
		$link_object->Load($resource_id, 'ResourceId');

		// "-item", because can be called as regular after event, and just "lst" recalls list instead
		$listtype_object = $this->Application->recallObject('lst.-item', null, Array('skip_autoload' => true));
		$listtype_object->Load($listtype_id);

		$action_fields = Array(	'EdPick'	=>	'EditorsPick',
								'New'		=>	'NewItem',
								'Hot'		=>	'HotItem',
								'Pop'		=>	'PopItem',
								'Status'	=>	'Status',
								'CustomTemplate'	=>	'CustomTemplate',
							);
	//	$action_prefix = 'OnPurchase';

		foreach($action_fields as $action => $field)
		{
			$action_value = $listtype_object->GetDBField($action_prefix.$action);
			if( $action_value != 3 )
			{
				$link_object->SetDBField($field, $action_value);
			}
		}

		$priority_value = $listtype_object->GetDBField($action_prefix.'PriorityValue');
		switch( $listtype_object->GetDBField($action_prefix.'PriorityAction') )
		{
			case 1: // equal
				$link_object->SetDBField('Priority', $priority_value);
			break;
			case 2: // increase
				$original_priority = $link_object->GetDBField('Priority');
				$link_object->SetDBField('Priority', $original_priority + $priority_value);
			break;
			case 3: // decrease
				$original_priority = $link_object->GetDBField('Priority');
				$link_object->SetDBField('Priority', $original_priority - $priority_value);
			break;
			default:
		}

		$link_object->Update();

		return array($link_object, $listtype_object);
	}

	/**
	 * Enter description here...
	 *
	 * @param kEvent $event
	 */
	function OnRequestEnhancement($event)
	{
		if ( $this->Application->prefixRegistred('ord') ) {
			$l_info = $this->Application->GetVar('l');
			if (!$l_info) {
				return false;
			}

			$link_id = key($l_info);
			$link_info = $l_info[$link_id];
			$listing_type_id = $link_info['ListingTypeId'];

			$listing_type = $this->Application->recallObject('lst', null, Array('skip_autoload' => true));
			$listing_type->Load($listing_type_id);

			if ($listing_type->GetDBField('EnableBuying')) {
				$add_to_cart_event = new kEvent('ord:OnAddVirtualProductToCart');
				$this->Application->HandleEvent($add_to_cart_event);

				if ($add_to_cart_event->redirect) {
					$event->SetRedirectParam('pass', 'm');
					$event->redirect = $add_to_cart_event->redirect;
				}
				return true;
			}
		}

		$event->CallSubEvent('OnListingCreate');
	}

	/**
	 * Create listing or extend existing listing period
	 *
	 * @param kEvent $event
	 */
	function OnListingCreate($event)
	{
		$new_processing = false;
		$link_id = $listing_type_id = 0;

		/** @var kDBItem $object */
		$object = $event->getObject( Array('skip_autoload' => true) );

		switch ($event->Name) {
			case 'EnhanceLinkAfterOrderApprove':
			case 'EnhancedLinkOnCompleteOrder':
				// when order with listing virtual product is approved
				$fields = $event->getEventParam('field_values');
				$item_data = unserialize($fields['ItemData']);
				$listing_type_id = $item_data['ListingTypeId'];
				$link_id = $item_data['LinkId'];

				$new_processing = getArrayValue($item_data, 'HasNewProcessing');
				break;

			case 'OnListingCreate':
				// when requesting enhancement from front (and not via in-commerce)
				$links_info = $this->Application->GetVar('l');
				if (!$links_info) return false;

				$event->redirect = false;
				$link_id = key($links_info);
				$link_info = $links_info[$link_id];
				$listing_type_id = $link_info['ListingTypeId'];

				$new_processing = false;
				break;
		}

		if (!$listing_type_id) {
			// free or invalid listing type selected
			return false;
		}

		// get resource_id of link beeing enhanced
		$sql = 'SELECT ResourceId
				FROM '.$this->Application->getUnitOption('l', 'TableName').'
				WHERE LinkId = '.$link_id;
		$resource_id = $this->Conn->GetOne($sql);

		// get listing by link's resource_id
		$object->Load($resource_id, 'ItemResourceId');
		if ($object->isLoaded()) {
			$original_values = $object->GetFieldValues();
		}
		else {
			// set initial fields to listing
			$object->SetDBField('ListingTypeId', $listing_type_id);
			$object->SetDBField('ItemResourceId', $resource_id);

			if ($event->Name == 'OnListingCreate' || $new_processing) {
				$item_status = STATUS_PENDING;
			}
			else {
				$item_status = STATUS_ACTIVE;
			}

			$object->SetDBField('Status', $item_status);
		}

		// set date of purchase for new listings
		$purchased_on = max(adodb_mktime(), $object->GetDBField('ExpiresOn'));
		if (!$object->isLoaded()) {
			$object->SetDBField('PurchasedOn_date', $purchased_on);
			$object->SetDBField('PurchasedOn_time', $purchased_on);
		}

		// set expiration time for listing
		$listing_type = $this->Application->recallObject('lst', null, Array('skip_autoload' => true));
		$listing_type->Load($listing_type_id);

		$dur_type_mapping = Array(	1	=>	1,
									2	=>	60,
									3	=>	3600,
									4	=>	3600*24,
									5	=>	3600*24*7,
									6	=>	3600*24*365/12,
									7	=>	3600*24*365
								);
		$duration = $listing_type->GetDBField('Duration');
		$duration_type = $listing_type->GetDBField('DurationType');
		$expiration_interval = $duration * $dur_type_mapping[$duration_type];
		$expiration_date = $purchased_on + $expiration_interval;
		$object->SetDBField('ExpiresOn_date', $expiration_date);
		$object->SetDBField('ExpiresOn_time', $expiration_date);

		// when extending enhancement mark listing as non-received renewal reminder
		$object->SetDBField('RenewalReminderSent', 0);

		$action = $object->isLoaded() ? 'Update' : 'Create';
		if ($object->$action()) {
			$event->status = kEvent::erSUCCESS;
			switch ($event->Name) {
				case 'EnhanceLinkAfterOrderApprove':
				case 'EnhancedLinkOnCompleteOrder':
					// when order with listing virtual product is approved
					if (getArrayValue($original_values, 'Status') != STATUS_ACTIVE) {
						$this->EnhanceLink($object, Array());
					}
					break;

				case 'OnListingCreate':
					// when requesting enhancement from front (and not via in-commerce)
					$event->redirect = $this->Application->GetVar('success_template');

					$sql = 'SELECT CreatedById FROM '.$this->Application->getUnitOption('l', 'TableName').'
							WHERE ResourceId = '.$object->GetDBField('ItemResourceId');
					$this->Application->emailUser('LINK.ENHANCE', $this->Conn->GetOne($sql));
					$this->Application->emailAdmin('LINK.ENHANCE');
					break;
			}


		}
		else {
			$event->status = kEvent::erFAIL;
		}


	}

	/**
	 * Enter description here...
	 *
	 * @param kEvent $event
	 */
	function EnhancedLinkOnCompleteOrder($event)
	{
		// create enhancement, but pending
		$this->OnListingCreate($event);

		// save created listing_id back to itemdata
		$object = $event->getObject( Array('skip_autoload' => true) );
		$fields = $event->getEventParam('field_values');
		$item_data = unserialize($fields['ItemData']);
		unset($item_data['ListingTypeId']);
		$item_data['ListingId'] = $object->GetID();

		$orditems_idfield = $this->Application->getUnitOption('orditems', 'IDField');
		$orditems_table = $this->Application->getUnitOption('orditems', 'TableName');

		$this->Conn->doUpdate( Array('ItemData' => serialize($item_data)), $orditems_table, $orditems_idfield.' = '.$fields['OrderItemId'] );
	}

	/**
	 * Enter description here...
	 *
	 * @param kEvent $event
	 */
	function EnhanceLinkAfterOrderApprove($event)
	{
		/** @var kDBItem $object */
		$object = $event->getObject( Array('skip_autoload' => true) );

		$fields = $event->getEventParam('field_values');
		$item_data = unserialize($fields['ItemData']);

		if ( getArrayValue($item_data, 'HasNewProcessing') ) {
			// new processing: just approve created listing here
			$listing_id = $item_data['ListingId'];
			$object->Load($listing_id);

			// moved enhancement period to time admin approved enhancement
			$time_diff = adodb_mktime() - $object->GetDBField('PurchasedOn');
			$object->SetDBField('PurchasedOn_date', $object->GetDBField('PurchasedOn_date') + $time_diff);
			$object->SetDBField('PurchasedOn_time', $object->GetDBField('PurchasedOn_time') + $time_diff);
			$object->SetDBField('ExpiresOn_date', $object->GetDBField('ExpiresOn_date') + $time_diff);
			$object->SetDBField('ExpiresOn_time', $object->GetDBField('ExpiresOn_time') + $time_diff);

			$object->SetDBField('Status', STATUS_ACTIVE);
			$object->Update();

			$this->EnhanceLink($object, Array());
			return true;
		}
		else {
			// create listing & approve it at the same time
			$this->OnListingCreate($event);
		}
	}

	/**
	 * Delete listing
	 *
	 * @param kEvent $event
	 */
	function EnhanceLinkAfterOrderDeny($event)
	{
		$object = $event->getObject( Array('skip_autoload' => true) );
		$fields = $event->getEventParam('field_values');
		$item_data = unserialize($fields['ItemData']);
		$listing_id = $item_data['ListingId'];

		$temp_handler = $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
		$temp_handler->DeleteItems($event->Prefix, $event->Special, Array($listing_id));
	}

	/**
	 * Enter description here...
	 *
	 * @param kEvent $event
	 */
	function ExpireLink($event)
	{
		/** @var kDBItem $object */
		$object = $event->getObject(Array ('skip_autoload' => true));

		$fields = $event->getEventParam('field_values');
		$item_data = unserialize($fields['ItemData']);

		$sql = 'SELECT ListingId FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
				WHERE ItemResourceId = ' . $item_data['LinkId'];
		$listing_id = $this->Conn->GetOne($sql);

		$object->Load($listing_id);
		$original_values = $object->GetFieldValues();
		$object->SetDBField('Status', 2);

		if ( $object->Update() ) {
			$event->status = kEvent::erSUCCESS;
			$this->ResetLink($original_values);
		}
		else {
			$event->status = kEvent::erFAIL;
		}
	}

	/**
	 * Apply same processing to each item being selected in grid
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function iterateItems(kEvent $event)
	{
		/** @var kDBItem $object */
		$object = $event->getObject(Array ('skip_autoload' => true));

		$ids = $this->StoreSelectedIDs($event);

		if ( $event->Name == 'OnMassApprove' ) {
			foreach ($ids as $id) {
				$object->Load($id);
				if ( $object->GetDBField('Status') != STATUS_ACTIVE ) {
					$original_values = $object->GetFieldValues();
					$object->SetDBField('Status', STATUS_ACTIVE);
					$this->EnhanceLink($object, $original_values);
				}
			}
		}

		if ( $event->Name == 'OnMassDecline' ) {
			foreach ($ids as $id) {
				$object->Load($id);
				if ( $object->GetDBField('Status') == STATUS_ACTIVE ) {
					$original_values = $object->GetFieldValues();
					$this->ResetLink($original_values);

					$sql = 'SELECT CreatedById
							FROM ' . $this->Application->getUnitOption('l', 'TableName') . '
							WHERE ResourceId = ' . $object->GetDBField('ItemResourceId');
					$this->Application->emailUser('LINK.ENHANCE.DENY', $this->Conn->GetOne($sql));
					$this->Application->emailAdmin('LINK.ENHANCE.DENY');
				}
			}
		}

		parent::iterateItems($event);

		// extend period for pending/renewal links (if owner has agreed)
		if ( $event->Name == 'OnMassApprove' ) {
			/** @var kDBItem $lst_object */
			$lst_object = $this->Application->recallObject('lst', null, Array ('skip_autoload' => true));

			foreach ($ids as $id) {
				$object->Load($id);

				$sql = 'SELECT CreatedById
						FROM ' . $this->Application->getUnitOption('l', 'TableName') . '
						WHERE ResourceId = ' . $object->GetDBField('ItemResourceId');
				$owner_id = $this->Conn->GetOne($sql);

				if ( $object->GetDBField('PendingRenewal') == 1 ) {
					$lst_object->Load( $object->GetDBField('ListingTypeId') );
					$dur_type_mapping = Array (
						1 => 1, 2 => 60, 3 => 3600, 4 => 3600 * 24, 5 => 3600 * 24 * 7,
						6 => 3600 * 24 * 365 / 12, 7 => 3600 * 24 * 365
					);
					$duration = $lst_object->GetDBField('Duration');
					$duration_type = $lst_object->GetDBField('DurationType');
					$expiration_interval = $duration * $dur_type_mapping[$duration_type];
					$renewal_begins = max(adodb_mktime(), $object->GetDBField('ExpiresOn'));
					$expiration_date = $renewal_begins + $expiration_interval;

					$object->SetDBField('ExpiresOn_date', $expiration_date);
					$object->SetDBField('ExpiresOn_time', $expiration_date);

					$object->SetDBField('RenewalReminderSent', 0);
					$object->SetDBField('PendingRenewal', 0);

					if ( $object->Update() ) {
						$event->SetRedirectParam('opener', 's');
						$this->Application->emailUser('LINK.ENHANCE.RENEW', $owner_id);
						$this->Application->emailAdmin('LINK.ENHANCE.RENEW');
					}
				}
				else {
					$this->Application->emailUser('LINK.ENHANCE.APPROVE', $owner_id);
					$this->Application->emailAdmin('LINK.ENHANCE.APPROVE');
				}
			}
		}
	}

	/**
	 * Redirects to cancel template on front-end
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function OnCancel(kEvent $event)
	{
		parent::OnCancel($event);

		if ( !$this->Application->isAdmin ) {
			$event->SetRedirectParam('opener', 's');
			$event->redirect = $this->Application->GetVar('cancel_template');
		}
	}

	/**
	 * Checks that user is owner of link & returns listing id if permissions are ok
	 *
	 * @param kEvent $event
	 * @return mixed
	 */
	function verifyListingOwner($event)
	{
		$link_id = $this->Application->GetVar('l_id');
		$user_id = $this->Application->RecallVar('user_id');
		$sql = 'SELECT ResourceId
				FROM '.$this->Application->getUnitOption('l', 'TableName').'
				WHERE (LinkId = '.$link_id.') AND (CreatedById = '.$user_id.')';
		$resource_id = $this->Conn->GetOne($sql);

		if (!$resource_id) {
			$event->status = kEvent::erFAIL;
			return false;
		}

		$sql = 'SELECT ListingId
				FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
				WHERE ItemResourceId = '.$resource_id;

		return $this->Conn->GetOne($sql);
	}

	function OnExtendEnhancement($event)
	{
		$listing_id = $this->verifyListingOwner($event);
		if (!$listing_id) {
			return ;
		}

		$object = $event->getObject( Array('skip_autoload' => true) );
		$object->Load($listing_id);

		$object->SetDBField('PendingRenewal', 1);
		$object->Update();
		$event->redirect = $this->Application->GetVar('success_template');

		$sql = 'SELECT CreatedById FROM '.$this->Application->getUnitOption('l', 'TableName').'
				WHERE ResourceId = '.$object->GetDBField('ItemResourceId');
		$this->Application->emailUser('LINK.ENHANCE.EXTEND', $this->Conn->GetOne($sql));
		$this->Application->emailAdmin('LINK.ENHANCE.EXTEND');
	}

	/**
	 * Cancels enhancement
	 *
	 * @param kEvent $event
	 */
	function OnCancelEnhancement($event)
	{
		$listing_id = $this->verifyListingOwner($event);
		if ( !$listing_id ) {
			return;
		}

		/** @var kDBItem $object */
		$object = $event->getObject(Array ('skip_autoload' => true));

		$object->Load($listing_id);

		$original_values = $object->GetFieldValues();
		$original_values['Status'] = 1;
		$this->ResetLink($original_values);

		$sql = 'SELECT CreatedById FROM ' . $this->Application->getUnitOption('l', 'TableName') . '
				WHERE ResourceId = ' . $object->GetDBField('ItemResourceId');
		$this->Application->emailUser('LINK.ENHANCE.CANCEL', $this->Conn->GetOne($sql));
		$this->Application->emailAdmin('LINK.ENHANCE.CANCEL');

		$object->Delete();
		$event->redirect = $this->Application->GetVar('success_template');
	}

	/**
	 * Checks expired paid listings
	 *
	 * @param kEvent $event
	 */
	function OnCheckExpiredPaidListings($event)
	{
		$sql = 'SELECT ListingId FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
				WHERE ExpiresOn < '.adodb_mktime().' AND Status = 1';
		$expired_listings = $this->Conn->GetCol($sql);
		if(is_array($expired_listings) && count($expired_listings) > 0)
		{
			/** @var kDBItem $object */
			$object = $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true));

			foreach($expired_listings as $listing_id)
			{
				$object->Load($listing_id);
				$original_values = $object->GetFieldValues();
				$this->ResetLink($original_values);
				$object->SetDBField('Status', 2);
				$object->Update();

				$sql = 'SELECT CreatedById FROM '.$this->Application->getUnitOption('l', 'TableName').'
						WHERE ResourceId = '.$object->GetDBField('ItemResourceId');
				$this->Application->emailUser('LINK.ENHANCE.EXPIRE', $this->Conn->GetOne($sql));
				$this->Application->emailAdmin('LINK.ENHANCE.EXPIRE');
			}
		}

		$sql = 'SELECT ls.ListingId, l.CreatedById FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' ls
				LEFT JOIN '.$this->Application->getUnitOption('lst', 'TableName').' lst
				ON ls.ListingTypeId = lst.ListingTypeId
				LEFT JOIN '.$this->Application->getUnitOption('l', 'TableName').' l
				ON ls.ItemResourceId = l.ResourceId
				WHERE ls.Status = 1
				AND ls.ExpiresOn < '.adodb_mktime().' + lst.RenewalReminder * 3600 *24
				AND ls.RenewalReminderSent = 0';
		$res = $this->Conn->Query($sql);
		if(is_array($res) && count($res) > 0)
		{
			$listing_ids = Array();
			foreach($res as $record)
			{
				$this->Application->emailUser('LINK.ENHANCE.RENEWAL.NOTICE', $record['CreatedById']);
				$this->Application->emailAdmin('LINK.ENHANCE.RENEWAL.NOTICE');
				$listing_ids[] = $record['ListingId'];
			}
			$sql = 'UPDATE '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
					SET RenewalReminderSent = 1
					WHERE ListingId IN ('.implode(',', $listing_ids).')';
			$this->Conn->Query($sql);
		}
	}

	/**
	 * Removes enhancements on listing delete
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function OnMassDelete(kEvent $event)
	{
		/** @var kDBItem $object */
		$object = $event->getObject(Array ('skip_autoload' => true));

		$ids = $this->StoreSelectedIDs($event);

		foreach ($ids as $id) {
			$object->Load($id);

			if ( $object->GetDBField('Status') == STATUS_ACTIVE ) {
				$this->ResetLink( $object->GetFieldValues() );
			}
		}

		parent::OnMassDelete($event);
	}

	/**
	 * Moves enhancement from original link to it's pending copy, that is going to be approved
	 *
	 * @param kEvent $event
	 */
	function OnMoveEnhancement($event)
	{
		$id_field = $this->Application->getUnitOption($event->MasterEvent->Prefix, 'IDField');
		$item_table_name = $this->Application->getUnitOption($event->MasterEvent->Prefix, 'TableName');

		$pending_id = $event->MasterEvent->getEventParam('id');
		$original_id = $event->MasterEvent->getEventParam('original_id');

		$sql = 'SELECT ResourceId, '.$id_field.'
				FROM '.$item_table_name.'
				WHERE '.$id_field.' IN ('.$pending_id.','.$original_id.')';
		$resource_ids = $this->Conn->GetCol($sql, $id_field);

		$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
		$sql = 'UPDATE '.$table_name.'
				SET ItemResourceId = '.$resource_ids[$pending_id].'
				WHERE ItemResourceId = '.$resource_ids[$original_id];
		$this->Conn->Query($sql);
	}

	/**
	 * Makes calculated fields to go to multilingual link fields
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function OnAfterConfigRead(kEvent $event)
	{
		parent::OnAfterConfigRead($event);

		$language_id = $this->Application->GetVar('m_lang');
		$calculated_fields = $this->Application->getUnitOption($event->Prefix, 'CalculatedFields');
		$calculated_fields['']['LinkName'] = 'CONCAT(item_table.l' . $language_id . '_Name, " (", item_table.Url, ")")';
		$this->Application->setUnitOption($event->Prefix, 'CalculatedFields', $calculated_fields);
	}
}