<?php
if (!defined("ROOT_PATH"))
{
	header("HTTP/1.1 403 Forbidden");
	exit;
}
require_once PJ_CONTROLLERS_PATH . 'pjWeb.controller.php';
class pjWebPages extends pjWeb
{
	private function __getFilter()
	{
		$pjListingModel = pjListingModel::factory();
		
		$type_arr = pjTypeModel::factory()
			->select("t1.*, t2.content AS `name`, (SELECT COUNT(*) FROM `".$pjListingModel->getTable()."` AS `TL` WHERE TL.type_id = t1.id AND (TL.status = 'T' OR (TL.status = 'E' AND TL.expire >= CURDATE()))) AS `number_of_packages`")
			->join('pjMultiLang', "t2.model='pjType' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='".$this->getLocaleId()."'", 'left outer')
			->where('t1.status', 'T')
			->orderBy('`name` ASC')
			->findAll()
			->getDataPair('id');
			
		/*
		$statement = sprintf("SELECT 1,
			(SELECT COUNT(*) FROM `%1\$s` WHERE `listing_season` REGEXP :regexp_1 LIMIT 1) AS `cnt_1`,
			(SELECT COUNT(*) FROM `%1\$s` WHERE `listing_season` REGEXP :regexp_2 LIMIT 1) AS `cnt_2`,
			(SELECT COUNT(*) FROM `%1\$s` WHERE `listing_season` REGEXP :regexp_3 LIMIT 1) AS `cnt_3`,
			(SELECT COUNT(*) FROM `%1\$s` WHERE `listing_season` REGEXP :regexp_4 LIMIT 1) AS `cnt_4`",
			$pjListingModel->getTable()
		);
		*/
		
		$statement = sprintf("SELECT 1,
			(SELECT COUNT(*) FROM `%1\$s` WHERE `listing_season` LIKE :like_1_start OR `listing_season` LIKE :like_1_middle OR `listing_season` LIKE :like_1_end LIMIT 1) AS `cnt_1`,
			(SELECT COUNT(*) FROM `%1\$s` WHERE `listing_season` LIKE :like_2_start OR `listing_season` LIKE :like_2_middle OR `listing_season` LIKE :like_2_end LIMIT 1) AS `cnt_2`,
			(SELECT COUNT(*) FROM `%1\$s` WHERE `listing_season` LIKE :like_3_start OR `listing_season` LIKE :like_3_middle OR `listing_season` LIKE :like_3_end LIMIT 1) AS `cnt_3`,
			(SELECT COUNT(*) FROM `%1\$s` WHERE `listing_season` LIKE :like_4_start OR `listing_season` LIKE :like_4_middle OR `listing_season` LIKE :like_4_end LIMIT 1) AS `cnt_4`",
			$pjListingModel->getTable()
		);
		
		/*
		'regexp_1' => "^1\||\|1\||\|1$",
		'regexp_2' => "^2\||\|2\||\|2$",
		'regexp_3' => "^3\||\|3\||\|3$",
		'regexp_4' => "^4\||\|4\||\|4$"
		*/
		
		$season_arr = $pjListingModel
			->prepare($statement)
			->exec(array(
				'like_1_start' => '1|%',
				'like_1_middle' => '%|1|%',
				'like_1_end' => '%|1',
				'like_2_start' => '2|%',
				'like_2_middle' => '%|2|%',
				'like_2_end' => '%|2',
				'like_3_start' => '3|%',
				'like_3_middle' => '%|3|%',
				'like_3_end' => '%|3',
				'like_4_start' => '4|%',
				'like_4_middle' => '%|4|%',
				'like_4_end' => '%|4'
			))
			->getDataIndex(0);
			
		return compact('season_arr', 'type_arr');
	}
	
	private function __getPage($id=NULL, $seo_url=NULL)
	{
		$pjPageModel = pjPageModel::factory();
		
		$pjPageModel
			->select('t1.*, t2.content AS `name`, t3.content AS `title`, t4.content AS `full_desc`, t5.content AS `meta_title`, t6.content AS `meta_desc`')
			->join('pjMultiLang', sprintf("t2.model='pjPage' AND t2.foreign_id=t1.id AND t2.locale='%u' AND t2.field='name'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t3.model='pjPage' AND t3.foreign_id=t1.id AND t3.locale='%u' AND t3.field='title'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t4.model='pjPage' AND t4.foreign_id=t1.id AND t4.locale='%u' AND t4.field='full_desc'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t5.model='pjPage' AND t5.foreign_id=t1.id AND t5.locale='%u' AND t5.field='meta_title'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t6.model='pjPage' AND t6.foreign_id=t1.id AND t6.locale='%u' AND t6.field='meta_desc'", $this->getLocaleId()), 'left outer');
		
		if (!is_null($id))
		{
			$pjPageModel->where('t1.id', $id);
		} elseif (!is_null($seo_url)) {
			$pjPageModel->where('t1.seo_url', $seo_url);
		} else {
			return FALSE;
		}
		
		return $pjPageModel
			->limit(1)
			->findAll()
			->getDataIndex(0);
	}
	
	public function pjActionIndex()
	{
		$home_m_title = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'home_m_title');
		$home_m_desc = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'home_m_desc');
		$this->set('meta_arr', array(
			'title' => $home_m_title['home_m_title'],
			'desc' => $home_m_desc['home_m_desc']
			)
		);
		
		$this->set('slide_arr', pjSlideModel::factory()
			->select('t1.*, t2.content AS `title`, t3.content AS `desc`, t4.content AS `url`')
			->join('pjMultiLang', sprintf("t2.model='pjSlide' AND t2.foreign_id=t1.id AND t2.locale='%u' AND t2.field='title'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t3.model='pjSlide' AND t3.foreign_id=t1.id AND t3.locale='%u' AND t3.field='desc'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t4.model='pjSlide' AND t4.foreign_id=t1.id AND t4.locale='%u' AND t4.field='url'", $this->getLocaleId()), 'left outer')
			->where('t1.status', 'T')
			->orderBy('t1.sort ASC')
			->findAll()
			->getData()
		);
		
		$this->set('dest_arr', pjDestinationModel::factory()
			->select('t1.*, t2.content AS `name`, t3.content AS `country`')
			->join('pjMultiLang', sprintf("t2.model='pjDestination' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t3.model='pjCountry' AND t3.foreign_id=t1.country_id AND t3.field='name' AND t3.locale='%u'", $this->getLocaleId()), 'left outer')
			->where('t1.on_home', 1)
			->where('t1.status', 'T')
			->orderBy('`name` ASC')
			->findAll()
			->getData()
		);
		
		pjObject::import('Model', 'pjGallery:pjGallery');
		
		$pjListingModel = pjListingModel::factory();
		$pjGalleryModel = pjGalleryModel::factory();
		$pjPriceModel = pjPriceModel::factory();
		
		$this->set('featured_arr', $pjListingModel
			->reset()
			->select(sprintf("t1.*, t2.content AS `listing_title`, t3.content AS `country_title`, t4.content AS `type`,
				(SELECT MIN(`price`) FROM `%1\$s` WHERE `listing_id` = t1.id ORDER BY `id` ASC LIMIT 1) AS `price_from`,
				(SELECT CONCAT_WS('|', `medium_path`, `alt`) FROM `%2\$s` WHERE `foreign_id` = t1.id ORDER BY `sort` ASC LIMIT 1) AS `image`
				", $pjPriceModel->getTable(), $pjGalleryModel->getTable()
			))
			->join('pjMultiLang', sprintf(
				"t2.model='pjListing' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='%u'",
				$this->getLocaleId()
			), 'left outer')
			->join('pjMultiLang', sprintf(
				"t3.model='pjCountry' AND t3.foreign_id=t1.country_id AND t3.field='name' AND t3.locale='%u'",
				$this->getLocaleId()
			), 'left outer')
			->join('pjMultiLang', sprintf(
				"t4.model='pjType' AND t4.foreign_id=t1.type_id AND t4.field='name' AND t4.locale='%u'",
				$this->getLocaleId()
			), 'left outer')
			->where('t1.is_featured', 'T')
			->orderBy('t1.id DESC')
			->findAll()
			->getData()
		);
		
		$this->set('deals_arr', $pjListingModel
			->reset()
			->select(sprintf("t1.*, t2.content AS `listing_title`, t3.content AS `country_title`, t4.content AS `type`,
				(SELECT MIN(`price`) FROM `%1\$s` WHERE `listing_id` = t1.id ORDER BY `id` ASC LIMIT 1) AS `price_from`,
				(SELECT CONCAT_WS('|', `medium_path`, `alt`) FROM `%2\$s` WHERE `foreign_id` = t1.id ORDER BY `sort` ASC LIMIT 1) AS `image`
				", $pjPriceModel->getTable(), $pjGalleryModel->getTable()
			))
			->join('pjMultiLang', sprintf(
				"t2.model='pjListing' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='%u'",
				$this->getLocaleId()
			), 'left outer')
			->join('pjMultiLang', sprintf(
				"t3.model='pjCountry' AND t3.foreign_id=t1.country_id AND t3.field='name' AND t3.locale='%u'",
				$this->getLocaleId()
			), 'left outer')
			->join('pjMultiLang', sprintf(
				"t4.model='pjType' AND t4.foreign_id=t1.type_id AND t4.field='name' AND t4.locale='%u'",
				$this->getLocaleId()
			), 'left outer')
			->where('t1.is_best_deal', 2)
			->orderBy('t1.id DESC')
			->findAll()
			->getData()
		);
		
		$this->set('banner_arr', pjBannerModel::factory()
			->select('t1.*, t2.content AS `alt`, t3.content AS `title`, t4.content AS `url`, t5.content AS `code`')
			->join('pjMultiLang', sprintf("t2.model='pjBanner' AND t2.foreign_id=t1.id AND t2.locale='%u' AND t2.field='alt'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t3.model='pjBanner' AND t3.foreign_id=t1.id AND t3.locale='%u' AND t3.field='title'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t4.model='pjBanner' AND t4.foreign_id=t1.id AND t4.locale='%u' AND t4.field='url'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t5.model='pjBanner' AND t5.foreign_id=t1.id AND t5.locale='%u' AND t5.field='code'", $this->getLocaleId()), 'left outer')
			->where('t1.status', 'T')
			->orderBy('RAND()')
			->limit(1)
			->findAll()
			->getDataIndex(0)
		);
		
		$this->set('price_arr', pjPriceModel::factory()
			->where('listing_id', $arr['id'])
			->orderBy('date_from ASC, date_to ASC')
			->findAll()
			->getData()
		);

		
		$filter = $this->__getFilter();
		
		$this->set('type_arr', $filter['type_arr']);
		$this->set('season_arr', $filter['season_arr']);
		
		$this->appendCss('owl.carousel.css', PJ_THIRD_PARTY_PATH . 'owl-carousel/');
		$this->appendCss('owl.theme.css', PJ_THIRD_PARTY_PATH . 'owl-carousel/');
		$this->appendJs('owl.carousel.min.js', PJ_THIRD_PARTY_PATH . 'owl-carousel/');
		
		$this->appendCss('jquery-ui.min.css', PJ_THIRD_PARTY_PATH . 'jquery_ui/css/smoothness/');
		$this->appendCss('pjWebHome.css');
		$this->appendCss('pjWebForms.css');
		
		$this->appendJs('jquery-ui.custom.min.js', PJ_THIRD_PARTY_PATH . 'jquery_ui/js/');
		$this->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/');
		$this->appendJs('pjWebHome.js');
		$this->appendJs('pjWebSuggest.js');
		$this->appendJs('pjWebSearch.js');
		$this->appendJs('pjWebForms.js');
	}
	
	public function pjActionCaptcha()
	{
		$this->setAjax(true);
		$this->setLayout('pjActionEmpty');

		header("Cache-Control: max-age=3600, private");
		
		if (!isset($_GET['comment']))
		{
			$Captcha = new pjCaptcha('app/web/obj/Anorexia.ttf', $this->defaultCaptcha, 6);
		} else {
			$Captcha = new pjCaptcha('app/web/obj/Anorexia.ttf', $this->defaultCommentCaptcha, 6);
		}
		$Captcha->setImage('app/web/img/button.png')->init(isset($_GET['rand']) ? $_GET['rand'] : null);
		exit;
	}

	public function pjActionCheckCaptcha()
	{
		$this->setAjax(true);
		$this->setLayout('pjActionEmpty');
		
		if ($this->isXHR())
		{
			$variable = $this->defaultCaptcha;
			if (isset($_GET['comment']))
			{
				$variable = $this->defaultCommentCaptcha;
			}
			
			if (!isset($_GET['captcha']) || empty($_GET['captcha'])
				|| !isset($_SESSION[$variable]) || empty($_SESSION[$variable]))
			{
				die('false');
			}
			
			if (pjCaptcha::validate($_GET['captcha'], $_SESSION[$variable]))
			{
				die('true');
			}
			die('false');
		}
		die('false');
	}
	
	public function pjActionContact()
	{
		$contact_m_title = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'contact_m_title');
		$contact_m_desc = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'contact_m_desc');
		$this->set('meta_arr', array(
			'title' => $contact_m_title['contact_m_title'],
			'desc' => $contact_m_desc['contact_m_desc']
			)
		);
		if (isset($_POST['contact_send']))
		{
			if (!isset($_POST['name'])
				|| !isset($_POST['email'])
				|| !isset($_POST['phone'])
				|| !isset($_POST['question'])
				|| !isset($_POST['captcha'])
				|| !pjValidation::pjActionNotEmpty($_POST['name'])
				|| !pjValidation::pjActionNotEmpty($_POST['email'])
				|| !pjValidation::pjActionNotEmpty($_POST['phone'])
				|| !pjValidation::pjActionNotEmpty($_POST['question'])
				|| !pjValidation::pjActionNotEmpty($_POST['captcha'])
				|| !pjValidation::pjActionEmail($_POST['email'])
				|| !isset($_SESSION[$this->defaultCaptcha])
				|| !pjCaptcha::validate($_POST['captcha'], $_SESSION[$this->defaultCaptcha])
				)
			{
				pjUtil::redirect(sprintf("%s%s/contact/?err=WC03", PJ_INSTALL_URL, $this->getLanguage()));
			}
			
			$arr = pjNotificationModel::factory()
				->select('t1.*, t2.content AS `contact_subject`, t3.content AS `contact_message`')
				->join('pjMultiLang', sprintf("t2.model='pjNotification' AND t2.foreign_id=t1.id AND t2.field='contact_subject' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
				->join('pjMultiLang', sprintf("t3.model='pjNotification' AND t3.foreign_id=t1.id AND t3.field='contact_message' AND t3.locale='%u'", $this->getLocaleId()), 'left outer')
				->find(1)->getData();
			if (empty($arr))
			{
				//TODO
			}
			
			$Email = new pjEmail();
			if ($this->option_arr['o_send_email'] == 'smtp')
			{
				$Email
					->setTransport('smtp')
					->setSmtpHost($this->option_arr['o_smtp_host'])
					->setSmtpPort($this->option_arr['o_smtp_port'])
					->setSmtpUser($this->option_arr['o_smtp_user'])
					->setSmtpPass($this->option_arr['o_smtp_pass'])
				;
			}

			$admin_email = $this->getFromEmail();
			
			$Email
				->setTo($admin_email)
				->setFrom($admin_email)
				->setReturnPath($admin_email)
				->setReplyTo($_POST['email'])
				->setSubject($arr['contact_subject'])
			;
			$message = str_replace(
				array('{Name}', '{Email}', '{Phone}', '{Question}', '{IP}'),
				array($_POST['name'], $_POST['email'], $_POST['phone'], $_POST['question'], pjUtil::getClientIp()),
				$arr['contact_message']
			);
			$err = $Email->send($message) ? 'WC01' : 'WC02';
			
			pjUtil::redirect(sprintf("%s%s/contact/?err=%s", PJ_INSTALL_URL, $this->getLanguage(), $err));
		}
		$this->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/');
		$this->appendJs('pjWebForms.js');
		$this->appendCss('pjWebPages.css');
		$this->appendCss('pjWebForms.css');
	}
	
	public function pjActionBestDeals()
	{
		$deals_m_title = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'deals_m_title');
		$deals_m_desc = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'deals_m_desc');
		$this->set('meta_arr', array(
			'title' => $deals_m_title['deals_m_title'],
			'desc' => $deals_m_desc['deals_m_desc']
			)
		);
		$this->appendJs('pjWebSuggest.js');
		$this->appendJs('pjWebSearch.js');
		
		$this->appendCss('pjWebForms.css');
		$this->appendCss('pjWebListings.css');
		$this->appendCss('pjWebMaps.css');
	}
	
	public function pjActionDestinations()
	{
		$pjDestinationModel = pjDestinationModel::factory();
		
		$this->set('dest_arr', $pjDestinationModel
			->select('t1.*, t2.content AS `name`, t3.content AS `country`')
			->join('pjMultiLang', sprintf("t2.model='pjDestination' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t3.model='pjCountry' AND t3.foreign_id=t1.country_id AND t3.field='name' AND t3.locale='%u'", $this->getLocaleId()), 'left outer')
			->where('t1.status', 'T')
			->orderBy('`name` ASC')
			->findAll()
			->getData()
		);
		
		if (isset($_GET['seo_url']) && !empty($_GET['seo_url']))
		{
			$arr = $pjDestinationModel
				->reset()
				->select('t1.*, t2.content AS `name`, t3.content AS `title`, t4.content AS `full_desc`, t5.content AS `meta_title`, t6.content AS `meta_desc`')
				->join('pjMultiLang', sprintf("t2.model='pjDestination' AND t2.foreign_id=t1.id AND t2.locale='%u' AND t2.field='name'", $this->getLocaleId()), 'left outer')
				->join('pjMultiLang', sprintf("t3.model='pjDestination' AND t3.foreign_id=t1.id AND t3.locale='%u' AND t3.field='title'", $this->getLocaleId()), 'left outer')
				->join('pjMultiLang', sprintf("t4.model='pjDestination' AND t4.foreign_id=t1.id AND t4.locale='%u' AND t4.field='full_desc'", $this->getLocaleId()), 'left outer')
				->join('pjMultiLang', sprintf("t5.model='pjDestination' AND t5.foreign_id=t1.id AND t5.locale='%u' AND t5.field='meta_title'", $this->getLocaleId()), 'left outer')
				->join('pjMultiLang', sprintf("t6.model='pjDestination' AND t6.foreign_id=t1.id AND t6.locale='%u' AND t6.field='meta_desc'", $this->getLocaleId()), 'left outer')
				->where('t1.seo_url', $_GET['seo_url'])
				->where('t1.status', 'T')
				->limit(1)
				->findAll()
				->getDataIndex(0);
		}
		
		$this->set('arr', $arr);
		$this->set('meta_arr', array(
			'title' => @$arr['meta_title'],
			'desc' => @$arr['meta_desc'])
		);
		$this->appendCss('pjWebPages.css');
		$this->appendJs('pjWebPages.js');
	}
	
	public function pjActionEnquiry()
	{
		$this->setAjax(true);
	
		if ($this->isXHR())
		{
			if (!isset($_POST['captcha'])
				|| empty($_POST['captcha'])
				|| !isset($_SESSION[$this->defaultCaptcha])
				|| !pjCaptcha::validate($_POST['captcha'], $_SESSION[$this->defaultCaptcha]))
			{
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Captcha does not match.'));
			}
			
			if (isset($_POST['booking_form']))
			{
				$pjEnquiryModel = pjEnquiryModel::factory();
				
				$required = array('listing_id', 'date_from', 'date_to', 'name', 'email', 'phone', 'notes');
				if (!$pjEnquiryModel->validateRequest($required, $_POST))
				{
					pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'Missing parameters.'));
				}
				
				$data = array();
				$data['date_from'] = pjUtil::formatDate($_POST['date_from'], $this->option_arr['o_date_format']);
				$data['date_to'] = pjUtil::formatDate($_POST['date_to'], $this->option_arr['o_date_format']);
				$data['status'] = 'New';
				$data = array_merge($_POST, $data);
				
				if (!$pjEnquiryModel->validates($data))
				{
					pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 102, 'text' => 'Invalid parameters.'));
				}
				
				$id = $pjEnquiryModel->setAttributes($data)->insert()->getInsertId();
				if ($id !== FALSE && (int) $id > 0)
				{
					$_SESSION[$this->defaultCaptcha] = NULL;
					unset($_SESSION[$this->defaultCaptcha]);
					
					$statement = sprintf("SELECT t1.*,
							t3.content AS `owner_subject`,
							t4.content AS `owner_message`,
							t6.content AS `admin_subject`,
							t7.content AS `admin_message`,
							t8.content AS `listing_title`,
							t9.email AS `owner_email`, t9.name AS `owner_name`,
							t10.email AS `admin_email`, t10.name AS `admin_name`
						FROM `%1\$s` AS `t1`
						
						LEFT OUTER JOIN (SELECT `id`, `user_id` FROM `%2\$s` GROUP BY `user_id`) AS `t2` ON t2.user_id = t1.owner_id
						LEFT OUTER JOIN `%3\$s` AS `t3` ON t3.model=:pjNotification AND t3.foreign_id=t2.id AND t3.field=:confirm_subject AND t3.locale=:locale
						LEFT OUTER JOIN `%3\$s` AS `t4` ON t4.model=:pjNotification AND t4.foreign_id=t2.id AND t4.field=:confirm_message AND t4.locale=:locale
						
						LEFT OUTER JOIN (SELECT `id`, `user_id` FROM `%2\$s` GROUP BY `user_id`) AS `t5` ON t5.user_id = :user_id
						LEFT OUTER JOIN `%3\$s` AS `t6` ON t6.model=:pjNotification AND t6.foreign_id=t5.id AND t6.field=:confirm_subject AND t6.locale=:locale
						LEFT OUTER JOIN `%3\$s` AS `t7` ON t7.model=:pjNotification AND t7.foreign_id=t5.id AND t7.field=:confirm_message AND t7.locale=:locale
						
						LEFT OUTER JOIN `%3\$s` AS `t8` ON t8.model=:pjListing AND t8.foreign_id=t1.id AND t8.field=:title AND t8.locale=:locale
						
						LEFT OUTER JOIN `%4\$s` AS `t9` ON t9.id = t1.owner_id
						LEFT OUTER JOIN `%4\$s` AS `t10` ON t10.id = :user_id
						
						WHERE t1.id = :id
						LIMIT 1",
						pjListingModel::factory()->getTable(), pjNotificationModel::factory()->getTable(),
						pjMultiLangModel::factory()->getTable(), pjUserModel::factory()->getTable()
					);
					
					$arr = $pjEnquiryModel
						->reset()
						->prepare($statement)
						->exec(array(
							'pjNotification' => 'pjNotification',
							'pjListing' => 'pjListing',
							'confirm_subject' => 'confirm_subject',
							'confirm_message' => 'confirm_message',
							'title' => 'title',
							'locale' => $this->getLocaleId(),
							'id' => $data['listing_id'],
							'user_id' => 1
						))
						->getDataIndex(0);
					
					if ($arr !== FALSE)
					{
						$from = !empty($this->option_arr['o_email_address']) ? $this->option_arr['o_email_address'] : $arr['admin_email'];
						if (!empty($arr['owner_id']) && !empty($arr['owner_email']))
						{
							$to = $arr['owner_email'];
						} else {
							$to = $from;
						}
						
						if (!empty($arr['owner_subject']))
						{
							$subject = $arr['owner_subject'];
							$message = $arr['owner_message'];
						} else {
							$subject = $arr['admin_subject'];
							$message = $arr['admin_message'];
						}
						
						$message = str_replace(
							array(
								'{OwnerName}',
								'{FullName}',
								'{Email}',
								'{Phone}',
								'{Notes}',
								'{StartDate}',
								'{EndDate}',
								'{ListingID}',
								'{ListingTitle}',
								'{EnquiryID}'),
							array(
								$arr['owner_name'],
								$_POST['name'],
								$_POST['email'],
								$_POST['phone'],
								$_POST['notes'],
								$_POST['date_from'],
								$_POST['date_to'],
								$arr['listing_refid'],
								$arr['listing_title'],
								$id
							),
							$message
						);
					
						$pjEmail = new pjEmail();
						if ($this->option_arr['o_send_email'] == 'smtp'
							&& !empty($this->option_arr['o_smtp_host'])
							&& !empty($this->option_arr['o_smtp_port'])
							&& !empty($this->option_arr['o_smtp_user'])
							&& !empty($this->option_arr['o_smtp_pass'])
						)
						{
							$pjEmail
								->setTransport('smtp')
								->setSmtpHost($this->option_arr['o_smtp_host'])
								->setSmtpPort($this->option_arr['o_smtp_port'])
								->setSmtpUser($this->option_arr['o_smtp_user'])
								->setSmtpPass($this->option_arr['o_smtp_pass'])
							;
						}
						$pjEmail
							->setFrom($from)
							->setTo($to)
							->setSubject($subject)
							->send($message);
					}
					
					pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Enquiry have been sent.'));
				}
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 103, 'text' => 'Enquiry have not been sent.'));
			}
			pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 104, 'text' => 'Missing parameters.'));
		}
		exit;
	}
	
	public function pjActionComment()
	{
		$this->setAjax(true);
	
		if ($this->isXHR())
		{
			if (!isset($_POST['captcha'])
				|| empty($_POST['captcha'])
				|| !isset($_SESSION[$this->defaultCommentCaptcha])
				|| !pjCaptcha::validate($_POST['captcha'], $_SESSION[$this->defaultCommentCaptcha]))
			{
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Captcha does not match.'));
			}
			
			if (isset($_POST['comment_form']))
			{
				$pjCommentModel = pjCommentModel::factory();
				
				$required = array('listing_id', 'name', 'email', 'title', 'comment');
				if (!$pjCommentModel->validateRequest($required, $_POST))
				{
					pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'Missing parameters.'));
				}
				
				$data = array();
				$data['status'] = $this->option_arr['o_comment_default_status'];
				$data = array_merge($_POST, $data);
				
				if (!$pjCommentModel->validates($data))
				{
					pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 102, 'text' => 'Invalid parameters.'));
				}
				
				$id = $pjCommentModel
					->setAttributes($data)
					->insert()
					->getInsertId();
					
				if ($id !== FALSE && (int) $id > 0)
				{
					$_SESSION[$this->defaultCommentCaptcha] = NULL;
					unset($_SESSION[$this->defaultCommentCaptcha]);
					
					pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Comment have been posted.'));
				}
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 103, 'text' => 'Comment have not been posted.'));
			}
			pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 104, 'text' => 'Missing parameters.'));
		}
		exit;
	}
	
	public function pjActionGetComments()
	{
		$this->setAjax(true);
	
		if ($this->isXHR())
		{
			if (isset($_GET['id']) && (int) $_GET['id'] > 0)
			{
				$this->set('comment_arr', pjCommentModel::factory()
					->where('t1.status', 'Confirmed')
					->where('t1.listing_id', $_GET['id'])
					->orderBy('t1.created DESC')
					->findAll()
					->getData()
				);
			}
		}
	}
	
	public function pjActionHolidayPackages()
	{
		$pckg_m_title = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'pckg_m_title');
		$pckg_m_desc = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'pckg_m_desc');
		$this->set('meta_arr', array(
			'title' => $pckg_m_title['pckg_m_title'],
			'desc' => $pckg_m_desc['pckg_m_desc']
			)
		);
		$this->appendCss('jquery-ui.min.css', PJ_THIRD_PARTY_PATH . 'jquery_ui/css/smoothness/');
		$this->appendJs('jquery-ui.custom.min.js', PJ_THIRD_PARTY_PATH . 'jquery_ui/js/');
		$this->appendJs('pjWebSuggest.js');
		$this->appendJs('pjWebSearch.js');
		
		$this->appendCss('pjWebForms.css');
		$this->appendCss('pjWebListings.css');
		$this->appendCss('pjWebMaps.css');
	}
	
	public function pjActionGetCount()
	{
		$this->setAjax(true);
	
		if ($this->isXHR())
		{
			if (isset($_GET['url']) && !empty($_GET['url']) && isset($_GET['vendor'])
				&& in_array($_GET['vendor'], array('twitter', 'facebook', 'google', 'linkedin')))
			{
				$url = $_GET['url'];
				
				$http = new pjHttp();
				switch ($_GET['vendor'])
				{
					case 'twitter':
						$http->request('http://urls.api.twitter.com/1/urls/count.json?url=' . $url);
						$response = $http->getResponse();
						$response = pjAppController::jsonDecode($response);
						if (isset($response->count))
						{
							$cnt = $response->count;
						}
						break;
					case 'facebook':
						$http->request('http://graph.facebook.com/?ids=' . $url);
						$response = $http->getResponse();
						$response = pjAppController::jsonDecode($response);
						if (isset($response->$url) && isset($response->$url->shares))
						{
							$cnt = $response->$url->shares;
						}
						break;
					case 'google':
						$data = array(
							'method' => 'pos.plusones.get',
						    'id' => 'p',
						    'params' => array(
						        'nolog' => true,
						        'id' => $url,
						        'source' => 'widget',
						        'userId' => '@viewer',
						        'groupId' => '@self'
						    ),
						    'jsonrpc' => '2.0',
						    'key' => 'p',
						    'apiVersion' => 'v1'
						);
						$data = pjAppController::jsonEncode($data);
						
						$http
							->setMethod('POST')
							->addHeader('Content-Type: application/json')
							->setData($data)
							->request('https://clients6.google.com/rpc');
							
						$response = $http->getResponse();
						$response = pjAppController::jsonDecode($response);
						if (isset($response->result) && isset($response->result->metadata) && isset($response->result->metadata->globalCounts) && isset($response->result->metadata->globalCounts->count))
						{
							$cnt = $response->result->metadata->globalCounts->count;
						}
						break;
					case 'linkedin':
						$http->request('http://www.linkedin.com/countserv/count/share?format=json&url=' . $url);
						$response = $http->getResponse();
						$response = pjAppController::jsonDecode($response);
						if (isset($response->count))
						{
							$cnt = $response->count;
						}
						break;
				}
				if (isset($cnt))
				{
					if ($cnt >= 1000000)
					{
						$cnt = sprintf("%sM", round($cnt / 1000000, 0));
					} elseif ($cnt >= 10000) {
						$cnt = sprintf("%sK", round($cnt / 1000, 0));
					} elseif ($cnt >= 1000) {
						$cnt = sprintf("%sK", round($cnt / 1000, 1));
					}
					pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => '', 'cnt' => $cnt));
				}
			}
			pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Missing, empty or invalid parameters.'));
		}
		exit;
	}
	
	public function pjActionListing()
	{
		if (!isset($_GET['id']) || (int) $_GET['id'] <= 0)
		{
			//TODO
		}
		
		$pjListingModel = pjListingModel::factory();
		
		$arr = $pjListingModel
			->select(sprintf("t1.*,
				t2.content AS `type_title`,
				t3.content AS `country_title`,
				t4.content AS `listing_title`,
				t5.content AS `listing_description`,
				t6.content AS `listing_terms`,
				t7.content AS `meta_title`,
				t8.content AS `meta_keywords`,
				t9.content AS `meta_description`,
				t10.content AS `flight_notes`,
				t11.content AS `checkin`,
				t12.content AS `checkout`,
				t13.content AS `pets`,
				t14.content AS `policies`,
				t15.content AS `fees`,
				(SELECT MIN(`price`)
					FROM `%1\$s` AS `TP1`
					WHERE TP1.listing_id = t1.id
					ORDER BY `id` ASC
					LIMIT 1) AS `min`,
				(SELECT MAX(`price`)
					FROM `%1\$s` AS `TP2`
					WHERE TP2.listing_id = t1.id
					ORDER BY `id` ASC
					LIMIT 1) AS `max`,
				(SELECT GROUP_CONCAT(TA.`month` SEPARATOR ',')
					FROM `%2\$s` AS `TA`
					WHERE TA.listing_id = t1.id
					ORDER BY `month` ASC) AS `avail`,
				(SELECT AVG(`rating`)
					FROM `%3\$s`
					WHERE `listing_id` = t1.id
					AND `status` = 'Confirmed'
					AND `rating` IS NOT NULL
					LIMIT 1) AS `avg_rating`,
				(SELECT COUNT(*)
					FROM `%3\$s`
					WHERE `listing_id` = t1.id
					AND `status` = 'Confirmed'
					AND `rating` IS NOT NULL
					LIMIT 1) AS `number_of_comments`
				", pjPriceModel::factory()->getTable(), pjListingAvailabilityModel::factory()->getTable(), pjCommentModel::factory()->getTable()
			))
			
			->join('pjMultiLang', sprintf("t2.model='pjType' AND t2.foreign_id=t1.type_id AND t2.field='name' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t3.model='pjCountry' AND t3.foreign_id=t1.country_id AND t3.field='name' AND t3.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t4.model='pjListing' AND t4.foreign_id=t1.id AND t4.field='title' AND t4.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t5.model='pjListing' AND t5.foreign_id=t1.id AND t5.field='description' AND t5.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t6.model='pjListing' AND t6.foreign_id=t1.id AND t6.field='terms' AND t6.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t7.model='pjListing' AND t7.foreign_id=t1.id AND t7.field='meta_title' AND t7.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t8.model='pjListing' AND t8.foreign_id=t1.id AND t8.field='meta_keywords' AND t8.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t9.model='pjListing' AND t9.foreign_id=t1.id AND t9.field='meta_description' AND t9.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t10.model='pjListing' AND t10.foreign_id=t1.id AND t10.field='flight_notes' AND t10.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t11.model='pjListing' AND t11.foreign_id=t1.id AND t11.field='checkin' AND t11.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t12.model='pjListing' AND t12.foreign_id=t1.id AND t12.field='checkout' AND t12.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t13.model='pjListing' AND t13.foreign_id=t1.id AND t13.field='pets' AND t13.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t14.model='pjListing' AND t14.foreign_id=t1.id AND t14.field='policies' AND t14.locale='%u'", $this->getLocaleId()), 'left outer')
			->join('pjMultiLang', sprintf("t15.model='pjListing' AND t15.foreign_id=t1.id AND t15.field='fees' AND t15.locale='%u'", $this->getLocaleId()), 'left outer')
			->where('t1.id', $_GET['id'])
			->where("(t1.status = 'T' OR (t1.status = 'E' AND t1.expire >= CURDATE()))")
			->limit(1)
			->findAll()
			->getDataIndex(0);
			
		if ($arr === FALSE || empty($arr))
		{
			//TODO
		}
		
		pjObject::import('Model', 'pjGallery:pjGallery');

		$pjListingModel->reset()->set('id', $arr['id'])->modify(array('views' => $arr['views'] + 1));
		
		$this->set('feature_arr', pjFeatureModel::factory()
			->select('t1.*, t2.content AS `feature_title`')
			->join('pjMultiLang', sprintf("t2.model='pjFeature' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
			->where('t1.status', 'T')
			->orderBy('`feature_title` ASC')
			->findAll()
			->getData()
		);
		
		$this->set('gallery_arr', pjGalleryModel::factory()
			->where('t1.foreign_id', $arr['id'])
			->orderBy('t1.sort ASC')
			->findAll()
			->getData()
		);
		$feature_ids = pjListingFeatureModel::factory()
			->where('t1.listing_id', $arr['id'])
			->findAll()
			->getDataPair(NULL, 'feature_id');
		
		$feature_arr = array();
		if (!empty($feature_ids))
		{
			$feature_arr = pjFeatureModel::factory()->select('t1.*, t2.content as feature_title')
				->join('pjMultiLang', sprintf("t2.model='pjFeature' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
				->whereIn('t1.id', $feature_ids)
				->findAll()
				->getData();
		}
		
		$this->set('price_arr', pjPriceModel::factory()
			->where('listing_id', $arr['id'])
			->orderBy('date_from ASC, date_to ASC')
			->findAll()
			->getData()
		);
		
		$this->set('listing_id', $arr['id']);
		
		$this->set('arr', $arr);
		$this->set('feature_arr', $feature_arr);
		
		$this->set('comment_arr', pjCommentModel::factory()
			->where('status', 'Confirmed')
			->where('listing_id', $arr['id'])
			->orderBy('created DESC')
			->findAll()
			->getData()
		);
		$this->set('meta_arr', array(
			'title' => $arr['listing_title'],
			'keywords' => $arr['meta_keywords'],
			'description' => $arr['meta_description']
		));
		
		if (!empty($arr['owner_id']))
		{
			$this->set('contact_arr', pjUserModel::factory()
				->find($arr['owner_id'])
				->getData());
		}
		
		$this->appendCss('owl.carousel.css', PJ_THIRD_PARTY_PATH . 'owl-carousel/');
		$this->appendCss('owl.theme.css', PJ_THIRD_PARTY_PATH . 'owl-carousel/');
		$this->appendJs('owl.carousel.min.js', PJ_THIRD_PARTY_PATH . 'owl-carousel/');
		
		$this->appendCss('jquery-ui.min.css', PJ_THIRD_PARTY_PATH . 'jquery_ui/css/smoothness/');
		$this->appendCss('pjWebForms.css');
		$this->appendCss('pjWebDetails.css');
		$this->appendCss('pjWebListings.css');
		$this->appendCss('pjWebMaps.css');
		
		$this->appendJs('jquery-ui.custom.min.js', PJ_THIRD_PARTY_PATH . 'jquery_ui/js/');
		$this->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/');
		$this->appendJs('pjWebForms.js');
		$this->appendJs('pjWebPages.js');
		$this->appendJs('pjWebDetails.js');
	}
	
	public function pjActionLocation()
	{
		$this->setAjax(true);
	
		if ($this->isXHR())
		{
			$items = array();
			
			if (isset($_GET['q']) && !empty($_GET['q']))
			{
				pjObject::import('Model', 'pjCountry:pjCountry');
				$pjListingModel = pjListingModel::factory();
				
				$q = $pjListingModel->escapeString($_GET['q']);
				$q = str_replace(array('%', '_'), array('\%', '\_'), trim($q));
				
				$c_arr = pjCountryModel::factory()
					->select("CONCAT(t1.id, '_country') AS `value`, t2.content AS `label`")
					->join('pjMultiLang', sprintf("t2.model='pjCountry' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
					->where('t1.status', 'T')
					->where(sprintf("t2.content LIKE '%s'", "%$q%"))
					->findAll()
					->getData();
				
				$d_arr = pjDestinationModel::factory()
					->select("CONCAT(t1.id, '_destination') AS `value`, CONCAT_WS(', ', t2.content, t3.content) AS `label`")
					->join('pjMultiLang', sprintf("t2.model='pjDestination' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
					->join('pjMultiLang', sprintf("t3.model='pjCountry' AND t3.foreign_id=t1.country_id AND t3.field='name' AND t3.locale='%u'", $this->getLocaleId()), 'left outer')
					->where('t1.status', 'T')
					->where(sprintf("(t2.content LIKE '%1\$s' OR t3.content LIKE '%1\$s')", "%$q%"))
					->findAll()
					->getData();
					
				$l_arr = $pjListingModel
					->select("CONCAT(t1.id, '_listing') AS `value`, CONCAT_WS(', ', t1.address_city, t1.address_state, t2.content) AS `label`")
					->join('pjMultiLang', sprintf("t2.model='pjCountry' AND t2.foreign_id=t1.country_id AND t2.field='name' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
					->where(sprintf("(t1.address_city LIKE '%1\$s' OR t1.address_state LIKE '%1\$s' OR t2.content LIKE '%1\$s')", "%$q%"))
					->findAll()
					->getData();
					
				$items = array_merge($c_arr, $d_arr, $l_arr);
			}
			
			pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => '', 'items' => $items));
		}
		exit;
	}
	
	public function pjActionForgot()
	{
		$forgot_m_title = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'forgot_m_title');
		$forgot_m_desc = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'forgot_m_desc');
		$this->set('meta_arr', array(
			'title' => $forgot_m_title['forgot_m_title'],
			'desc' => $forgot_m_desc['forgot_m_desc']
			)
		);
		if (isset($_POST['send_forgot']))
		{
			if ($this->option_arr['o_allow_add_package'] == 'No')
			{
				pjUtil::redirect(sprintf("%s%s/forgot/?err=WL01", PJ_INSTALL_URL, $this->getLanguage()));
			}
			if (!isset($_POST['email'])
				|| !pjValidation::pjActionNotEmpty($_POST['email'])
				|| !pjValidation::pjActionEmail($_POST['email'])
				)
			{
				pjUtil::redirect(sprintf("%s%s/forgot/?err=WF03", PJ_INSTALL_URL, $this->getLanguage()));
			}
			
			$user = pjUserModel::factory()
				->where('t1.email', $_POST['email'])
				->limit(1)
				->findAll()
				->getDataIndex(0);
				
			if ($user === FALSE)
			{
				pjUtil::redirect(sprintf("%s%s/forgot/?err=WF04", PJ_INSTALL_URL, $this->getLanguage()));
			}
			
			$arr = pjNotificationModel::factory()
				->select('t1.*, t2.content AS `forgot_subject`, t3.content AS `forgot_message`')
				->join('pjMultiLang', sprintf("t2.model='pjNotification' AND t2.foreign_id=t1.id AND t2.field='forgot_subject' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
				->join('pjMultiLang', sprintf("t3.model='pjNotification' AND t3.foreign_id=t1.id AND t3.field='forgot_message' AND t3.locale='%u'", $this->getLocaleId()), 'left outer')
				->find(1)
				->getData();
			if (empty($arr))
			{
				pjUtil::redirect(sprintf("%s%s/forgot/?err=WF05", PJ_INSTALL_URL, $this->getLanguage()));
			}
			
			$Email = new pjEmail();
			if ($this->option_arr['o_send_email'] == 'smtp')
			{
				$Email
					->setTransport('smtp')
					->setSmtpHost($this->option_arr['o_smtp_host'])
					->setSmtpPort($this->option_arr['o_smtp_port'])
					->setSmtpUser($this->option_arr['o_smtp_user'])
					->setSmtpPass($this->option_arr['o_smtp_pass'])
				;
			}

			$admin_email = $this->getFromEmail();
			
			$Email
				->setTo($user['email'])
				->setFrom($admin_email)
				->setReturnPath($admin_email)
				->setReplyTo($admin_email)
				->setSubject($arr['forgot_subject'])
			;
			$message = str_replace(
				array('{Password}'),
				array($user['password']),
				$arr['forgot_message']
			);
			$err = $Email->send($message) ? 'WF01' : 'WF02';
			
			pjUtil::redirect(sprintf("%s%s/forgot/?err=%s", PJ_INSTALL_URL, $this->getLanguage(), $err));
		}
		$this->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/');
		$this->appendJs('pjWebForms.js');
		$this->appendCss('pjWebPages.css');
		$this->appendCss('pjWebForms.css');
	}
	
	public function pjActionLogin()
	{
		$login_m_title = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'login_m_title');
		$login_m_desc = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'login_m_desc');
		$this->set('meta_arr', array(
			'title' => $login_m_title['login_m_title'],
			'desc' => $login_m_desc['login_m_desc']
			)
		);
		$this->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/');
		$this->appendJs('pjWebForms.js');
		$this->appendCss('pjWebPages.css');
		$this->appendCss('pjWebForms.css');
	}
	
	public function pjActionRegister()
	{
		$register_m_title = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'register_m_title');
		$register_m_desc = pjMultiLangModel::factory()->getSingleLang(1	, 'pjOption', 7, 'register_m_desc');
		$this->set('meta_arr', array(
			'title' => $register_m_title['register_m_title'],
			'desc' => $register_m_desc['register_m_desc']
			)
		);
		if (isset($_POST['send_register']))
		{
			if ($this->option_arr['o_allow_add_package'] == 'No')
			{
				pjUtil::redirect(sprintf("%s%s/register/?err=WL01", PJ_INSTALL_URL, $this->getLanguage()));
			}
			
			if (!isset($_POST['email'])
				|| !isset($_POST['name'])
				|| !isset($_POST['captcha'])
				|| !isset($_POST['password'])
				|| !isset($_POST['retype_password'])
				|| !isset($_SESSION[$this->defaultCaptcha])
				|| !pjValidation::pjActionNotEmpty($_POST['email'])
				|| !pjValidation::pjActionEmail($_POST['email'])
				|| !pjValidation::pjActionNotEmpty($_POST['name'])
				|| !pjValidation::pjActionNotEmpty($_POST['captcha'])
				|| !pjValidation::pjActionNotEmpty($_POST['password'])
				|| !pjValidation::pjActionNotEmpty($_POST['retype_password'])
				|| $_POST['password'] != $_POST['retype_password']
				|| !pjCaptcha::validate($_POST['captcha'], $_SESSION[$this->defaultCaptcha])
				)
			{
				$_SESSION[$this->defaultFormRegister] = $_POST;
				pjUtil::redirect(sprintf("%s%s/register/?err=WR03", PJ_INSTALL_URL, $this->getLanguage()));
			}
			
			$pjUserModel = pjUserModel::factory();
			$user = $pjUserModel
				->where('t1.email', $_POST['email'])
				->limit(1)
				->findAll()
				->getDataIndex(0);
				
			if ($user !== FALSE && !empty($user))
			{
				$_SESSION[$this->defaultFormRegister] = $_POST;
				pjUtil::redirect(sprintf("%s%s/register/?err=WR04", PJ_INSTALL_URL, $this->getLanguage()));
			}
			
			$data = array();
			$data['password'] = $_POST['password'];
			$data['email'] = $_POST['email'];
			$data['name'] = $_POST['name'];
			$data['role_id'] = 3;
			$data['is_active'] = 'F';
			$data['status'] = $this->option_arr['o_owner_is_active'] == 'Yes' ? 'T' : 'F';
			$data['ip'] = pjUtil::getClientIp();
			
			$user_id = $pjUserModel
				->reset()
				->setAttributes($data)
				->insert()
				->getInsertId();
				
			if ($user_id === FALSE || (int) $user_id <= 0)
			{
				$_SESSION[$this->defaultFormRegister] = $_POST;
				pjUtil::redirect(sprintf("%s%s/register/?err=WR05", PJ_INSTALL_URL, $this->getLanguage()));
			}
			
			if (isset($_SESSION[$this->defaultFormRegister]))
			{
				$_SESSION[$this->defaultFormRegister] = NULL;
				unset($_SESSION[$this->defaultFormRegister]);
			}
			
			$arr = pjNotificationModel::factory()
				->select('t1.*, t2.content AS `new_account_subject`, t3.content AS `new_account_message`')
				->join('pjMultiLang', sprintf("t2.model='pjNotification' AND t2.foreign_id=t1.id AND t2.field='new_account_subject' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
				->join('pjMultiLang', sprintf("t3.model='pjNotification' AND t3.foreign_id=t1.id AND t3.field='new_account_message' AND t3.locale='%u'", $this->getLocaleId()), 'left outer')
				->find(1)
				->getData();
			if (empty($arr))
			{
				pjUtil::redirect(sprintf("%s%s/register/?err=WR06", PJ_INSTALL_URL, $this->getLanguage()));
			}

			$Email = new pjEmail();
			if ($this->option_arr['o_send_email'] == 'smtp')
			{
				$Email
					->setTransport('smtp')
					->setSmtpHost($this->option_arr['o_smtp_host'])
					->setSmtpPort($this->option_arr['o_smtp_port'])
					->setSmtpUser($this->option_arr['o_smtp_user'])
					->setSmtpPass($this->option_arr['o_smtp_pass'])
				;
			}

			$admin_email = $this->getFromEmail();
			
			$Email
				->setTo($admin_email)
				->setFrom($admin_email)
				->setReturnPath($admin_email)
				->setReplyTo($data['email'])
				->setSubject($arr['new_account_subject'])
			;
			$message = str_replace(
				array('{Name}', '{Email}'),
				array($data['name'], $data['email']),
				$arr['new_account_message']
			);
			$err = $Email->send($message) ? 'WR01' : 'WR02';
			
			pjUtil::redirect(sprintf("%s%s/register/?err=%s", PJ_INSTALL_URL, $this->getLanguage(), $err));
		}
		$this->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/');
		$this->appendJs('pjWebForms.js');
		$this->appendCss('pjWebPages.css');
		$this->appendCss('pjWebForms.css');
	}
	
	public function pjActionPage()
	{
		if (isset($_GET['seo_url']) && !empty($_GET['seo_url']))
		{
			$arr = $this->__getPage(null, $_GET['seo_url']);
			if ($arr === FALSE || empty($arr) || $arr['status'] == 'F')
			{
				pjWeb::pjActionNotFound();
			}
			$this->set('arr', $arr);
			$this->set('meta_arr', array(
				'title' => @$arr['meta_title'],
				'desc' => @$arr['meta_desc'])
			);
			switch ((int) $arr['id'])
			{
				case 1:
					$this->setTemplate('pjWebPages', 'pjActionAbout');
					$this->appendCss('pjWebForms.css');
					$this->appendCss('pjWebPages.css');
					$this->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/');
					$this->appendJs('pjWebForms.js');
					break;
				case 2:
					$this->set('dest_arr', pjDestinationModel::factory()
						->select('t1.*, t2.content AS `name`, t3.content AS `country`')
						->join('pjMultiLang', sprintf("t2.model='pjDestination' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
						->join('pjMultiLang', sprintf("t3.model='pjCountry' AND t3.foreign_id=t1.country_id AND t3.field='name' AND t3.locale='%u'", $this->getLocaleId()), 'left outer')
						->where('t1.status', 'T')
						->orderBy('`name` ASC')
						->findAll()
						->getData()
					);
					
					$this->setTemplate('pjWebPages', 'pjActionDestinations');
					$this->appendCss('pjWebPages.css');
					$this->appendJs('pjWebPages.js');
					break;
				case 3:
					$this->setTemplate('pjWebPages', 'pjActionTerms');
					$this->appendCss('pjWebForms.css');
					$this->appendCss('pjWebPages.css');
					$this->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/');
					$this->appendJs('pjWebForms.js');
					break;
			}
		}
	}
	
	public function pjActionSearch()
	{
		$this->setAjax(true);

		if ($this->isXHR())
		{
			$pjListingModel = pjListingModel::factory()
				->join('pjMultiLang', sprintf(
					"t2.model='pjListing' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='%u'",
					$this->getLocaleId()
				), 'left outer')
				->join('pjMultiLang', sprintf(
					"t3.model='pjListing' AND t3.foreign_id=t1.id AND t3.field='description' AND t3.locale='%u'",
					$this->getLocaleId()
				), 'left outer')
				->join('pjMultiLang', sprintf(
					"t4.model='pjCountry' AND t4.foreign_id=t1.country_id AND t4.field='name' AND t4.locale='%u'",
					$this->getLocaleId()
				), 'left outer');
		
			$pjListingModel->where("(t1.status = 'T' OR (t1.status = 'E' AND t1.expire >= CURDATE()))");
				
			if (isset($_GET['is_best_deal']) && in_array($_GET['is_best_deal'], array('1,2')))
			{
				$pjListingModel->where("t1.is_best_deal != '0'");
			} else {
				if (isset($_GET['season']) && is_array($_GET['season']) && !empty($_GET['season']))
				{
					$s = array();
					foreach ($_GET['season'] as $season)
					{
						$s[] = sprintf(
							"(t1.listing_season REGEXP '^%1\$u\\\||\\\|%1\$u\\\||\\\|%1\$u$' OR t1.listing_season='%1\$u')",
							(int) $season
						);
					}
					$pjListingModel->where('('.join(" OR ", $s).')');
				}
				if (isset($_GET['type']) && is_array($_GET['type']) && !empty($_GET['type']))
				{
					$pjListingModel->whereIn('t1.type_id', array_map('intval', $_GET['type']));
				}
				if (isset($_GET['rating_from']) && (int) $_GET['rating_from'] > 0
					&& isset($_GET['rating_to']) && (int) $_GET['rating_to'] > 0)
				{
					if ($_GET['rating_from'] != $_GET['rating_to'])
					{
						$pjListingModel->where(sprintf(
							"(t1.listing_rating BETWEEN '%u' AND '%u')",
							(int) $_GET['rating_from'],
							(int) $_GET['rating_to']
						));
					} else {
						$pjListingModel->where('t1.listing_rating', (int) $_GET['rating_from']);
					}
				}
				if (isset($_GET['price_from']) && (int) $_GET['price_from'] >= 0
					&& isset($_GET['price_to']) && (int) $_GET['price_to'] >= 0)
				{
					$pjListingModel->where(sprintf(
						"t1.id IN (SELECT TP.listing_id FROM `%s` AS `TP` WHERE TP.price BETWEEN '%u' AND '%u')",
						pjPriceModel::factory()->getTable(),
						(int) $_GET['price_from'],
						(int) $_GET['price_to']
					));
				} else {
					if (isset($_GET['price_from']) && (int) $_GET['price_from'] >= 0)
					{
						$pjListingModel->where(sprintf(
							"t1.id IN (SELECT TP.listing_id FROM `%s` AS `TP` WHERE TP.price >= '%u')",
							pjPriceModel::factory()->getTable(),
							(int) $_GET['price_from']
						));
					} elseif (isset($_GET['price_to']) && (int) $_GET['price_to'] >= 0) {
						$pjListingModel->where(sprintf(
							"t1.id IN (SELECT TP.listing_id FROM `%s` AS `TP` WHERE TP.price <= '%u')",
							pjPriceModel::factory()->getTable(),
							(int) $_GET['price_to']
						));
					}
				}
				if (isset($_GET['q']) && !empty($_GET['q']))
				{
					$q = $pjListingModel->escapeString($_GET['q']);
					$q = str_replace(array('%', '_'), array('\%', '\_'), trim($q));
					$pjListingModel->where(sprintf("(t1.address_city LIKE '%1\$s' OR t4.content LIKE '%1\$s')", "%$q%"));
				}
			}
				
			$column = 'id';
			$direction = 'DESC';
			/*if (isset($_GET['direction']) && isset($_GET['column']) && in_array(strtoupper($_GET['direction']), array('ASC', 'DESC')))
			{
				$column = $_GET['column'];
				$direction = strtoupper($_GET['direction']);
			}*/
			
			if (!isset($_GET['json']))
			{
				$total = $pjListingModel->findCount()->getData();
				$rowCount = isset($_GET['row_count']) && (int) $_GET['row_count'] > 0 ? (int) $_GET['row_count'] : $this->getDefaultItemPerPage();
				$pages = ceil($total / $rowCount);
				$page = isset($_GET['page']) && (int) $_GET['page'] > 0 && (int) $_GET['page'] <= $pages ? (int) $_GET['page'] : 1;
				$offset = ((int) $page - 1) * $rowCount;
				if ($page > $pages)
				{
					$page = $pages;
				}
				$pjListingModel->limit($rowCount, $offset);
			}
			
			pjObject::import('Model', 'pjGallery:pjGallery');
			
			$arr = $pjListingModel
				->select(sprintf("t1.*, t2.content AS `listing_title`, t3.content AS `listing_description`, t4.content AS `country_title`,
					(SELECT MIN(`price`) FROM `%1\$s` WHERE `listing_id` = t1.id ORDER BY `id` ASC LIMIT 1) AS `min`,
					(SELECT MAX(`price`) FROM `%1\$s` WHERE `listing_id` = t1.id ORDER BY `id` ASC LIMIT 1) AS `max`,
					(SELECT AVG(`rating`) FROM `%2\$s` WHERE `listing_id` = t1.id AND `status` = 'Confirmed' AND `rating` IS NOT NULL) AS `avg_rating`,
					(SELECT COUNT(*) FROM `%2\$s` WHERE `listing_id` = t1.id AND `status` = 'Confirmed' AND `rating` IS NOT NULL) AS `number_of_comments`,
					(SELECT `medium_path` FROM `%3\$s` WHERE `foreign_id` = t1.id ORDER BY `sort` ASC LIMIT 1) AS `image`,
					(SELECT `large_path` FROM `%3\$s` WHERE `foreign_id` = t1.id ORDER BY `sort` ASC LIMIT 1) AS `large_image`
				", pjPriceModel::factory()->getTable(), pjCommentModel::factory()->getTable(), pjGalleryModel::factory()->getTable()))
				->orderBy("t1.is_featured DESC, $column $direction")
				->findAll()
				->getData();
			
			if (isset($_GET['json']))
			{
				$URL = PJ_INSTALL_URL . $this->getLanguage() . '/';
				foreach ($arr as $k => $v)
				{
					$arr[$k]['url'] = sprintf("%s%s-%u/", $URL, pjUtil::friendlyURL($v['listing_title']), $v['id']);
					$arr[$k]['price'] = 'n/a';
					if (!empty($v['max']) && !empty($v['min']))
					{
						if ($v['max'] != $v['min'])
						{
							$arr[$k]['price'] = pjUtil::formatCurrencySign(ceil($v['min']), $this->option_arr['o_currency']) . ' - ' . pjUtil::formatCurrencySign(ceil($v['max']), $this->option_arr['o_currency']);
						} else {
							$arr[$k]['price'] = pjUtil::formatCurrencySign(ceil($v['min']), $this->option_arr['o_currency']);
						}
					}
				}
				
				pjAppController::jsonResponse(array('data' => $arr, 'locale' => array(
					 'nights' => __('front_label_nights', true),
					 'night' => __('front_label_night', true),
					 'price' => __('front_label_price', true),
					 'flight' => __('front_label_flight_included', true),
					 'details' => __('front_label_details', true)
				)));
			}
				
			$this->set('arr', $arr);
			$this->set('paginator', compact('total', 'pages', 'page', 'rowCount', 'offset'));
			
			$filter = $this->__getFilter();
			
			$this->set('type_arr', $filter['type_arr']);
			$this->set('season_arr', $filter['season_arr']);
		}
	}
	
	public function pjActionSubscribe()
	{
		$this->setAjax(true);
	
		if ($this->isXHR())
		{
			if (!isset($_POST['subscriber_email']) || empty($_POST['subscriber_email']) || !pjValidation::pjActionEmail($_POST['subscriber_email']))
			{
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Missing, empty or invalid parameters.'));
			}
			
			$pjSubscriptionModel = pjSubscriptionModel::factory();
			$arr = $pjSubscriptionModel
				->where('t1.email', $_POST['subscriber_email'])
				->limit(1)
				->findAll()
				->getDataIndex(0);
				
			if ($arr === FALSE)
			{
				$id = $pjSubscriptionModel
					->reset()
					->setAttributes(array(
						'email' => $_POST['subscriber_email'],
						'is_subscribed' => 'T',
						'date_subscr' => ':CURDATE()'
					))
					->insert()
					->getInsertId();
				if ($id !== FALSE && (int) $id > 0)
				{
					pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'You have been subscribed.'));
				}
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'You have not been subscribed.'));
			}
			
			if ($arr['is_subscribed'] == 'F')
			{
				$result = $pjSubscriptionModel
					->modify(array(
						'is_subscribed' => 'T',
						'date_subscr' => ':CURDATE()'
					))
					->getAffectedRows();
					
				if ($result == 1)
				{
					pjAppController::jsonResponse(array('status' => 'OK', 'code' => 201, 'text' => 'You have been subscribed.'));
				}
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 102, 'text' => 'You have not been subscribed.'));
			}
			
			if ($arr['is_subscribed'] == 'T')
			{
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 103, 'text' => 'You are already subscribed.'));
			}
		}
		exit;
	}
}
?>