<?

class CommentTools
{
	public static $validation=3;
	
	public static function comment_add()
	{
		if (!access('comment_add')) return LabCMS::i()->error403();
		$pc=new LabComments(null, $_GET['var1']);
		self::_add($pc);
	}
	
	public static function comment_reply()
	{
		if (!access('comment_add')) return LabCMS::i()->error403();
		$pc=new LabComments($_GET['var1']);
		self::_add($pc);
	}
	
	protected static function _add($pc)
	{
		self::_checkAccess($pc);
		if (!LabCMS::i()->no_errors) return;
		
		$form=self::_buildCommentForm();
		if ($form->validate())
		{
			$data=$form->getValue();
			if (isNotBot($_POST['login']))
			{
				$data['login']=$data[LabConfig::$cfg['catcher']];
				unset($data[LabConfig::$cfg['catcher']]);
			}
			$data['status']=access('comment_no_premoderation')?1:2;
			if ($pc->add($data))
				refresh('', $pc->url);
		}
		
		self::_assign('form', self::_render($form));
		LabCMS::i()->setModuleTemplate('string:{$form.html}');
	}
	
	public static function comment_edit()
	{
		$cmt=new LabComments($_GET['var1']);
		self::_checkAccess($cmt);
		if (!LabCMS::i()->no_errors) return;
		
		if (($cmt->user_id==User::i()->id && !access('comment_edit'))
			|| ($cmt->user_id!=User::i()->id && !access('comment_moderator, comment_admin')))
				return LabCMS::i()->error403();
		
		$form=self::_buildCommentForm();
		
		if ($form->validate())
		{
			if ($cmt->edit($form->getValue()))
				refresh('', $cmt->url);
		}
		
		$form->addDataSource(new HTML_QuickForm2_DataSource_Array(array(
				'login'	=> $cmt->login,
				'email'	=> $cmt->email,
				'text'	=> $cmt->text
			)));
		self::_assign('form', self::_render($form));
		LabCMS::i()->setModuleTemplate('string:{$form.html}');
	}
	
	public static function comment_delete()
	{
		if (!User::checkToken($_GET['token'], false)) return;
		$cmt=new LabComments($_GET['var1']);
		if (!LabCMS::i()->no_errors) return;
		if (($cmt->user_id==User::i()->id && !access('comment_edit'))
			|| ($cmt->user_id!=User::i()->id && !access('comment_moderator, comment_admin')))
				return LabCMS::i()->error403();
		
		//если сообщение последнее в цепочке и удаляет автор - удаляем полностью
		//если нет - просто помечаем удаленным
		if ($cmt->leaf && $cmt->user_id==User::i()->id)
			$cmt->deleteBranch();
		else
			$cmt->delete();
		
		if (LabCMS::i()->no_errors) refresh('', $cmt->url);
		
	}
	
	public static function comment_undelete()
	{
		if (!User::checkToken($_GET['token'], false)) return;
		$cmt=new LabComments($_GET['var1']);
		if (!LabCMS::i()->no_errors) return;
		
		if (!access('comment_admin')) return LabCMS::i()->error403();
		if ($cmt->undelete())
			refresh('', $cmt->url);
	}
	
	public static function comment_unhide()
	{
		if (!User::checkToken($_GET['token'], false)) return;
		$cmt=new LabComments($_GET['var1']);
		if (!LabCMS::i()->no_errors) return;
		
		if (!access('comment_moderator, comment_admin')) return LabCMS::i()->error403();
		if ($cmt->unhide())
			refresh('', $cmt->url);
	}
	
	public static function comment_delete_branch()
	{
		if (!User::checkToken($_GET['token'], false)) return;
		$cmt=new LabComments($_GET['var1']);
		if (!LabCMS::i()->no_errors) return;
		
		if (!access('comment_admin')) return LabCMS::i()->error403();
		if ($cmt->deleteBranch())
			refresh('', $cmt->url);
	}
	
	public static function comment_abuse()
	{
		if (!User::checkToken($_GET['token'], false)) return;
		$cmt=new LabComments($_GET['var1']);
		self::_checkAccess($cmt);
		if (!LabCMS::i()->no_errors) return;
		if (!User::i()->isGuest() && access('comment_abuse'))
		{
			$cmt->abuse();
		}
		refresh('', $cmt->url);
	}
	
	public static function comment_moderate()
	{
		if (!access('comment_moderator, comment_admin'))	return LabCMS::i()->error403();
		self::_setModerationTemplate();
		if ($_SERVER['REQUEST_METHOD']=='POST')
		{
			if (!User::checkToken($_POST['token'], false)) return;
			LabComments::updateAbusedComments($_POST['act']);
			refresh(false, _url(false, 'comment_moderate'));
		}
		
		$comments=LabComments::getAbusedComments();
		
		if ($comments['comments']) foreach($comments['comments'] as $key=>$comment)
		{
			$comments['comments'][$key]['text_html']=getbb($comment['text']);
		}
		self::_assign('comments', $comments['comments']);
	}

	public static function comment_premoderate()
	{
		if (!access('comment_moderator, comment_admin'))	return LabCMS::i()->error403();
		self::_setModerationTemplate();
		self::_assign('mode', 'pre');
		if ($_SERVER['REQUEST_METHOD']=='POST')
		{
			if (!User::checkToken($_POST['token'], false)) return;
			LabComments::updatePremoderatedComments($_POST['act']);
			refresh(false, _url(false, 'comment_premoderate'));
		}
		
		$comments=LabComments::getModerationComments();
		
		if ($comments['comments']) foreach($comments['comments'] as $key=>$comment)
		{
			$comments['comments'][$key]['text_html']=getbb($comment['text']);
		}
		self::_assign('comments', $comments['comments']);
	}
	
	public static function comment_rss()
	{
		$comments=LabComments::getLastComments();
		$url=getServerName();
		$rss=array('title'=>'Последние комментарии - '.LabConfig::get('site_name'),
						'link'=>$url.LabCMS::i()->url(),
						'description'=>"Последние комментарии на сайте http://".$_SERVER['SERVER_NAME']);

		if ($comments['comments']) foreach($comments['comments'] as $comment)
		{
			if (in_array($comment['status'], array(1,2)))
			{
				$text_html=($comment['status']==1)?getbb($comment['text']):'Ожидает модерации';
				$rss['feed'][]=array('title'=>'комментарий #'.$comment['comment_id'],
								'description'=>'<b>'.htmlspecialchars($comment['login']).'</b><br />'.$text_html,
								'link'=>$url.$comment['url'],
								'pubDate'=>$comment['last_update']);
			}
		}
		LabVars::$break=true;
		feed($rss);
	}
	
	public static function comment_repair()
	{
		if (!access('comment_admin'))	return LabCMS::i()->error403();
		LabComments::repairComments();
		LabCMS::i()->reset_cache('all');
		refresh();
	}
	
	public static function getComments($item_key, $url)
	{
		if(LabConfig::$cfg['cache'])
		{
			$cacher=new Cache_Generic();
			$last_update=LabComments::getLastUpdate($item_key);
			$cache_key='lab_comments_'.LabCMS::i()->getModuleId().'_'.$item_key.'_'.$last_update;
			$comments=$cacher->get($cache_key);
		}
		
		if (!$comments)
		{
			$comments=LabComments::getComments($item_key, $url);
			if ($comments['comments'])
				foreach($comments['comments'] as $key=>$comment)
				{
					$comments['comments'][$key]['text_html']=getbb($comment['text']);
				}
		}
		else $comments['cached']=true;

		if ($comments['url'] && $comments['url']!=$url)
		{
			LabComments::updateUrl($comments['item_id'], $url);
			$comments['url']=$url;
		}

		if(LabConfig::$cfg['cache'] && !$comments['cached']) $cacher->set($cache_key, $comments, 60*60*24);
		
		$_SESSION['comments'][$comments['item_id']]=true;
		
		if ($comments['comments'])
		{
			foreach($comments['comments'] as $key=>$comment)
			{
				$comment=self::_assignButtons($comment);
				$comments['comments'][$key]=$comment;
			}
		}

		//для админа и модератора выводим сообщения о комментариях, требущих их внимания		
		if (access('comment_moderator, comment_admin'))
		{
			if ($count=LabComments::getAbusedCounter())
				LabCMS::i()->setMessage(sprintf(_m('<a href="%s">Жалоб на комментарии: %s</a>'), _url(false, 'comment_moderate'), $count), true, true);
			if ($count=LabComments::getModerationCounter())
				LabCMS::i()->setMessage(sprintf(_m('<a href="%s">Комментариев ожидают модерации: %s</a>'), _url(false, 'comment_premoderate'), $count), true, true);
		}
		
		return $comments;
	}
	
	public static function comment_json()
	{
		Debug_HackerConsole_Main::disable();
		if (!User::checkToken($_POST['token'], false)) self::_json_error();
		
		$json_response=array('error'=>'Метод не найден');
		$method='_json_'.$_POST['action'];
		if (is_callable(array(self, $method)))
			$json_response=self::$method();
			
		echo real_json_encode($json_response);
		exit;
	}
	
	static function _json_comment_get_new()
	{
		$cmt=new LabComments($_POST['comment_id']);
		self::_checkAccess($cmt);
		if (!LabCMS::i()->no_errors) self::_json_error();
		$json_response=array();
		if ($comments=$cmt->getNewComments())
		{
			foreach($comments as $comment)
			{
				$comment['text_html']=getbb($comment['text']);
				self::_assign('comment', $comment);
				$json_response[]=array('comment_id'=>$comment['comment_id'], 'parent_id'=>$comment['parent_id'], 'html'=>Tpl::i()->fetch(LabCMS::i()->getModuleName().'/comment_ajax.tpl'));
			}
		}
		return $json_response;
	}
	
	protected static function _json_comment_add()
	{
		if (!access('comment_add')) self::_json_error('Недостаточно прав для написания комментариев!');
		if ($_POST['comment_id']) $pc=new LabComments($_POST['comment_id']);
		else $pc=new LabComments(null, $_POST['item_id']);
		self::_checkAccess($pc);
		if (!LabCMS::i()->no_errors) self::_json_error();
		
		$form=self::_buildCommentForm();
		if ($form->validate())
		{
			$data=$form->getValue();
			if (isNotBot($_POST['login']))
			{
				$data['login']=$data[LabConfig::$cfg['catcher']];
				unset($data[LabConfig::$cfg['catcher']]);
			}
			$data['status']=access('comment_no_premoderation')?1:2;
			if ($comment_id=$pc->add($data))
			{
				$comment=new LabComments($comment_id);
				$comment->info['text_html']=getbb($comment->info['text']);
				$comment->info=self::_assignButtons($comment->info);
				self::_assign('comment', $comment->info);
				$json_response['comment_id']=$comment_id;
				$json_response['parent_id']=intval($comment->parent_id);
				$json_response['html']=Tpl::i()->fetch(LabCMS::i()->getModuleName().'/comment_ajax.tpl');
				return $json_response;
			}
		}
		else
		{
			foreach (new RecursiveIteratorIterator($form->getIterator()) as $elem)
			{
				if ($elem->getError()) self::_json_error($elem->getError());
			}
		}
	}
	
	protected static function _json_comment_edit()
	{
		$cmt=new LabComments($_POST['comment_id']);
		self::_checkAccess($cmt);
		if (!LabCMS::i()->no_errors) self::_json_error();
		
		if (($cmt->user_id==User::i()->id && !access('comment_edit'))
			|| ($cmt->user_id!=User::i()->id && !access('comment_moderator, comment_admin')))
				self::_json_error('Недостаточно прав для редактирования!');
		
		$form=self::_buildCommentForm();
		
		if ($form->validate())
		{
			$data=$form->getValue();
			if ($cmt->edit($data)) return array('text_html'=>getbb($data['text']), 'comment_id'=>$cmt->id);
		}
		else
		{
			foreach (new RecursiveIteratorIterator($form->getIterator()) as $elem)
			{
				if ($elem->getError()) self::_json_error($elem->getError());
			}
		}
	}
	
	protected static function _json_comment_delete()
	{
		$cmt=new LabComments($_POST['comment_id']);
		self::_checkAccess($cmt);
		if (!LabCMS::i()->no_errors) self::_json_error();
		if (($cmt->user_id==User::i()->id && !access('comment_edit'))
			|| ($cmt->user_id!=User::i()->id && !access('comment_moderator, comment_admin')))
				self::_json_error('Недостаточно прав для удаления!');
		
		//если сообщение последнее в цепочке и удаляет автор - удаляем полностью
		//если нет - просто помечаем удаленным
		$json_response['comment_id']=$cmt->id;

		if ($cmt->leaf && $cmt->user_id==User::i()->id)
		{
			if(!$cmt->deleteBranch()) self::_json_error();
			$json_response['branch_id']=$cmt->id;
		}
		else
		{
			if(!$cmt->delete()) self::_json_error();
		}
		return $json_response;
	}
	
	protected static function _json_comment_undelete()
	{
		$cmt=new LabComments($_POST['comment_id']);
		if (!LabCMS::i()->no_errors) self::_json_error();
		
		if (!access('comment_admin')) self::_json_error('Недостаточно прав для восстановления!');
		
		$json_response['comment_id']=$cmt->id;
		
		if (!$cmt->undelete()) self::_json_error();

		return $json_response;
	}
	
	protected static function _json_comment_unhide()
	{
		$cmt=new LabComments($_POST['comment_id']);
		if (!LabCMS::i()->no_errors) self::_json_error();
		
		if (!access('comment_moderator, comment_admin')) self::_json_error('Недостаточно прав для модерации!');
		
		$json_response['comment_id']=$cmt->id;
		
		if (!$cmt->unhide()) self::_json_error();
		$json_response['ok']=true;

		return $json_response;
	}
	
	protected static function _json_comment_delete_branch()
	{
		$cmt=new LabComments($_POST['comment_id']);
		if (!LabCMS::i()->no_errors) self::_json_error();
		
		if (!access('comment_admin')) self::_json_error('Недостаточно прав для удаления!');
		if ($cmt->deleteBranch()) return array('comment_id'=>$cmt->id);
		self::_json_error();
	}
	
	protected static function _json_comment_abuse()
	{
		$cmt=new LabComments($_POST['comment_id']);
		self::_checkAccess($cmt);
		if (!LabCMS::i()->no_errors) self::_json_error();
		if (!User::i()->isGuest() && access('comment_abuse'))
		{
			if ($cmt->abuse()) return array('comment_id'=>$cmt->id, 'message'=>"Жалоба принята");
			self::_json_error();
		}
		else self::_json_error('Недостаточно прав для подачи жалобы');
	}
	
	protected static function _json_comment_get()
	{
		$cmt=new LabComments($_POST['comment_id']);
		self::_checkAccess($cmt);
		if (!LabCMS::i()->no_errors) self::_json_error();
		
		if ((!access('comment_edit') && $cmt->user_id==User::i()->id)
			&& !access('comment_moderator, comment_admin'))	self::_json_error('Недостаточно прав для редактирования!');
		
		$json_response['comment_id']=$cmt->login;
		$json_response['text']=$cmt->text;
		return $json_response;
	}
	
	protected static function _json_error($msg=false)
	{
		if ($msg) echo real_json_encode(array('error'=>$msg));
		else echo real_json_encode(array('error'=>LabCMS::i()->errors[0]));
		exit; 
	}
	
	protected static function _assignButtons($comment)
	{
		//набор правил
		switch($comment['status'])
		{
			case(1): //опубликовано
				$comment['buttons']['add']=access('comment_add');
				$comment['buttons']['edit']=((access('comment_edit') && $comment['user_id']==User::i()->id) || access('comment_moderator, comment_admin'));
				$comment['buttons']['delete']=((access('comment_edit') && $comment['user_id']==User::i()->id) || access('comment_moderator, comment_admin'));
				$comment['buttons']['delete_branch']=access('comment_admin');
				$comment['buttons']['abuse']=(access('comment_abuse') && (!$comment['abuse'] || !array_key_exists(User::i()->id, (array)$comment['abuse'])));
			break;
			case(2): //ожидает модерации
				if (!access('comment_moderator, comment_admin')) $comment['text_html']="Комментарий ожидает модерации";
				$comment['buttons']['unhide']=access('comment_moderator, comment_admin');
				$comment['buttons']['edit']=access('comment_moderator, comment_admin');
				$comment['buttons']['delete']=access('comment_moderator, comment_admin');
				$comment['buttons']['delete_branch']=access('comment_admin');
			break;
			case(3): //удалено
				if (!access('comment_admin')) $comment['text_html']="Комментарий удален";
				$comment['buttons']['undelete']=access('comment_admin');
				$comment['buttons']['delete_branch']=access('comment_admin');
			break;
		}
		return $comment;
	}
	
	protected static function _buildCommentForm()
	{
		$form=new HTML_QuickForm2('cmt_form', 'post', array('action'=>''), false);
		$token=$form->addElement('hidden', 'token', array('value'=>User::i()->token));
		$token->addRule('callback', _m('Ошибка сохранения'), array('callback'=>array('User', 'checkToken'), 'arguments'=>array(false)));
		if (User::i()->isGuest())
		{
			$login=$form->addElement('text', LabConfig::$cfg['catcher'], null, array('label'=>'Имя'.self::_getCatcher()));
			$login->addRule('required', 'Надо ввести имя', null, self::$validation);
			$form->addElement('text', 'email', null, array('label'=>'Email'));
			self::_addLoginRules($login);
		}
		$msg=$form->addElement('textarea', 'text', array('class'=>'bbcode', 'rows'=>5, 'cols'=>50), array('label'=>'Комментарий'));
		$form->addElement('submit', null, array('value'=>'Сохранить'), array('label'=>'&nbsp;'));
		$msg->addRule('required', 'Не введен текст комментария', null, self::$validation);
		return $form;
	}
	
	protected static function _checkAccess($obj)
	{
		if (!($_SESSION['comments'][$obj->item_id] || access('comment_moderator, comment_admin'))) refresh('', _url(false, false, false, $obj->url));
	}
	
	protected static function _error($msg, $lang=false)
	{
		return LabCMS::i()->error($msg, $lang);
	}
	
	protected static function _assign($key, $value=null)
	{
		Tpl::i()->assign($key, $value);
	}
	
	protected static function _render($form)
	{
		$renderer = HTML_QuickForm2_Renderer::factory('labsmarty');
		$html=$form->render($renderer)->toArray();
		if (self::$validation>1)
		{
			LabCMS::i()->skins[LabCMS::i()->getSkin()]['js']=LabCMS::i()->skins[LabCMS::i()->getSkin()]['js']+$renderer->getJavascriptBuilder()->getLibraries(false, false);
		}
		return $html;
	}
	
	protected static function _addLoginRules(&$login)
	{
		return $login->addRule('required', _m('Надо указать логин'), null, self::$validation)
		->and_($login->createRule('maxlength', _m('Логин не может быть длиннее 20 символов'), 20, self::$validation))
		->and_($login->createRule('notCallback', _m('Логин уже занят'), array(User::i(), 'isLoginExists')));
	}
	
	protected static function _getCatcher()
	{
		return '<input type="text" name="login" value="" class="catch" />';
	}
	
	protected static function _setModerationTemplate()
	{
		$string=<<<HTML
<div class="comments">
<form action="" method="post" id="comments">
	<input type="hidden" name="token" value="{\$_user->token}" />
	<ul>
	{foreach \$comments as \$comment}
		<li class="comment_item">
			<div class="comment_tools">
				{if \$mode=='pre'}Опубликовать{else}Оставить{/if} <input type="radio" name="act[{\$comment.comment_id}]" value="ok" />
				Удалить <input type="radio" name="act[{\$comment.comment_id}]" value="del" />
			</div>
			<a href="{\$comment.url|escape}#comment{\$comment.comment_id}">ссылка</a>
			{if \$comment.abuse_count}<div class="abuse_users"> Жалоб: {\$comment.abuse_count} <br/>
			Пожаловались: {foreach \$comment.abuse as \$user_id=>\$login}{\$login|escape}{if !\$login@last},{/if}{/foreach}</div>{/if}
			<div>
				<div class="user_info"><span class="login">{\$comment.login|escape}</span> <span class="date">[{\$comment.putdate}] [{\$comment.ip}]</span></div>
				<div class="comment_body">{\$comment.text_html}</div>
			</div>
		</li>
	{foreachelse}
		<div>Все довольны. Никто ни на что не жалуется:)</div>
	{/foreach}
	<ul>
	{if \$comments}<p><input type="submit" value="применить" /></p>{/if}
</form>
</div>
HTML;
		LabCMS::i()->setModuleTemplate('string:'.$string);
	}
}
