<?php
/**
 * @package        RSForm! Pro
 * @copyright  (c) 2007 - 2019 RSJoomla!
 * @link           https://www.rsjoomla.com
 * @license        GNU General Public License http://www.gnu.org/licenses/gpl-3.0.en.html
 */

defined('_JEXEC') or die;

use Joomla\String\StringHelper;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Factory;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Filter\OutputFilter;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\String\PunycodeHelper;

/**
 * Class plgSystemRsfparticles
 */
class plgSystemRsfparticles extends CMSPlugin
{
	/**
	 * @var bool
	 */
	protected $autoloadLanguage = true;

	protected $json_elements = array(
		'images' => array(
			'image_intro',
			'float_intro',
			'image_intro_alt',
			'image_intro_caption',
			'image_fulltext',
			'float_fulltext',
			'image_fulltext_alt',
			'image_fulltext_caption'
		),
		'urls' => array(
			'urla',
			'urlatext',
			'targeta',
			'urlb',
			'urlbtext',
			'targetb',
			'urlc',
			'urlctext',
			'targetc'
		),
		'attribs'=> array(
			'article_layout',
			'show_title',
			'link_titles',
			'show_tags',
			'show_intro',
			'info_block_position',
			'info_block_show_title',
			'show_category',
			'link_category',
			'show_parent_category',
			'link_parent_category',
			'show_author',
			'link_author',
			'show_create_date',
			'show_modify_date',
			'show_publish_date',
			'show_item_navigation',
			'show_hits',
			'show_noauth',
			'urls_position',
			'alternative_readmore',
			'article_page_title',
			'show_publishing_options',
			'show_article_options',
			'show_urls_images_backend',
			'show_urls_images_frontend'
		),
		'metadata' => array(
			'robots',
			'author',
			'rights',
			'xreference'
		)
	);

	/**
	 * Save the form properties
	 *
	 * @param $form
	 *
	 * @return void
	 */
	public function onRsformFormSave($form)
	{
		$application            = Factory::getApplication();
		$data                   = $application->input->get('ra', array(), 'array');
		$data['form_id']        = $form->FormId;
		$data['ra_merge_vars']  = $application->input->get('ra_merge_vars', array(), 'array');

		if ($row = $this->getTable())
		{
			try
			{
				if (!$row->save($data))
				{
					throw new Exception($row->getError());
				}
			}
			catch (Exception $e)
			{
				$application->enqueueMessage($e->getMessage(), 'error');
			}
		}
	}

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

	private function getJsonElements()
	{
		static $done;

		if (!$done)
		{
			$done = true;

			$db = Factory::getDbo();
			$query = $db->getQuery(true)
				->select($db->qn('name'))
				->from($db->qn('#__fields'))
				->where($db->qn('context') . ' = ' . $db->q('com_content.article'))
				->where($db->qn('type') . ' != ' . $db->q('repeatable'));

			$this->json_elements['joomla_fields'] = $db->setQuery($query)->loadColumn();
		}

		return $this->json_elements;
	}

	/**
	 * Function that generates the Form Properties - Articles tab content
	 *
	 * @return bool
	 * @throws Exception
	 */
	public function onRsformBackendAfterShowFormEditTabs()
	{
		$formId = Factory::getApplication()->input->getInt('formId', 0);
		$row    = $this->getTable();

		if (!$row)
		{
			return false;
		}

		$row->load($formId);
		$row->ra_merge_vars = !empty($row->ra_merge_vars) ? @unserialize($row->ra_merge_vars) : array();

		if ($row->ra_merge_vars === false)
		{
			$row->ra_merge_vars = array();
		}
		
		$merge_vars = array('global' =>
			array(
				'created_by'         	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_CREATED_BY'),
				'created_by_alias'   	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_CREATED_BY_ALIAS'),
				'created'   		 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_CREATED_DATE'),
				'catid'        		 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_CATEGORY_ID'),
				'title'          	 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_TITLE'),
				'alias'          	 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_ALIAS'),
				'metakey'          	 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_META_KEY'),
				'metadesc'           	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_META_DESC'),
				'state'				 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_PUBLISH_STATE'),
				'publish_up'		 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_PUBLISH_UP'),
				'publish_down'		 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_PUBLISH_DOWN'),
				'language'			 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_LANGUAGE'),
				'access'			 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_ACCESS_LEVEL'),
				'featured'			 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_FEATURED'),
				'tags'				 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_TAGS'),
				'article_page_title' 	=> Text::_('PLG_SYSTEM_RSFP_ARTICLES_ARTICLE_PAGE_TITLE'),
				'alternative_readmore'  => Text::_('PLG_SYSTEM_RSFP_ARTICLES_ALTERNATIVE_READMORE'),
			)
		);

		// add the json elements
		foreach ($this->getJsonElements() as $type => $f_vars)
		{
			// skip the attribs
			if ($type == 'attribs')
			{
				continue;
			}
			
			if (!isset($merge_vars[$type]))
			{
				$merge_vars[$type] = array();
			}

			foreach ($f_vars as $f_var)
			{
				if ($type == 'joomla_fields')
				{
					$merge_vars[$type][$f_var] = $this->getFieldLabel($f_var);
				}
				else
				{
					$merge_vars[$type][$f_var] = Text::_('PLG_SYSTEM_RSFP_ARTICLES_'.strtoupper($f_var));
				}
			}
		}

		$lists['published'] = RSFormProHelper::renderHTML('select.booleanlist', 'ra[ra_published]', '', $row->ra_published);
		$lists['front_messages'] = RSFormProHelper::renderHTML('select.booleanlist', 'ra[ra_show_front_messages]', '', $row->ra_show_front_messages);
		$lists['trigger_plugins'] = RSFormProHelper::renderHTML('select.booleanlist', 'ra[ra_trigger_plugins]', '', $row->ra_trigger_plugins);
		$lists['trigger_on_payment'] = RSFormProHelper::renderHTML('select.booleanlist', 'ra[ra_trigger_on_payment]', '', $row->ra_trigger_on_payment);

		$hasPayment = PluginHelper::isEnabled('system', 'rsfppayment');

		$editor = RSFormProHelper::getEditor();

		$display_mapped_fields = array();

		Factory::getDocument()->addStyleDeclaration('#rsfparticlesdiv .js-editor-none > textarea#ra_content { display: block; }');
		?>
		<div id="rsfparticlesdiv">
			<table class="admintable">
				<tr>
					<td valign="top" align="left">
						<table width="100%" class="table table-bordered">
							<tr>
								<td colspan="2">
									<div class="alert alert-info"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_DESC'); ?></div>
								</td>
							</tr>
							<tr>
								<td width="80" align="right" nowrap="nowrap" class="key"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_USE_INTEGRATION'); ?></td>
								<td><?php echo $lists['published']; ?></td>
							</tr>
                            <?php if ($hasPayment) { ?>
                            <tr>
                                <td width="80" align="right" nowrap="nowrap" class="key"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_TRIGGER_ON_PAYMENT'); ?></td>
                                <td><?php echo $lists['trigger_on_payment']; ?></td>
                            </tr>
                            <?php } ?>
							<tr>
								<td width="80" align="right" nowrap="nowrap" class="key"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_TRIGGER_CONTENT_PLUGINS'); ?></td>
								<td><?php echo $lists['trigger_plugins']; ?></td>
							</tr>
                            <tr>
                                <td width="80" align="right" nowrap="nowrap" class="key"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_SHOW_FRONT_MESSAGES'); ?></td>
                                <td><?php echo $lists['front_messages']; ?></td>
                            </tr>
						</table>

						<?php foreach ($merge_vars as $type => $m_vars) { ?>
							<h3 class="rsfp-legend"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_MAP_FIELDS_'.strtoupper($type)); ?>
								<?php if ($type != 'global') { ?>
									<button type="button" class="btn btn-primary pull-right" onclick="articlesToggle('<?php echo $type; ?>')"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_TOGGLE_FIELDS'); ?></button>
								<?php } ?>
							</h3>

							<table width="100%" class="table table-bordered" id="rsfa_<?php echo RSFormProHelper::htmlEscape($type)?>" style="<?php echo($type != 'global' ? 'display:none' : ''); ?>">
								<?php if ($type == 'images') { ?>
									<tr>
										<td colspan="2">
											<div class="alert alert-info"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_MAP_FIELDS_IMAGES_INFO'); ?></div>
										</td>
									</tr>
								<?php } ?>
								<?php foreach ($m_vars as $merge_var => $title) { ?>
									<tr>
										<td width="25%" align="right" nowrap="nowrap" class="key"><label for="ra_merge_vars_<?php echo $merge_var; ?>"><?php echo $title; ?></label></td>
										<td>
											<?php
											if ($type == 'joomla_fields')
											{
												$name = 'ra_merge_vars[joomla_fields][' . $merge_var . ']';
												$value = isset($row->ra_merge_vars['joomla_fields'][$merge_var]) ? $row->ra_merge_vars['joomla_fields'][$merge_var] : '';
											}
											else
											{
												$name = 'ra_merge_vars[' . $merge_var . ']';
												$value = isset($row->ra_merge_vars[$merge_var]) ? $row->ra_merge_vars[$merge_var] : '';
											}
											?>
											<input name="<?php echo $name; ?>" class="rs_inp rs_80" id="ra_merge_vars_<?php echo $merge_var; ?>" value="<?php echo RSFormProHelper::htmlEscape($value); ?>" data-delimiter="," data-placeholders="display" />
										</td>
									</tr>
									<?php
									if ($type != 'global' && !empty($value)) {
										$display_mapped_fields[$type] = true;
									}
									?>
								<?php } ?>
							</table>
						<?php } ?>

						<h3 class="rsfp-legend"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_CONTENT'); ?></h3>
						<div style="overflow: hidden">
							<?php echo $editor->display('ra[ra_content]', RSFormProHelper::htmlEscape($row->ra_content), '100%', 500, 70, 20, true, 'ra_ra_content'); ?>
						</div>
					</td>
					<td valign="top" width="1%" nowrap="nowrap">
						<button class="btn btn-secondary" type="button" onclick="articlesToggle('quick_add_fields');"><?php echo Text::_('RSFP_TOGGLE_QUICKADD'); ?></button>
						<div id="rsfa_quick_add_fields" style="width: 200px;margin-left:5px; display:none">
							<h3><?php echo Text::_('RSFP_QUICK_ADD');?></h3>
							<?php
							echo RSFormProHelper::generateQuickAddGlobal();

							foreach ($this->getQuickfields() as $field)
							{
								echo RSFormProHelper::generateQuickAdd($field, 'display');
							}
							?>
						</div>
					</td>
				</tr>
			</table>
		</div>
		<?php

		$script = '';
		if ($display_mapped_fields)
		{
			$script .= 'jQuery(document).ready(function($){';
			foreach ($display_mapped_fields as $type => $active)
			{
				$script .= '$("#rsfa_' . RSFormProHelper::htmlEscape($type) . '").css("display", "");';
			}
			$script .= '});';
		}

		$script .= "function articlesToggle(element) { jQuery('#rsfa_'+element).toggle(); }";

		Factory::getDocument()->addScriptDeclaration($script);

		return true;
	}

	protected function getQuickfields() {
		require_once JPATH_ADMINISTRATOR . '/components/com_rsform/helpers/quickfields.php';
		return RSFormProQuickFields::getFieldNames('all');
	}

	/**
	 * Button from the Form Properties Menu ( LEFT SIDE )
	 */
	public function onRsformBackendAfterShowFormEditTabsTab()
	{
		?>
		<li><a href="javascript: void(0);" id="rsfparticles"><span class="rsficon rsficon-file-text-o"></span><span class="inner-text"><?php echo Text::_('PLG_SYSTEM_RSFP_ARTICLES_INTEGRATION'); ?></span></a></li>
		<?php
	}

	private function getSettings($formId)
    {
        static $cache = array();

        if (!isset($cache[$formId]))
        {
	        $db    = Factory::getDbo();
	        $query = $db->getQuery(true);
	        $query->select('*')
		        ->from($db->qn('#__rsform_articles'))
		        ->where($db->qn('form_id') . '=' . $db->q((int) $formId))
		        ->where($db->qn('ra_published') . '=' . $db->q(1));
	        $db->setQuery($query);

	        if ($cache[$formId] = $db->loadObject())
            {
	            $cache[$formId]->ra_merge_vars = @unserialize($cache[$formId]->ra_merge_vars);
	            if ($cache[$formId]->ra_merge_vars === false)
	            {
		            $cache[$formId]->ra_merge_vars = array();
	            }
            }
        }

        if (!empty($cache[$formId]))
        {
	        return clone $cache[$formId];
        }

        return false;
    }

	/**
	 * Hook in the RSForm!Pro submission storing process.
	 *
	 * @param $args
	 *
	 * @return bool
	 */
	public function onRsformFrontendAfterStoreSubmissions($args)
	{
		$formId       = (int) $args['formId'];
		$SubmissionId = (int) $args['SubmissionId'];

		if ($row = $this->getSettings($formId))
		{
		    if (empty($row->ra_trigger_on_payment))
            {
                $this->saveArticle($formId, $SubmissionId, $row);
            }
		}
	}

	public function onRsformAfterConfirmPayment($SubmissionId)
	{
		require_once JPATH_ADMINISTRATOR . '/components/com_rsform/helpers/submissions.php';
		$submission = RSFormProSubmissionsHelper::getSubmission($SubmissionId, false);

		if ($submission)
		{
			if ($row = $this->getSettings($submission->FormId))
            {
	            if ($row->ra_trigger_on_payment)
	            {
		            $this->saveArticle($submission->FormId, $SubmissionId, $row);
	            }
            }
		}
	}

	private function getSeparator($formId) {
		$db = Factory::getDbo();
		// Load our form
		$query = $db->getQuery(true)
			->select($db->qn('MultipleSeparator'))
			->from($db->qn('#__rsform_forms'))
			->where($db->qn('FormId') . ' = ' . $db->q($formId));

		// Multiple items separator
		return str_replace(array('\n', '\r', '\t'), array("\n", "\r", "\t"), $db->setQuery($query)->loadResult());
	}

	private function saveArticle($formId, $SubmissionId, $row)
    {
        // For convenience
	    $merge_vars = $row->ra_merge_vars;

	    // Get placeholders
	    list($replace, $with) = RSFormProHelper::getReplacements($SubmissionId);

	    $db = Factory::getDbo();

	    foreach ($merge_vars as $var => $value)
	    {
		    if ($var == 'joomla_fields')
		    {
			    // See if multiple selection fields are being used so we can send the correct data
			    $allFields = array();
			    foreach (array_values($value) as $v)
			    {
				    if ($v && preg_match('/{(.*?):.*}/is', $v, $match))
				    {
					    $allFields[] = $match[1];
				    }
			    }

			    $multiplePlaceholders = array();
			    if ($allFields)
			    {
				    $query = $db->getQuery(true)
					    ->select($db->qn('c.ComponentId'))
					    ->from($db->qn('#__rsform_components', 'c'))
					    ->join('left', $db->qn('#__rsform_properties', 'p') . ' ON (' . $db->qn('c.ComponentId') . ' = ' . $db->qn('p.ComponentId') . ')')
					    ->where($db->qn('c.FormId') . ' = ' . $db->q($formId))
					    ->where($db->qn('p.PropertyName') . ' = ' . $db->q('NAME'))
					    ->where($db->qn('p.PropertyValue') . ' IN (' . implode(',', $db->q($allFields)) . ')');

				    if ($componentIds = $db->setQuery($query)->loadColumn())
				    {
					    if ($all_data = RSFormProHelper::getComponentProperties($componentIds))
					    {
						    // Multiple items separator
						    $separator = $this->getSeparator($formId);

						    foreach ($all_data as $componentId => $property)
						    {
							    if (isset($property['ITEMS']))
							    {
								    $pos = array_search('{' . $property['NAME'] . ':value}', $replace);

								    if ($pos !== false)
								    {
									    $multiplePlaceholders['{' . $property['NAME'] . ':value}'] = strlen($separator) ? explode($separator, $with[$pos]) : $with[$pos];
								    }
							    }
							    elseif (isset($property['FILESSEPARATOR']) && isset($property['MULTIPLE']) && $property['MULTIPLE'] === 'YES')
							    {
							    	$fileSeparator = $property['FILESSEPARATOR'];

								    foreach (array('value', 'path', 'localpath', 'filename', 'image', 'localimage') as $k)
								    {
									    $pos = array_search('{' . $property['NAME'] . ':' . $k . '}', $replace);

									    if ($pos !== false)
									    {
										    $multiplePlaceholders['{' . $property['NAME'] . ':' . $k . '}'] = explode($fileSeparator, $with[$pos]);
									    }
								    }
							    }
						    }
					    }
				    }
			    }

			    // Let's see which Joomla! fields need multiple values
			    $multipleJoomlaFields = $this->getMultipleJoomlaFields();
			    $calendarJoomlaFields = $this->getCalendarJoomlaFields();

			    foreach ($value as $k => $v)
			    {
				    if (strlen($v))
				    {
					    if ($multiplePlaceholders && in_array($k, $multipleJoomlaFields))
					    {
						    foreach ($multiplePlaceholders as $multiplePlaceholder => $arrayValues)
						    {
							    if (strpos($v, $multiplePlaceholder) !== false)
							    {
								    $merge_vars[$var][$k] = $arrayValues;

								    continue 2;
							    }
						    }
					    }

					    $merge_vars[$var][$k] = str_replace($replace, $with, $v);

					    if (in_array($k, $calendarJoomlaFields))
						{
							try
							{
								$merge_vars[$var][$k] = Factory::getDate($merge_vars[$var][$k], Factory::getUser()->getTimezone())->toSql();
							}
							catch (Exception $e)
							{
								$merge_vars[$var][$k] = '';
							}
						}
				    }
			    }
		    }
		    else
		    {
			    if (strlen($value))
			    {
					$merge_vars[$var] = str_replace($replace, $with, $value);

			    	if (in_array($var, array('created', 'publish_up', 'publish_down')))
					{
						$merge_vars[$var] = str_replace($replace, $with, $value);

						try
						{
							$merge_vars[$var] = Factory::getDate($merge_vars[$var], Factory::getUser()->getTimezone())->toSql();
						}
						catch (Exception $e)
						{
							$merge_vars[$var] = '';
						}
					}
			    }
		    }
	    }

	    // check and replace scripting accordingly in the content
	    if (strpos($row->ra_content, '{/if}') !== false)
	    {
		    require_once JPATH_ADMINISTRATOR . '/components/com_rsform/helpers/scripting.php';
		    RSFormProScripting::compile($row->ra_content, $replace, $with);
	    }

	    // replace placeholders in the content
	    $row->ra_content = str_replace($replace, $with, $row->ra_content);

	    $article_instance = RSFormProArticles::getInstance();

	    // merge the vars with the ones that are changed by the user in the script area
	    $merge_vars = array_merge($merge_vars, $article_instance->args);


		if (isset($merge_vars['tags']) && strlen($merge_vars['tags']) > 0) {
			// replace the configured separator with the comma
			$merge_vars['tags'] = str_replace($this->getSeparator($formId), ',', $merge_vars['tags']);
			$merge_vars['tags'] = explode(',', $merge_vars['tags']);
			// trim for spaces each tag
			$merge_vars['tags'] = array_map('trim', $merge_vars['tags']);
		}

	    try
	    {
		    $article_instance->saveArticle($merge_vars, $row->ra_content, $this->getJsonElements(), $row->ra_trigger_plugins);
	    }
	    catch(Exception $e)
	    {
		    if ($row->ra_show_front_messages)
		    {
			    Factory::getApplication()->enqueueMessage($e->getMessage(), 'warning');
		    }
	    }
    }

    private function getCalendarJoomlaFields()
	{
		static $cache;

		if (!is_array($cache))
		{
			$cache = array();

			// Load the helper
			JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
			if ($fields = FieldsHelper::getFields('com_content.article'))
			{
				foreach ($fields as $field)
				{
					if ($field->type == 'calendar')
					{
						$cache[] = $field->name;
					}
				}
			}
		}

		return $cache;
	}

	private function getMultipleJoomlaFields()
	{
		static $cache;

		if (!is_array($cache))
		{
			$cache = array();

			// Load the helper
			JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
			if ($fields = FieldsHelper::getFields('com_content.article'))
			{
				foreach ($fields as $field)
				{
					if ($field->type == 'checkboxes' || (!empty($field->fieldparams) && $field->fieldparams->get('multiple')))
					{
						$cache[] = $field->name;
					}
				}
			}
		}

		return $cache;
	}

	private function getFieldLabel($name)
	{
		static $cache;

		if (!is_array($cache))
		{
			$cache = array();

			JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
			if ($fields = FieldsHelper::getFields('com_content.article'))
			{
				foreach ($fields as $field)
				{
					$cache[$field->name] = RSFormProHelper::htmlEscape($field->label) . ' (<small>' . RSFormProHelper::htmlEscape($field->name) . '</small>)';
				}
			}
		}

		return isset($cache[$name]) ? $cache[$name] : $name;
	}

	/**
	 * Handle uninstall
	 *
	 * @param $formId
	 */
	public function onRsformFormDelete($formId)
	{
		if ($row = $this->getTable())
		{
			$row->delete($formId);
		}
	}

	/**
	 * Handle Form Backup
	 *
	 * @param $form
	 * @param $xml
	 * @param $fields
	 */
	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('articles');
				foreach ($data as $property => $value)
				{
					$xml->add($property, $value);
				}
				$xml->add('/articles');
			}
		}
	}

	/**
	 * Handle Form Restores
	 *
	 * @param $form
	 * @param $xml
	 * @param $fields
	 */
	public function onRsformFormRestore($form, $xml, $fields)
	{
		if (isset($xml->articles))
		{
			$data = array(
				'form_id' => $form->FormId
			);

			foreach ($xml->articles->children() as $property => $value)
			{
				$data[$property] = (string) $value;
			}

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

	/**
	 * Truncate tables on restores
	 */
	public function onRsformBackendFormRestoreTruncate()
	{
		Factory::getDbo()->truncateTable('#__rsform_articles');
	}

	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();
			}
		}
	}
}

class RSFormProArticles
{
	public $args = array();

	public function setArgs($args)
	{
		$this->args = $args;
	}

	public static function getInstance()
	{
		static $inst;
		if (!$inst)
		{
			$inst = new RSFormProArticles;
		}

		return $inst;
	}

	public function saveArticle($args, $content = '', $json_elements = array(), $triggerPlugins = 1)
    {
		// init the article
		$article        = new stdClass();
	    $app            = Factory::getApplication();
		$unicode_slug   = Factory::getConfig()->get('unicodeslugs');
		$images 		= isset($json_elements['images']) ? $json_elements['images'] : array();
		$urls 			= isset($json_elements['urls']) ? $json_elements['urls'] : array();
		$metadata 		= isset($json_elements['metadata']) ? $json_elements['metadata'] : array();
		$joomla_fields 	= isset($json_elements['joomla_fields']) ? $json_elements['joomla_fields'] : array();
		$attribs 		= isset($json_elements['attribs']) ? $json_elements['attribs'] : array();

		$images_found 		 = array();
		$urls_found 		 = array();
		$metadata_found 	 = array();
		$joomla_fields_found = array();

		// start the attribs for the article
		$article->attribs = array_fill_keys($attribs, '');
		$article->attribs = (object) $article->attribs;

		$tags = array();
		$can_create_tags = Factory::getUser()->authorise('core.create', 'com_tags');

		if (isset($args['tags']) && !empty($args['tags']) && $can_create_tags) {
			// hold the tags
			$tags = $args['tags'];

			// refactor the tags prefixing them with #new#
			foreach ($tags as $i =>$tag) {
				$tags[$i] = '#new#'.$tag;
			}
		}

		// remove them from args because we are not using them
		if (isset($args['tags'])) {
			unset($args['tags']);
		}

		foreach ($args as $var => $value)
		{
			if ($var == 'joomla_fields')
			{
				foreach ($value as $k => $v)
				{
					if ((!empty($v) || strlen($v)) && in_array($k, $joomla_fields))
					{
						$joomla_fields_found[$k] = $v;
					}
				}

				continue;
			}

			if (!strlen($value))
			{
				continue;
			}

			// check for images related vars
			if (in_array($var, $images))
			{
				$images_found[$var] = $value;
				continue;
			}

			// check for urls related vars
			if (in_array($var, $urls))
			{
				$urls_found[$var] = $value;
				continue;
			}

			// check for metadata related vars
			if (in_array($var, $metadata))
			{
				$metadata_found[$var] = $value;
				continue;
			}

			// check for article attribs related vars
			if (in_array($var, $attribs))
			{
				$article->attribs->$var = (string) $value;
				continue;
			}

			// filter the alias if specified
			if ($var == 'alias')
			{
				$value = $unicode_slug ?  OutputFilter::stringURLUnicodeSlug($value) : OutputFilter::stringURLSafe($value);
			}

			// filter the catid
			if ($var == 'catid')
			{
				$value = (int) $value;

				// Check if the category exists
				JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

				$catid = CategoriesHelper::validateCategoryId($value, 'com_content');

				if ($catid == 0)
				{
					throw new Exception(Text::_('PLG_SYSTEM_RSFP_ARTICLES_ERROR_INVALID_CATEGORY'));
				}
			}

			$article->{$var} = $value;
		}

		// make the attribs a json string
		$article->attribs = json_encode($article->attribs);

		// if the alias is not mapped or empty value built it from the title
		if (empty($article->alias) && !empty($article->title))
		{
			$article->alias = $unicode_slug ?  OutputFilter::stringURLUnicodeSlug($article->title) : OutputFilter::stringURLSafe($article->title);
		}

	    $article->articletext = $content;

		// All the checks that we can perform for the newly created article object
		// -- in case the catid is not mapped
		if (empty($article->catid))
		{
			throw new Exception(Text::_('PLG_SYSTEM_RSFP_ARTICLES_ERROR_CATEGORY_NOT_SPECIFIED'));
		}

		if (empty($article->title))
		{
			throw new Exception(Text::_('PLG_SYSTEM_RSFP_ARTICLES_ERROR_TITLE_NOT_SPECIFIED'));
		}

		// check if the language mapped exist
		if (!empty($article->language) && $article->language !== '*')
		{
			if (!LanguageHelper::exists($article->language))
			{
				throw new Exception(Text::_('PLG_SYSTEM_RSFP_ARTICLES_ERROR_INVALID_LANGUAGE'));
			}
		}

		// check the access level selected
		if (!empty($article->access))
		{
			$article->access = (int) $article->access;

			if (!in_array($article->access, $this->getAllViewLevels()))
			{
				throw new Exception(Text::_('PLG_SYSTEM_RSFP_ARTICLES_ERROR_INVALID_ACCESS_LEVEL'));
			}
		}
		else
		{
			$article->access = 1;
		}

		// ---- JSON Fields ----
		// must add the other vars for images even if they are not set
		foreach ($images as $key) {
			if (!isset($images_found[$key])) {
				$images_found[$key] = '';
			} else if (isset($images_found[$key]) && ($key == 'image_fulltext' || $key == 'image_intro')) {
				// clean the images so that relative path is saved (for migration purpose)
				$images_found[$key] = str_replace(array(JPATH_SITE.DIRECTORY_SEPARATOR, Uri::base()), '', $images_found[$key]);
			}
		}

		// add the images to the article
		$images_found = (object) $images_found;
		$article->images = json_encode($images_found);


		// must add the other vars for urls even if they are not set
		foreach($urls as $key) {
			if (!isset($urls_found[$key])) {
				$urls_found[$key] = '';
			} else if (isset($urls_found[$key]) && ($key == 'urla' || $key == 'urlb' || $key == 'urlc')){
				// if the url entered is not a valid url make the value empty
				if (!$this->validUrl($urls_found[$key])) {
					$urls_found[$key] = '';
				}
			}
		}

		// add the images to the article
		$urls_found = (object) $urls_found;
		$article->urls = json_encode($urls_found);

		// must add the other vars for metadata even if they are not set
		foreach($metadata as $key) {
			if (!isset($metadata_found[$key])) {
				$metadata_found[$key] = '';
			}
		}

		// add the images to the article
		$metadata_found = (object) $metadata_found;
		$article->metadata = json_encode($metadata_found);

		// ---- END JSON Fields ----

		// check to see if the article is set as featured
		if (!empty($article->featured)) {
			$article->featured = 1;
		} else {
			$article->featured = 0;
		}

		// -- check if the alias already exists
		$table = Table::getInstance('Content');

		if ($table->load(array('alias' => $article->alias, 'catid' => $article->catid)))
		{
			$article->alias = $this->generateNewAlias($table, $article->catid, $article->alias);
		}

		// if there is no language mapped add the default 'ALL'
		if (empty($article->language)) {
			$article->language = '*';
		}

		// add a date to publish_up if the state is 1
		if (!empty($article->state) && empty($article->publish_up))
		{
			$article->publish_up = Factory::getDate()->toSql();
		}

		// save the article
		$article = (array) $article; // needs to be an array
		// in case there is a check for aliases then an id is loaded
		if (!empty($table->id)) {
			$table->id = null;
		}
		// bind the article data to the table object
		$table->bind($article);

		// do the internal checks
		if (!$table->check())
		{
			throw new Exception($table->getError());
		}

		if ($triggerPlugins)
        {
	        // Import plugins
	        PluginHelper::importPlugin('content');

	        // Set default context
	        $context = 'com_content.article';

	        // Trigger the before save event.
	        $result = $app->triggerEvent('onContentBeforeSave', array($context, $table, true, $article));

	        if (in_array(false, $result, true))
	        {
		        return false;
	        }
        }

		// handle the tags here
		if (!empty($tags) && $can_create_tags) {
			$table->newTags = $tags;
		}

		// store the article
		if ($table->store())
		{
			// if the article is marked as featured need to add it to frontpage content, will use the content model from the backend
			if ($article['featured'])
			{
				$this->featured($table->id, 1);
			}

			if ($joomla_fields_found)
			{
				// Emulate
				$data = array('com_fields' => $joomla_fields_found);

				// Load the model
				BaseDatabaseModel::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_fields/models', 'FieldsModel');
				$model = BaseDatabaseModel::getInstance('Field', 'FieldsModel', array('ignore_request' => true));

				// Load the helper
				JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
				$fields = FieldsHelper::getFields('com_content.article');

				// Loop over the fields
				foreach ($fields as $field)
				{
					// Determine the value if it is (un)available from the data
					if (key_exists($field->name, $data['com_fields']))
					{
						$value = $data['com_fields'][$field->name] === false ? null : $data['com_fields'][$field->name];
					}
					// Field not available on form, use stored value
					else
					{
						$value = isset($field->rawvalue) ? $field->rawvalue : null;
					}

					// If no value set (empty) remove value from database
					if (is_array($value) ? !count($value) : !strlen($value))
					{
						$value = null;
					}

					// JSON encode value for complex fields
					if (is_array($value) && (count($value, COUNT_NORMAL) !== count($value, COUNT_RECURSIVE) || !count(array_filter(array_keys($value), 'is_numeric'))))
					{
						$value = json_encode($value);
					}

					// Setting the value for the field and the item
					$model->setFieldValue($field->id, $table->id, $value);
				}
			}

			if ($triggerPlugins)
            {
	            // Trigger the after save event.
	            $app->triggerEvent('onContentAfterSave', array($context, $table, true, $article));
            }

			if (version_compare(JVERSION, '4.0', '>='))
			{
				$workflow = new Joomla\CMS\Workflow\Workflow('com_content.article');
				$stage_id = $workflow->getDefaultStageByCategory($table->catid);
				$workflow->createAssociation($table->id, $stage_id);
			}
		}
		else
		{
			throw new Exception($table->getError());
		}

		return true;
	}

	private function featured($pks, $value = 1)
    {
	    // Sanitize the ids.
	    $pks = (array) $pks;
	    $pks = array_map('intval', $pks);

        if (file_exists(JPATH_ADMINISTRATOR . '/components/com_content/src/Table/FeaturedTable.php'))
        {
            require_once JPATH_ADMINISTRATOR . '/components/com_content/src/Table/FeaturedTable.php';

	        $table = Table::getInstance('FeaturedTable', 'Joomla\\Component\\Content\\Administrator\\Table\\');
        }
        else
        {
	        Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_content/tables');

	        $table = Table::getInstance('Featured', 'ContentTable');
        }

	    try
	    {
		    $db = Factory::getDbo();
		    $query = $db->getQuery(true)
			    ->update($db->quoteName('#__content'))
			    ->set('featured = ' . (int) $value)
			    ->where('id IN (' . implode(',', $pks) . ')');
		    $db->setQuery($query);
		    $db->execute();

		    if ((int) $value == 0)
		    {
			    // Adjust the mapping table.
			    // Clear the existing features settings.
			    $query = $db->getQuery(true)
				    ->delete($db->quoteName('#__content_frontpage'))
				    ->where('content_id IN (' . implode(',', $pks) . ')');
			    $db->setQuery($query);
			    $db->execute();
		    }
		    else
		    {
			    // First, we find out which of our new featured articles are already featured.
			    $query = $db->getQuery(true)
				    ->select('f.content_id')
				    ->from('#__content_frontpage AS f')
				    ->where('content_id IN (' . implode(',', $pks) . ')');
			    $db->setQuery($query);

			    $oldFeatured = $db->loadColumn();

			    // We diff the arrays to get a list of the articles that are newly featured
			    $newFeatured = array_diff($pks, $oldFeatured);

			    // Featuring.
			    $tuples = array();

			    foreach ($newFeatured as $pk)
			    {
				    $tuples[] = $pk . ', 0';
			    }

			    if (count($tuples))
			    {
				    $columns = array('content_id', 'ordering');
				    $query = $db->getQuery(true)
					    ->insert($db->quoteName('#__content_frontpage'))
					    ->columns($db->quoteName($columns))
					    ->values($tuples);
				    $db->setQuery($query);
				    $db->execute();
			    }
		    }
	    }
	    catch (Exception $e)
	    {
		    Factory::getApplication()->enqueueMessage($e->getMessage(), 'warning');
	    }

	    $table->reorder();

	    return true;
    }
	
	protected function validUrl($url)
	{
		try
		{
			// URLs need a scheme to be valid
			if (!preg_match('/^(https?):\/\//i', $url, $match))
			{
				$url = 'http://'.$url;
			}
			
			// But too many schemes don't do
			if (substr_count($url, '://') > 1)
			{
				return false;
			}
			
			// Let's encode utf-8 characters
			$url = PunycodeHelper::urlToPunycode($url);
			
			// Let's use the Joomla! Uri to grab the host
			$uri = Uri::getInstance($url);
			$host = $uri->getScheme().'://'.$uri->getHost();
			
			// Now FILTER_VALIDATE_URL should suffice
			if (filter_var($host, FILTER_VALIDATE_URL))
			{
				return true;
			}
			
			return false;
		}
		catch (Exception $e)
		{
			return false;
		}
	}

	protected function getAllViewLevels() {
		// Only load the view levels once.
		static $viewLevels = array();

		if (empty($viewLevels))
		{
			// Get a database object.
			$db = Factory::getDbo();

			// Build the base query.
			$query = $db->getQuery(true)
				->select('id')
				->from($db->qn('#__viewlevels'));

			// Set the query for execution.
			$db->setQuery($query);

			// Build the view levels array.
			foreach ($db->loadAssocList() as $level)
			{
				$viewLevels[] = (int) $level['id'];
			}
		}

		return $viewLevels;
	}

	/**
	 * Generate new alias that is not in the database
	 */
	protected function generateNewAlias($table, $category_id, $alias)
	{
		while ($table->load(array('alias' => $alias, 'catid' => $category_id)))
		{
			$alias = StringHelper::increment($alias, 'dash');
		}

		return $alias;
	}
}