<?php
/*
* @package LabCMS
* @copyright (c) 2006 Alexander Levin aka Loki (loki_angel@mail.ru)
* @support http://labcms.ru
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/

class forum_main extends ModuleTools
{
	public $ajax_methods=array('subscribe_item', 'unsubscribe_item');
	protected $module;

	public function __construct()
	{
		if (!access('read')) return $this->error403();
		$this->module=Factory::create('forum.module');
		$forums=$this->module->getAllForums();
		$this->_assign('forums', $forums['collection']);
	}

	//форумы
	public function forums()
	{
		$this->_setTpl('forums');
		$this->_setTitle();
	}

	public function add_forum()
	{
		if (!access('admin')) return $this->error403();
		$form=$this->module->getEditForumForm();

		if ($form->validate()) {
			$this->module->addForum($form->getValue());
			refresh();
		}
		
		$this->_assign('form', $this->_renderForm($form));
		$this->_setTpl('form');
		
		$this->_setTitle(null, null, null, array(_m("Cоздание нового форума"), _url(false, 'add_forum')));
	}

	public function edit_forum()
	{
		if (!access('admin')) return $this->error403();
		if (!$forum=$this->module->getForumById($_GET['var1'])) return $this->_error(_m('Форум не найден!'));
		
		$form=$this->module->getEditForumForm($forum);
		
		if ($form->validate()) {
			$this->module->updateForum($forum, $form->getValue());
			refresh();
		}
		
		$this->_assign('form', $this->_renderForm($form));
		$this->_setTpl('form');
		
		$this->_setTitle($forum, null, null, array(_m("Редактирование форума"), _url($forum->id, 'edit_forum')));
	}

	public function delete_forum()
	{
		if (!access('admin')) return $this->error403();
		User::checkToken($_GET['token']);
		if (!$forum=$this->module->getForumById($_GET['var1'])) return $this->_error(_m('Форум не найден!'));
		$this->module->deleteForum($forum);
		refresh();
	}

	//темы
	public function themes()
	{
		if (!$forum=$this->module->getForumById($_GET['var1'])) return $this->_error(_m('Форум не найден!'));
		if ($forum->closed && !access('read_closed')) return $this->error403();
		if (isset($_GET['data_type']) && $_GET['data_type']=='xml') return $this->_themes_xml($forum);
		$page=isset($_GET['var2'])?$_GET['var2']:1;

		$themes=$this->module->getThemesByForum($forum, $page, config::get('forum_themes_at_page'));

		if ($themes['count']) {
			$this->_assign('themes', $themes['collection']);
			$this->_assign('pager', $this->module->getPager($themes['count'], $page, config::get('forum_themes_at_page')));
		}

		$this->_setTpl('themes');
		$this->_assign('forum', $forum);
		$this->_setTitle($forum);
	}

	protected function _themes_xml($forum)
	{
	
		$this->_setTpl('string:{$xml}', true);
		LabVars::$break=true;
		LabVars::$forceDisplay=true;

		//sendXmlHeaders();
		if (LabCMS::i()->is_cached('string:{$xml}', 10*60, 'themes'.$forum->id)) return;

		$themes=$this->module->getThemesByForum($forum, 1, 50);

		$rss=array('title'=>'Последние темы форума - '.htmlspecialchars($forum->name).' - '.config::get('core.site_name'),
							'link'=>config::get('core.siteUrl')._url(),
							'description'=>"Последние темы в форуме ".config::get('core.site_name'));

		foreach ($themes['collection'] as $theme) {
			$rss['feed'][]=array('title'=>htmlspecialchars($theme->subject),
								'description'=>"Последний ответ: "
								.date("d/m/Y H:i", $theme->last_post_date)
								.' ('.htmlspecialchars($theme->last_user->login).')'
								."<br />Всего ответов: ".$theme->total_posts,
								'link'=>config::get('core.siteUrl')._url(array($theme->id, $theme->total_pages), 'theme')
								.'#last',
								'pubDate'=>$theme->last_post);
		}

		$xml=genereteFeed($rss);
		$this->_assign('xml', $xml);
	}

	public function hidden_themes()
	{
		if (!access('admin')) return $this->error403();
		$page=isset($_GET['var2'])?$_GET['var2']:1;

		$themes=$this->module->getThemesByHidden($page, config::get('forum_themes_at_page'));

		if ($themes['count']) {
			$this->_assign('themes', $themes['collection']);
			$this->_assign('pager', $this->module->getPager($themes['count'], $page, config::get('forum_themes_at_page')));
		}
		$this->_setTpl('themes');
		
		$this->_setTitle(null, null, null, array(_m('Скрытые темы'), _url(null, 'hidden_themes')));
	}

	public function user_themes()
	{
		$user=User::getUser($_GET['var1']);
		if ($user->isGuest()) return $this->_error(_m('Пользователь не найден'));
		$page=isset($_GET['var2'])?$_GET['var2']:1;

		$themes=$this->module->getThemesByUser($user, $page, config::get('forum_themes_at_page'));
		
		$this->_setTpl('themes');
		
		if ($themes['count']) {
			$this->_assign('themes', $themes['collection']);
			$this->_assign('pager', $this->module->getPager($themes['count'], $page, config::get('forum_themes_at_page')));
		}
		
		$this->_setTitle(
			null, null, null, array(sprintf(_m('Темы пользователя %s'), $user->login), _url($user->id, 'user_themes'))
		);
	}

	public function search()
	{
		if (!$_GET['search']) $_GET['search']=$_GET['var3'];
		if (!empty($_GET['var1'])) {
			if (!$forum=$this->module->getForumById($_GET['var1'])) return $this->_error(_m('Форум не найден!'));
		} else $forum=null;

		$page=isset($_GET['var2'])?$_GET['var2']:1;

		$themes=$this->module->getThemesByString($_GET['search'], $forum, $page, config::get('forum_themes_at_page'));

		if ($themes['count']) {
			$this->_assign('themes', $themes['collection']);
			$this->_assign('pager', $this->module->getPager($themes['count'], $page, config::get('forum_themes_at_page')));
		}

		$this->_setTpl('themes');
		$this->_assign('forum', $forum);
	}

	public function add_theme()
	{
		if (!access('add')) return $this->error403();
		if (!$forum=$this->module->getForumById($_GET['var1'])) return $this->_error(_m('Форум не найден!'));
		if ($forum->closed && !access('add_closed')) return $this->error403();
		
		$form=$this->module->getAddThemeForm();
		
		//если незарегистрированный пользователь - вводим дополнительные проверки
		if (User::i()->isGuest()) $this->_botOborCheck($form);

		if ($form->validate()) {
			$data=$form->getValue();
			if (User::i()->isNotGuest()) $data['user']=User::i()->getCurrentUser();
			else $data['user']=User::getUser();
			$data['forum']=$forum;

			if ($theme=$this->module->addTheme($data)) {
				refresh('', _url($theme->id, 'theme'));
			}
		}
		$this->_assign('form', $this->_renderForm($form));
		$this->_setTpl('edit_post');
		
		$this->_setTitle($forum, null, null, array(_m('Добавление темы'), _url($forum->id, 'add_theme')));
	}

	public function toggle()
	{
		if (!access('moderator')) return $this->error403();
		User::checkToken($_GET['token']);
		if (!$theme=$this->module->getThemeById($_GET['var1'])) return $this->_error(_m('Тема не найдена!'));
		$this->module->toggleTheme($theme);
		
		if ($_GET['redirect']) $url=$_GET['redirect'];
		else $url=_url($theme->id, 'theme');
		refresh('', $url);
	}

	public function delete_theme()
	{
		if (!access('admin')) return $this->error403();
		User::checkToken($_GET['token']);
		if (!$theme=$this->module->getThemeById($_GET['var1'])) return $this->_error(_m('Тема не найдена!'));

		if ($this->module->deleteTheme($theme)) {
			if ($_GET['redirect']) $url=$_GET['redirect'];
			else $url=_url($theme->forum->id);
			refresh('', $url);
		}
	}

	public function hide_theme()
	{
		if (!access('moderator')) return $this->error403();
		User::checkToken($_GET['token']);
		if (!$theme=$this->module->getThemeById($_GET['var1'])) return $this->_error(_m('Тема не найдена!'));
		$this->module->hideTheme($theme);
		
		if ($_GET['redirect']) $url=$_GET['redirect'];
		else $url=_url($theme->forum->id, 'forum');
		refresh('', $url);

	}

	public function unhide_theme()
	{
		if (!access('admin')) return $this->error403();
		User::checkToken($_GET['token']);
		if (!$theme=$this->module->getThemeById($_GET['var1'])) return $this->_error(_m('Тема не найдена!'));
		$this->module->unhideTheme($theme);
		
		if ($_GET['redirect']) $url=$_GET['redirect'];
		else $url=_url($theme->forum_id, 'forum');
		refresh('', $url);
	}

	//посты
	public function theme()
	{
		if (!$theme=$this->module->getThemeById($_GET['var1'])) return $this->_error(_m('Тема не найдена!'));
		if ($theme->forum->closed && !access('read_closed')) return $this->error403();
		if (isset($_GET['data_type']) && $_GET['data_type']=='xml') return $this->_theme_xml($theme);
		$page=isset($_GET['var2'])?$_GET['var2']:1;

		$posts=$this->module->getPostsByTheme($theme, $page, config::get('forum_posts_at_page'));

		if (config::get('rating_enable')) {
			$voter=Rating_Generic::init();
			$this->_assign('post_votes', $voter->getUserItemVotes(array_keys($posts), $this->module->getVoteType()));
		}

		if (User::i()->isNotGuest()) {
			$subscribe=Factory::create('Subscriber');
			$this->_assign('item_subscribed', $subscribe->getSubscribeStatus($theme->getSubsribeId()));
		}
		
		if ($posts['count']) {
			$this->_assign('posts', $posts['collection']);
			$this->_assign('pager', $this->module->getPager($posts['count'], $page, config::get('forum_posts_at_page')));
		}

		$this->_assign('theme', $theme);
		$this->_assign('forum', $theme->forum);
		$this->_setTpl('posts');
		$this->_setTitle($theme->forum, $theme);

		//помечаем тему как прочитанную
		$_SESSION['forum']['themes'][$theme->id]=true;
	}

	protected function _theme_xml($theme)
	{
		$this->_setTpl('string:{$xml}', true);
		LabVars::$break=true;
		LabVars::$forceDisplay=true;
		
		//sendXmlHeaders();
		if (LabCMS::i()->is_cached('string:{$xml}', 10*60, 'posts'.$theme->theme_id)) return;
		
		$posts=$this->module->getLastPostsOfTheme($theme, 1, 50);
		
		$rss=array('title'=>htmlspecialchars($theme->subject.' - '.config::get('core.site_name')),
							'link'=>config::get('core.siteUrl')._url($theme->id, 'theme'),
							'description'=>"Тема в форуме ".config::get('core.site_name'));
							
		foreach ($posts['collection'] as $key=>$post) {
			$rss['feed'][]=array('title'=>htmlspecialchars($post->user->login),
								'description'=>$post->msg_html,
								'link'=>config::get('core.siteUrl')._url(array($post->theme_id, $post->theme->total_pages), 'theme').'#p'.$post->id,
								'pubDate'=>$post->putdate);
		}
		
		$xml=genereteFeed($rss);
		$this->_assign('xml', $xml);
	}

	public function new_posts()
	{
		$this->_setTpl('string:{$xml}', true);
		LabVars::$break=true;
		LabVars::$forceDisplay=true;
		//sendXmlHeaders();
		if (LabCMS::i()->is_cached('string:{$xml}', 10*60, 'last_posts_'.access('read_closed'))) return;


		$posts=$this->module->getLastPosts(1, 50);

		$rss=array('title'=>'Последние сообщения - '.htmlspecialchars(config::get('core.site_name')),
							'link'=>config::get('core.siteUrl')._url(),
							'description'=>"Последние сообщения в форуме ".htmlspecialchars(config::get('core.domain')));

		foreach ($posts['collection'] as $post) {

			if (!access('read_closed') && $post->theme->forum->closed) continue;

			$rss['feed'][]=array('title'=>htmlspecialchars($post->theme->subject),
								'description'=>'<b>'.htmlspecialchars($post->user->login).'</b><br />'.$post->msg_html,
								'link'=>config::get('core.siteUrl')._url(array($post->theme->id, $post->theme->total_pages), 'theme').'#p'.$post->id,
								'pubDate'=>$post->putdate);
		}
		$xml=genereteFeed($rss);
		$this->_assign('xml', $xml);
	}

	
	public function hidden_posts()
	{
		if (!access('admin')) return $this->error403();
		$page=isset($_GET['var2'])?$_GET['var2']:1;
		$posts=$this->module->getPostsByHidden($page, config::get('forum_posts_at_page'));

		if ($posts['count']) {
			$this->_assign('posts', $posts['collection']);
			$this->_assign('pager', $this->module->getPager($posts['count'], $page, config::get('forum_posts_at_page')));
		}

		$this->_setTpl('posts');
		
		$this->_setTitle(null, null, null, array(_m('Скрытые сообщения'), _url(null, 'hidden_posts')));
	}

	
	public function user_posts()
	{
		$user=User::getUser($_GET['var1']);
		if ($user->isGuest()) return $this->_error(_m('Пользователь не найден'));
		$page=isset($_GET['var2'])?$_GET['var2']:1;
		$posts=$this->module->getPostsByUser($user, $page, config::get('forum_posts_at_page'));

		if (config::get('rating_enable')) {
			$voter=Rating_Generic::init();
			$this->_assign('post_votes', $voter->getUserItemVotes(array_keys($posts), $this->module->getVoteType()));
		}

		if ($posts['count']) {
			$this->_assign('posts', $posts['collection']);
			$this->_assign('pager', $this->module->getPager($posts['count'], $page, config::get('forum_posts_at_page')));
		}

		$this->_setTpl('posts');
		
		$this->_setTitle(
			null, null, null, array(sprintf(_m('Сообщения пользователя %s'), $user->login), _url(null, 'user_posts'))
		);
	}

	public function edit()
	{
		if (!$post=$this->module->getPostById($_GET['var1'])) return $this->_error(_m('Сообщение не найдено!'));
		if ($post->theme->forum->closed && !access('read_closed')) return $this->error403();
		if (!($post->isAuthor() && access('delete')) && !access('admin')) return $this->error403();

		$form=$this->module->getEditPostForm($post);
		if ($form->validate()) {
			$this->module->updatePost($post, $form->getValue());
			refresh('', _url(array($post->theme_id, $post->theme->total_pages), 'theme').'#p'.$post->id);
		}
		$this->_assign('form', $this->_renderForm($form));
		$this->_assign('post', $post);
		$this->_assign('theme', $post->theme);
		$this->_assign('forum', $post->theme->forum);
		
		$this->_setTpl('edit_post');
		
		$this->_setTitle($post->theme->forum, $post->theme, $post, array(_m('Редактирование'), _url($post->id, 'edit')));
	}

	
	public function post()
	{
		if (!$post=$this->module->getPostById($_GET['var1'])) return $this->_error(_m('Сообщение не найдено!'));
		if ($post->theme->forum->closed && !access('read_closed')) return $this->error403();
		
		$this->_assign('post', $post);
		$this->_assign('theme', $post->theme);
		$this->_assign('forum', $post->theme->forum);
		
		$this->_setTpl('post');
		
		$this->_setTitle($post->theme->forum, $post->theme, $post);
	}

	public function reply($quote=false)
	{
		if (!access('add')) return $this->error403();
		if (!$post=$this->module->getPostById($_GET['var1'])) return $this->_error(_m('Сообщение не найдено!'));
		if ($post->theme->forum->closed && !access('add_closed')) return $this->error403();

		if ($quote) $form=$this->module->getAddPostFormQuote($post);
		else $form=$this->module->getEditPostForm();
		
		//если незарегистрированный пользователь - вводим дополнительные проверки
		if (User::i()->isGuest()) $this->_botOborCheck($form);
		
		if ($form->validate()) {
			$data=$form->getValue();
			if (User::i()->isNotGuest()) $data['user']=User::i()->getCurrentUser();
			else $data['user']=User::getUser();

			$data['theme']=$post->theme;

			if ($post=$this->module->addPost($data)) {
				refresh('', _url(array($post->theme->id, $post->theme->total_pages), 'theme').'#p'.$post->id);
			}
		}
		
		$this->_assign('form', $this->_renderForm($form));
		$this->_assign('theme', $post->theme);
		$this->_assign('forum', $post->theme->forum);
		$this->_assign('reply', $post);
		$this->_setTpl('edit_post');
		$this->_setTitle($post->theme->forum, $post->theme, $post, array(_m('Ответ'), _url($post->id, 'reply')));
	}

	public function quote()
	{
		$this->reply(true);
	}

	public function delete()
	{
		User::checkToken();
		if (!$post=$this->module->getPostById($_GET['var1'])) return $this->_error(_m('Сообщение не найдено!'));
		if (!($post->isAuthor() && access('delete')) && !access('admin')) return $this->error403();
		if ($post->first) return $this->_error(_m('Нельзя удалять первое сообщение ветки'));
		
		if ($_GET['redirect']) $url=$_GET['redirect'];
		else $url=_url(array($post->theme_id), 'theme');
		
		$this->module->deletePost($post);
		
		refresh('', $url);
	}

	public function hide_post()
	{
		User::checkToken();
		if (!access('moderator')) return $this->error403();
		if (!$post=$this->module->getPostById($_GET['var1'])) return $this->_error(_m('Сообщение не найдено!'));
		if ($post->first) return $this->_error(_m('Нельзя удалять первое сообщение ветки'));
		$this->module->hidePost($post);
		
		if ($_GET['redirect']) $url=$_GET['redirect'];
		else $url=_url(array($post->theme_id), 'theme');
		refresh('', $url);
	}
	
	public function unhide_post()
	{
		User::checkToken();
		if (!access('admin')) return $this->error403();
		if (!$post=$this->module->getPostById($_GET['var1'])) return $this->_error(_m('Сообщение не найдено!'));
		$this->module->unhidePost($post);
		
		if ($_GET['redirect']) $url=$_GET['redirect'];
		else $url=_url(array($post->theme_id), 'theme');
		refresh('', $url);
	}


	public function extract()
	{
		if (!access('moderator')) return $this->error403();
		if (!$post=$this->module->getPostById($_GET['var1'])) return $this->_error(_m('Сообщение не найдено!'));

		$form=$this->module->getExtractForm();
		
		if ($form->validate()) {
			if ($new_theme=$this->module->extractTheme($form->getValue(), $post)) {
				refresh('', _url($new_theme->id, 'theme'));
			}
		}
		
		$this->_assign('form', $this->_renderForm($form));
		$this->_setTpl('form');
	}


	public function vote()
	{
		if (!$post=$this->module->getPostById($_POST['item_id'])) return $this->_json_error(_m('Сообщение не найдено!'));
		if ($post->theme->forum->closed && !access('read_closed')) $this->_json_error(_m('Нет доступа'));
		if ($post->hidden || $post->theme->hidden) $this->_json_error(_m('Нет доступа'));

		if ($data=$this->module->votePost($post, $_POST['vote'], $this->vote_type)) {
			echo real_json_encode(
				array(
					'total_votes'=>$post->total_votes,
					'vote_result'=>$post->vote_result,
					'rating'=>$post->rating
				)
			);
		} else {
			$this->_json_error(LabCMS::i()->errors[0]);
		}
		exit;
	}

	protected function _json_error($msg)
	{
		echo real_json_encode(array('error'=>$msg));
		exit;
	}

	public function ajax()
	{
		if (!in_array($_POST['action'], $this->ajax_methods))
			$this->_json_error(_m('Метод не найден'));
		if (User::i()->isGuest()) $this->_json_error(_m('Доступ запрещен'));
		$method='_json_'.$_POST['action'];
		$result=$this->$method();
		echo real_json_encode($result);
		exit;
	}
	
	protected function _json_subscribe_item()
	{
		if (!$theme=$this->module->getThemeById($_POST['item_id'])) return $this->_json_error(_m('Тема не найдена'));
		$subsctiber=Factory::create('Subscriber');
		$subsctiber->subscribe($theme->getSubsribeId());
		return array('ok'=>1);
	}
	
	protected function _json_unsubscribe_item()
	{
		if (!$theme=$this->module->getThemeById($_POST['item_id'])) return $this->_json_error(_m('Тема не найдена'));
		$subsctiber=Factory::create('Subscriber');
		$subsctiber->unsubscribe($theme->getSubsribeId());
		return array('ok'=>1);
	}

	protected function _botOborCheck($form)
	{
		if ($form->isSubmitted()) {
			if (Botobor_Keeper::get()->isRobot()) {
				die('злобный бот!');
			}
			//после восстановления полей снова передаем данные в обработчик формы
			$form->setDatasources(array(Factory::create('HTML_QuickForm2_DataSource_SuperGlobal')));
		}
	}

	protected function error403()
	{
		return LabCMS::i()->error403();
	}

	protected function _setTitle($forum=null, $theme=null, $post=null, $data=null)
	{
		$title[]=config::get('core.title');

		if ($forum) {
			$title[]=$forum->name;
			addBreadcrumb(
				$forum->name,
				_url($forum->id)
			);
		}
		
		if ($theme) {
			$title[]=$theme->subject;
			addBreadcrumb(
				$theme->subject,
				_url(array($theme->id,1), 'theme')
			);
		}

		if ($post) {
			$title[]='#'.$post->id;
			addBreadcrumb(
				'#'.$post->id,
				_url($post->id, 'post'),
				true
			);
		}
		
		if ($data) {
			$title[]=$data[0];
			addBreadcrumb(
				$data[0],
				$data[1]
			);
		}
		$title=array_reverse($title);	
		$title=implode(' / ', $title);
		config::set('core.title', $title);
		
		//добавляем вывод rss фидов
		Tpl::i()->append(
			'feed_rss',
			array(
				'path'=>_url(false, 'new_posts', 'xml'),
				'name'=>_m('Новые сообещния форума').' '.config::get('core.site_name')
			)
		);
		if (is_object($forum) && $forum->id) {
			Tpl::i()->append(
				'feed_rss',
				array(
					'path'=>_url($forum->id, false, 'xml'),
					'name'=>'Форум '.$forum->name.' - '.config::get('core.site_name')
				)
			);
		}
		if (is_object($theme) && $theme->id) {
			Tpl::i()->append(
				'feed_rss',
				array(
					'path'=>_url($theme->id, 'theme', 'xml'),
					'name'=>'Сообщения темы "'.$theme->subject.'" - '.config::get('core.site_name')
				)
			);
		}
	}

}