<?php
/**
* @package RSForm!Pro
* @copyright (C) 2007-2019 www.rsjoomla.com
* @license GPL, http://www.gnu.org/copyleft/gpl.html
*/

// no direct access
defined('_JEXEC') or die;

use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Http\HttpFactory;
use Joomla\Utilities\IpHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Router\Route;

class plgSystemRsfpakismet extends CMSPlugin
{
	protected $autoloadLanguage = true;

	protected function getTable()
	{
		return Table::getInstance('RSForm_Akismet', 'Table');
	}

	public function onRsformFormSave($form)
	{
		$data 			 		= Factory::getApplication()->input->post->get('akismet', array(), 'array');
		$data['form_id'] 		= $form->FormId;
		$data['aki_merge_vars'] = array();

		$form = $this->getTabForm();
		if ($fields = $form->getFieldset('merge'))
		{
			foreach ($fields as $field)
			{
				$data['aki_merge_vars'][$field->fieldname] = isset($data[$field->fieldname]) ? $data[$field->fieldname] : '';
			}
		}

		$row = $this->getTable();
		if (!$row)
		{
			return false;
		}

		return $row->save($data);
	}
	
	public function onRsformBackendFormCopy($args)
	{
		$formId 	= $args['formId'];
		$newFormId 	= $args['newFormId'];

		if ($row = $this->getTable())
		{
			if ($row->load($formId))
			{
				if (!$row->bind(array('form_id' => $newFormId)))
				{
					return false;
				}

				if (!$row->check())
				{
					return false;
				}

				return $row->store();
			}
		}
	}

	protected function getTabForm()
	{
		Form::addFormPath(__DIR__ . '/forms');

		$form = Form::getInstance( 'plg_system_rsfpakismet.tab', 'tab', array('control' => 'akismet'), false, false);

		return $form;
	}

	public function onRsformBackendAfterShowFormEditTabs()
	{
		$formId = Factory::getApplication()->input->getInt('formId');
		$row 	= $this->getTable();
		
		if (!$row)
		{
			return false;
		}
		
		$row->load($formId);
		$row->migrateData();

		$form = $this->getTabForm();
		$data = $row->getProperties();
		$data['aki_merge_vars'] = array();

		if ($fields = $form->getFieldset('merge'))
		{
			if (is_array($row->aki_merge_vars))
			{
				foreach ($row->aki_merge_vars as $key => $value)
				{
					$data[$key] = $value;
				}
			}
		}

		$form->bind($data);
		?>
		<div id="akismetdiv">
			<fieldset class="form-horizontal">
				<legend class="rsfp-legend"><?php echo Text::_('RSFP_AKI_NAME'); ?></legend>
				<div class="alert alert-info"><?php echo Text::_('RSFP_AKISMET_DESC'); ?></div>
				<?php echo $form->renderFieldset('params'); ?>
				<legend class="rsfp-legend"><?php echo Text::_('RSFP_AKI_MERGE_VARS'); ?></legend>
				<p><?php echo Text::_('RSFP_AKI_MERGE_VARS_DESC'); ?></p>
				<?php echo $form->renderFieldset('merge'); ?>
			</fieldset>
		</div>
		<?php
	}

	public function onRsformBackendAfterShowFormEditTabsTab()
	{
		?>
		<li><a href="javascript: void(0);" id="akismet"><span class="rsficon rsficon-text-color"></span><span class="inner-text"><?php echo Text::_('RSFP_AKI_INTEGRATION'); ?></span></a></li>
		<?php
	}

	public function onRsformFrontendBeforeFormValidation($args)
	{
		$post   = $args['post'];
		$formId = (int) $post['formId'];
		$db     = Factory::getDbo();
		$app	= Factory::getApplication();

		/* @var $row TableRSForm_Akismet */
		$row = $this->getTable();
		if (!$row)
		{
			return false;
		}

		if ($row->load(array('form_id' => $formId, 'aki_published' => 1)))
		{
			try
			{
				$http = HttpFactory::getHttp();
				$key = RSFormProHelper::getConfig('aki.key');

				// Check for a valid key
				$data = array(
					'key' => $key,
					'blog' => (string) Uri::getInstance()
				);

				$response = $http->post('https://rest.akismet.com/1.1/verify-key', $data);

				if ($response->code != 200)
				{
					throw new Exception(Text::sprintf('RSFP_AKI_RESPONSE_CODE', $response->code));
				}

				if ($response->body == 'invalid')
				{
					throw new Exception($response->headers['X-akismet-debug-help']);
				}

				$tag = Factory::getLanguage()->getTag();
				$tmp = explode('-', $tag);
				$lang = strtolower(reset($tmp));

				// Submit comment
				$data = array(
					'blog' 			=> Uri::root(),
					'user_ip'      	=> IpHelper::getIp(),
					'user_agent'   	=> $app->input->server->get('HTTP_USER_AGENT', '', 'raw'),
					'referrer'     	=> $app->input->server->get('HTTP_REFERER', '', 'raw'),
					'permalink'    	=> (string) Uri::getInstance(),
					'comment_type' 			=> 'contact-form',
					'blog_charset' 			=> 'UTF-8',
					'blog_lang' 			=> $lang,
					'comment_author' 		=> '',
					'comment_author_email' 	=> '',
					'comment_author_url' 	=> '',
					'comment_content' 		=> ''
				);

				foreach ($row->aki_merge_vars as $tag => $field)
				{
					if (empty($tag))
					{
						continue;
					}

					if (!isset($post[$field]))
					{
						$post[$field] = '';
					}

					if (is_array($post[$field]))
					{
						$post[$field] = implode(',', $post[$field]);
					}

					$data[$tag] = $post[$field];
				}

				$response = $http->post(sprintf('https://%s.rest.akismet.com/1.1/comment-check', $key), $data);

				if ($response->code != 200)
				{
					throw new Exception(Text::sprintf('RSFP_AKI_RESPONSE_CODE', $response->code));
				}

				if ($response->body == 'true')
				{
					throw new Exception(Text::_('RSFP_AKI_OUR_SYSTEMS_HAVE_DETECTED_THAT_YOUR_SUBMISSION_IS_SPAM'), 500);
				}
			}
			catch (Exception $e)
			{
				$app->enqueueMessage($e->getMessage(), 'error');

				if ($e->getCode() == 500)
				{
					$query = $db->getQuery(true)
						->select($db->qn('ComponentId'))
						->from($db->qn('#__rsform_components'))
						->where($db->qn('FormId') . ' = ' . $db->q($formId))
						->where($db->qn('Published') . ' = ' . $db->q(1));
					$db->setQuery($query);
					$components = $db->loadColumn();

					if (!empty($components))
					{
						$args['invalid'] = array_merge($args['invalid'],$components);
						$args['invalid'] = array_unique($args['invalid']);
					}
				}
			}
		}
	}

	public function onRsformBackendAfterShowConfigurationTabs($tabs)
	{
		$tabs->addTitle(Text::_('RSFP_AKI_NAME'), 'form-akismet');
		$tabs->addContent($this->configurationScreen());
	}

	public function onRsformFormDelete($formId)
	{
		if ($row = $this->getTable())
		{
			$row->delete($formId);
		}
	}

	public function onRsformFormBackup($form, $xml, $fields)
	{
		if ($row = $this->getTable())
		{
			if ($row->load($form->FormId))
			{
				$row->check();

				$data = $row->getProperties();
				unset($data['form_id']);

				$xml->add('akismet');
				foreach ($data as $property => $value)
				{
					$xml->add($property, $value);
				}
				$xml->add('/akismet');
			}
		}
	}

	public function onRsformFormRestore($form, $xml, $fields)
	{
		if (isset($xml->akismet))
		{
			$data = array(
				'form_id' => $form->FormId
			);
			foreach ($xml->akismet->children() as $property => $value)
			{
				$data[$property] = (string) $value;
			}

			$row = $this->getTable();
			$row->save($data);
		}
	}

	public function onRsformBackendFormRestoreTruncate()
	{
		Factory::getDbo()->truncateTable('#__rsform_akismet');
	}

	protected function configurationScreen()
	{
		ob_start();

		Form::addFormPath(__DIR__ . '/forms');

		$form = Form::getInstance( 'plg_system_rsfpakismet.configuration', 'configuration', array('control' => 'rsformConfig'), false, false );
		$form->bind($this->loadFormData());

		?>
		<div id="page-akismet" class="form-horizontal">
			<?php
			foreach ($form->getFieldsets() as $fieldset)
			{
				if ($fields = $form->getFieldset($fieldset->name))
				{
					foreach ($fields as $field)
					{
						echo $field->renderField();
					}
				}
			}
			?>
		</div>
		<?php

		$contents = ob_get_contents();
		ob_end_clean();

		return $contents;
	}

	private function loadFormData()
	{
		$data 	= array();
		$db 	= Factory::getDbo();

		$query = $db->getQuery(true)
			->select('*')
			->from($db->qn('#__rsform_config'))
			->where($db->qn('SettingName') . ' LIKE ' . $db->q('aki.%', false));
		if ($results = $db->setQuery($query)->loadObjectList())
		{
			foreach ($results as $result)
			{
				$data[$result->SettingName] = $result->SettingValue;
			}
		}

		return $data;
	}

	public function onRsformBackendGetEditFields(&$return, $submission)
	{
		if (Factory::getApplication()->input->get('format') == 'pdf')
		{
			return;
		}

		if ($row = $this->getTable())
		{
			if ($row->load(array('form_id' => $submission->FormId, 'aki_published' => 1)))
			{
				Text::script('RSFP_AKI_SUBMIT_SPAM_SURE');

				$new_field = array(Text::_('RSFP_AKI_NAME'));

				if (isset($submission->values['_AKISMET_SPAM']))
				{
					$new_field[] = Text::_('RSFP_AKI_ALREADY_SUBMITTED');
				}
				else
				{
					$new_field[] = '<a onclick="return confirm(Joomla.JText._(\'RSFP_AKI_SUBMIT_SPAM_SURE\'))" href="' . Route::_('index.php?option=com_rsform&task=plugin&plugin_task=akismet.spam&id=' . $submission->SubmissionId) . '" class="btn btn-secondary">' . Text::_('RSFP_AKI_SUBMIT_SPAM') . '</a><br><small>' . Text::_('RSFP_AKI_SUBMIT_SPAM_DESC') . '</small>';
				}

				$return[] = $new_field;
			}
		}
	}

	public function onRsformBackendSwitchTasks()
	{
		$app = Factory::getApplication();

		if ($app->input->getString('plugin_task') == 'akismet.spam')
		{
			try
			{
				$id = $app->input->getInt('id');

				require_once JPATH_ADMINISTRATOR . '/components/com_rsform/helpers/submissions.php';
				$submission = RSFormProSubmissionsHelper::getSubmission($id);

				if (!$submission)
				{
					throw new Exception(Text::_('RSFP_AKI_CANNOT_MARK_AS_SPAM_MISSING_SUBMISSION'));
				}

				$row = $this->getTable();

				if (!$row)
				{
					throw new Exception(Text::_('RSFP_AKI_MISSING_TABLE'));
				}

				if (!$row->load(array('form_id' => $submission->FormId, 'aki_published' => 1)))
				{
					throw new Exception(Text::_('RSFP_AKI_UNPUBLISHED_INTEGRATION'));
				}

				$http 	= HttpFactory::getHttp();
				$key 	= RSFormProHelper::getConfig('aki.key');
				$data 	= array(
					'key' 	=> $key,
					'blog' 	=> (string) Uri::getInstance()
				);

				$response = $http->post('https://rest.akismet.com/1.1/verify-key', $data);

				if ($response->code != 200)
				{
					throw new Exception(Text::sprintf('RSFP_AKI_RESPONSE_CODE', $response->code));
				}

				if ($response->body == 'invalid')
				{
					throw new Exception($response->headers['X-akismet-debug-help']);
				}

				$tag = $submission->Lang;
				$tmp = explode('-', $tag);
				$lang = strtolower(reset($tmp));

				// Submit comment
				$data = array(
					'blog' 					=> Uri::root(),
					'user_ip'      			=> $submission->UserIp,
					'user_agent'   			=> isset($submission->values['_AKI_USER_AGENT']) ? $submission->values['_AKI_USER_AGENT'] : '',
					'referrer'     			=> isset($submission->values['_AKI_REFERRER']) ? $submission->values['_AKI_REFERRER'] : '',
					'permalink'    			=> isset($submission->values['_AKI_PERMALINK']) ? $submission->values['_AKI_PERMALINK'] : '',
					'comment_type' 			=> 'contact-form',
					'blog_charset' 			=> 'UTF-8',
					'blog_lang' 			=> $lang,
					'comment_author' 		=> '',
					'comment_author_email' 	=> '',
					'comment_author_url' 	=> '',
					'comment_content' 		=> ''
				);

				foreach ($row->aki_merge_vars as $tag => $field)
				{
					if (empty($tag))
					{
						continue;
					}

					if (isset($submission->values[$field]))
					{
						$data[$tag] = $submission->values[$field];
					}
					else
					{
						$data[$tag] = '';
					}
				}

				$response = $http->post(sprintf('https://%s.rest.akismet.com/1.1/submit-spam', $key), $data);

				if ($response->code != 200)
				{
					throw new Exception(Text::sprintf('RSFP_AKI_RESPONSE_CODE', $response->code));
				}

				if ($response->body != 'Thanks for making the web a better place.')
				{
					throw new Exception(Text::sprintf('RSFP_AKI_ERROR_BODY', strip_tags($response->body)));
				}

				$value = (object) array(
					'FormId' 		=> $submission->FormId,
					'SubmissionId' 	=> $id,
					'FieldName'		=> '_AKISMET_SPAM',
					'FieldValue'	=> 1
				);

				Factory::getDbo()->insertObject('#__rsform_submission_values', $value);

				$app->enqueueMessage(Text::_('RSFP_AKI_MARKED_AS_SPAM'));
				$app->redirect('index.php?option=com_rsform&view=submissions&layout=edit&cid=' . $id);
			}
			catch (Exception $e)
			{
				$app->enqueueMessage($e->getMessage(), 'error');
				$app->redirect('index.php?option=com_rsform&view=submissions');
			}
		}
	}

	public function onRsformFrontendBeforeStoreSubmissions($args)
	{
		$row = $this->getTable();

		if ($row->load(array('form_id' => $args['formId'], 'aki_published' => 1)))
		{
			$input = Factory::getApplication()->input->server;

			$args['post']['_AKI_USER_AGENT'] = $input->get('HTTP_USER_AGENT', '', 'raw');
			$args['post']['_AKI_REFERRER'] = $input->get('HTTP_REFERER', '', 'raw');
			$args['post']['_AKI_PERMALINK'] = (string) Uri::getInstance();
		}
	}
}