first commit

This commit is contained in:
2026-02-08 21:16:11 +01:00
commit e17b7026fd
8881 changed files with 1160453 additions and 0 deletions

View File

@@ -0,0 +1,156 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
// import Joomla modelform library
jimport('joomla.application.component.modeladmin');
/**
* Campaign Model Class
*/
class ConvertFormsModelCampaign extends JModelAdmin
{
/**
* Returns a reference to the a Table object, always creating it.
*
* @param type The table type to instantiate
* @param string A prefix for the table class name. Optional.
* @param array Configuration array for model. Optional.
* @return JTable A database object
* @since 2.5
*/
public function getTable($type = 'Campaign', $prefix = 'ConvertFormsTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
/**
* Method to get the record form.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
* @return mixed A JForm object on success, false on failure
* @since 2.5
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm('com_convertforms.campaign', 'campaign', array('control' => 'jform', 'load_data' => $loadData));
if (empty($form))
{
return false;
}
return $form;
}
/**
* Method to get the data that should be injected in the form.
*
* @return mixed The data for the form.
*/
protected function loadFormData()
{
// Check the session for previously entered form data.
$data = JFactory::getApplication()->getUserState('com_convertforms.edit.campaign.data', array());
if (empty($data))
{
$data = $this->getItem();
}
return $data;
}
/**
* Method to validate form data.
*/
public function validate($form, $data, $group = null)
{
$newdata = array();
$params = array();
$this->_db->setQuery('SHOW COLUMNS FROM #__convertforms_campaigns');
$dbkeys = $this->_db->loadObjectList('Field');
$dbkeys = array_keys($dbkeys);
foreach ($data as $key => $val)
{
if (in_array($key, $dbkeys))
{
$newdata[$key] = $val;
}
else
{
$params[$key] = $val;
}
}
$newdata['params'] = json_encode($params);
return $newdata;
}
/**
* [getItem description]
*
* @param [type] $pk [description]
*
* @return [type] [description]
*/
public function getItem($pk = null)
{
if ($item = parent::getItem($pk))
{
$params = $item->params;
if (is_array($params) && count($params))
{
foreach ($params as $key => $value)
{
if (!isset($item->$key) && !is_object($value))
{
$item->$key = $value;
}
}
unset($item->params);
}
}
return $item;
}
/**
* Method to copy an item
*
* @access public
* @return boolean True on success
*/
function copy($id)
{
$item = $this->getItem($id);
unset($item->_errors);
$item->id = 0;
$item->published = 0;
$item->name = JText::sprintf('NR_COPY_OF', $item->name);
$item = $this->validate(null, (array) $item);
return ($this->save($item));
}
}

View File

@@ -0,0 +1,145 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
class ConvertFormsModelCampaigns extends JModelList
{
/**
* Constructor.
*
* @param array An optional associative array of configuration settings.
*
* @see JController
*/
public function __construct($config = array())
{
if (empty($config['filter_fields']))
{
$config['filter_fields'] = array(
'id', 'a.id',
'state', 'a.state',
'created', 'a.created',
'search',
'ordering', 'a.ordering',
'service', 'a.service',
'name','a.name',
'leads', 'issues'
);
}
parent::__construct($config);
}
/**
* Method to auto-populate the model state.
*
* This method should only be called once per instantiation and is designed
* to be called on the first call to the getState() method unless the model
* configuration flag to ignore the request is set.
*
* Note. Calling getState in this method will result in recursion.
*
* @param string $ordering An optional ordering field.
* @param string $direction An optional direction (asc|desc).
*
* @return void
*
* @since 3.7.0
*/
protected function populateState($ordering = 'a.id', $direction = 'desc')
{
// List state information.
parent::populateState($ordering, $direction);
}
/**
* Method to build an SQL query to load the list data.
*
* @return string An SQL query
*/
protected function getListQuery()
{
// Create a new query object.
$db = JFactory::getDBO();
$query = $db->getQuery(true);
// Select some fields from the item table
$query
->select('a.*')
->from('#__convertforms_campaigns a');
// Filter State
$filter = $this->getState('filter.state');
if (is_numeric($filter))
{
$query->where('a.state = ' . ( int ) $filter);
}
else if ($filter == '')
{
$query->where('( a.state IN (0,1,2))');
}
// Filter the list over the search string if set.
$search = $this->getState('filter.search');
if (!empty($search))
{
if (stripos($search, 'id:') === 0)
{
$query->where('a.id = ' . ( int ) substr($search, 3));
}
else
{
$search = $db->quote('%' . $db->escape($search, true) . '%');
$query->where(
'( `name` LIKE ' . $search . ' )'
);
}
}
// Confirmed Total Leads
$query->select('
(select count(c.id) from #__convertforms_conversions as c where c.campaign_id = a.id) as leads'
);
// Add the list ordering clause.
$orderCol = $this->state->get('list.ordering', 'a.id');
$orderDirn = $this->state->get('list.direction', 'desc');
$query->order($db->escape($orderCol . ' ' . $orderDirn));
return $query;
}
/**
* [getItems description]
*
* @return object
*/
public function getItems()
{
$items = parent::getItems();
foreach ($items as $key => $item)
{
if (!$item->params)
{
continue;
}
$params = json_decode($item->params);
$items[$key] = (object) array_merge((array) $item, (array) $params);
unset($items[$key]->params);
}
return $items;
}
}

View File

@@ -0,0 +1,558 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Filter\InputFilter;
use ConvertForms\Form;
use ConvertForms\Helper;
use ConvertForms\FieldsHelper;
defined('_JEXEC') or die('Restricted access');
// import Joomla modelform library
jimport('joomla.application.component.modeladmin');
/**
* Conversion Model Class
*/
class ConvertFormsModelConversion extends JModelAdmin
{
/**
* The database object
*
* @var object
*/
private $db;
/**
* Constructor.
*
* @param array $config An optional associative array of configuration settings.
*
* @see JModelLegacy
* @since 1.6
*/
public function __construct($config = array())
{
parent::__construct($config);
$this->db = JFactory::getDbo();
// Make sure our plugins are loaded. Without this line, the PDF plugin won't be able to catch the onContentAfterSave event.
JPluginHelper::importPlugin('convertformstools');
}
/**
* Returns a reference to the a Table object, always creating it.
*
* @param type The table type to instantiate
* @param string A prefix for the table class name. Optional.
* @param array Configuration array for model. Optional.
* @return JTable A database object
* @since 2.5
*/
public function getTable($type = 'Conversion', $prefix = 'ConvertFormsTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
/**
* Allows preprocessing of the JForm object.
*
* @param JForm $form The form object
* @param array $data The data to be merged into the form object
* @param string $group The plugin group to be executed
*
* @return void
*
* @since 3.6.1
*/
protected function preprocessForm(Joomla\CMS\Form\Form $form, $data, $group = 'content')
{
if (!isset($data->params))
{
return parent::preprocessForm($form, $data, $group);
}
// Ensure the form binds the data regardless the letter case of the field's name.
// We should not rely on the field's name. Instead we need to switch over to field's IDs instead.
$data->params = array_change_key_case($data->params);
// @todo - What we do here is somehow a joke. We should consider moving the logic of preparing each field to the respective field class in the namespace.
$data_ = clone $data;
$this->prepare($data_);
// Add form custom fields to form
$fields = [];
foreach ($data_->prepared_fields as $key => $field)
{
$type = $field->options->get('type');
// Map of fields types that need to be transformed in order to be recognized by the XML parser.
$transformFields = [
'hidden' => 'text',
'currency' => 'NR_Currencies',
'country' => 'NR_Geo',
'checkbox' => 'checkboxes',
'dropdown' => 'list',
'fileupload' => 'textlist',
'confirm' => $field->options->get('confirm_type')
];
if ($type == 'fileupload')
{
$limit_files = $field->options->get('limit_files');
if (!isset($limit_files) || (isset($limit_files) && $limit_files == '1'))
{
$transformFields['fileupload'] = 'text';
// In case the previous multiple field is turn into a single field, we need to transform the value from array to string too.
if (is_array($data->params[$key]))
{
$data->params[$key] = implode(',', $data->params[$key]);
}
}
}
if (array_key_exists($type, $transformFields))
{
$type = $transformFields[$type];
}
// Radio fields doesn't accept Array as a value and we need to transform it into a string.
if (in_array($type, ['radio']))
{
if (isset($data->params[$key]))
{
$data->params[$key] = implode('', (array) $data->params[$key]);
}
}
// Create the field
$label = $field->class->getLabel();
$fld = new SimpleXMLElement('<field/>');
$fld->addAttribute('name', $key);
$fld->addAttribute('type', $type);
$fld->addAttribute('label', $label);
$fld->addAttribute('hint', $field->options->get('placeholder', $label));
$fld->addAttribute('description', $fld->attributes()->hint);
$fld->addAttribute('class', 'input-xlarge');
$fld->addAttribute('rows', 10); // Used for textarea inputs
$fld->addAttribute('filter', $field->options->get('filter', 'safehtml'));
if ($type == 'editor')
{
$fld->addAttribute('editor', $field->options->get('editor'));
}
// Define options to list-based fields
if (in_array($type, ['list', 'radio', 'checkboxes']) && $choices = $field->class->getOptions())
{
if ($type == 'list' && $hint = $field->options->get('placeholder'))
{
array_unshift($choices, [
'label' => trim($hint),
'value' => '',
'selected' => true
]);
}
foreach ($choices as $choice)
{
$option = $fld->addChild('option', htmlspecialchars($choice['label']));
$option->addAttribute('value', strip_tags($choice['value']));
}
}
// Get field's XML
$fields[] = str_replace('<?xml version="1.0"?>', '', $fld->asXml());
}
$form->setField(new SimpleXMLElement('
<fieldset name="params">
<fields name="params">
' . implode('', $fields) . '
</fields>
</fieldset>
'));
parent::preprocessForm($form, $data, $group);
}
/**
* Method to get the record form.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
* @return mixed A JForm object on success, false on failure
* @since 2.5
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm('com_convertforms.conversion', 'conversion', array('control' => 'jform', 'load_data' => $loadData));
if (empty($form))
{
return false;
}
return $form;
}
/**
* Method to get the data that should be injected in the form.
*
* @return mixed The data for the form.
*/
protected function loadFormData()
{
// Check the session for previously entered form data.
$data = JFactory::getApplication()->getUserState('com_convertforms.edit.conversion.data', array());
if (empty($data))
{
$data = $this->getItem(null, false);
}
return $data;
}
/**
* Validate data before saving
*
* @param object $form The form to validate
* @param object $data The data to validate
* @param string $group
*
* @return array The validated data
*/
public function validate($form, $data, $group = null)
{
// Validate conversion edited via the backend
if (JFactory::getApplication()->isClient('administrator'))
{
return parent::validate($form, $data, $group);
}
// Make sure we have a valid Form data
if (!isset($data['cf']) || empty($data['cf']))
{
throw new Exception('No submission data found');
}
// Make sure we have a valid Form ID passed
if (!isset($data['cf']['form_id']) || !$formid = (int) $data['cf']['form_id'])
{
throw new Exception('Form ID is either missing or invalid');
}
// Let the user manipulate the post data before saved into the database.
// @todo - Move PHP Scripts logic to a separate plugin.
$payload = ['post' => &$data['cf']];
Form::runPHPScript($formid, 'formprocess', $payload);
// Get form from payload or load a new instance
$form = isset($payload['form']) ? $payload['form'] : Form::load($formid);
$error_message = null;
$result = JFactory::getApplication()->triggerEvent('onConvertFormsSubmissionValidate', [&$data['cf'], &$error_message, $form]);
if (in_array(false, $result, true))
{
throw new \Exception(is_null($error_message) ? 'Error' : $error_message);
}
// Honeypot check
if (isset($data['cf']['hnpt']) && !empty($data['cf']['hnpt']))
{
throw new Exception('Honeypot field triggered');
die();
}
// Make sure the right form is loaded
if (is_null($form['id']))
{
throw new Exception('Unknown Form');
}
// Initialize the object that is going to be saved in the database
$newData = [
'form_id' => $formid,
'campaign_id' => (int) $form['params']['campaign'],
'state' => isset($form['params']['submission_state']) ? $form['params']['submission_state'] : 1
];
$overrides = isset($data['overrides']) ? json_decode($data['overrides']) : [];
// Let's validate submitted data
foreach ($form['fields'] as $key => $form_field)
{
$field_name = isset($form_field['name']) ? $form_field['name'] : null;
$field_class = FieldsHelper::getFieldClass($form_field['type'], $form_field, $data);
$user_value = (!is_null($field_name) && isset($data['cf'][$field_name])) ? $data['cf'][$field_name] : null;
// Check if the field must be ignored and not be validated. Eg: hidden by conditional logic.
if (isset($overrides->ignore) && is_array($overrides->ignore) && in_array($form_field['key'], $overrides->ignore))
{
continue;
}
// Validate and Filter user value. If an error occurs the submission aborts with an exception shown in the form
$field_class->validate($user_value);
// Skip unknown fields or fields with an empty value
if (!$field_name || $user_value == '')
{
continue;
}
$newData['params'][$field_name] = $user_value;
}
return $newData;
}
/**
* Create a new conversion based on the post data.
*
* @return object The new conversion row object
*/
public function createConversion($data)
{
JPluginHelper::importPlugin('convertforms');
JPluginHelper::importPlugin('convertformstools');
JPluginHelper::importPlugin('system');
// Validate data
$data = $this->validate(null, $data);
/**
* This event is rather useful for the following reasons:
*
* 1. It allows us to make modifications to the submission after it passes the validation checks.
* 2. It allows us to access and modify submission properties such as 'state' and 'form_id'. Eg: Store all submissions unpublished by default.
*
* We may support this event in the PHP Scripts section too.
*/
JFactory::getApplication()->triggerEvent('onConvertFormsSubmissionBeforeSave', [&$data]);
$form_data = Form::load($data['form_id']);
$submission = null;
// If we are not saving the data to the database, mock the submission in order to be used as expected.
if (isset($form_data['params']['save_data_to_db']) && $form_data['params']['save_data_to_db'] == '0')
{
$submission = (object) array_merge($form_data, $data);
$submission->id = 'unsaved_submission_' . uniqid();
$submission->user_id = 0;
$submission->created = JFactory::getDate()->toSql();
$submission->modified = JFactory::getDbo()->getNullDate();
$this->prepareItem($submission);
JPluginHelper::importPlugin('convertforms');
JPluginHelper::importPlugin('convertformstools');
JFactory::getApplication()->triggerEvent('onConvertFormsConversionAfterSave', [$submission, $this, 1]);
}
else
{
// JSON_UNESCAPED_UNICODE encodes multibyte unicode characters literally.
// Without: Τάσος => \u03a4\u03ac\u03c3\u03bf\u03c2
// With: Τάσος => Τάσος
$data['params'] = json_encode($data['params'], JSON_UNESCAPED_UNICODE);
// Everything seems fine. Let's save data to the database.
if (!$this->save($data))
{
throw new Exception($this->getError());
}
$submission = $this->getItem();
}
// Run user's PHP script after the form has been processed, stored into the database and all addons have run.
// @todo - Move PHP Scripts logic into a separate plugin.
$payload = ['submission' => &$submission];
Form::runPHPScript($data['form_id'], 'afterformsubmission', $payload);
/**
* Why this event was created:
*
* - Due to the fact that we cannot hook into "onConvertFormsSubmissionAfterSave" and manipulate the $submission object.
* If we try to do so, the updated $submission wont find its way to the other listeners hooked to this event.
*
* When does this event run:
*
* - Right after the submission has been saved to the database.
* - Before other plugins hook to run their own code after the submission has been processed.
*
* When it should be used:
*
* - When we want to modify the submission object just before other listeners hook into "onConvertFormsSubmissionAfterSave"
* such as Email Notifications so they will get the updated $submission object.
*
* Example Use Case:
*
* - If we want to rename the uploaded files and use add the submission id to the filename, we must listen to this event,
* update the $submission object, rename the file, update the database and emails will use the updated file data.
*/
JFactory::getApplication()->triggerEvent('onConvertFormsSubmissionAfterSavePrepare', [&$submission]);
/**
* When does this event run:
*
* - At the end of the submission process, after the $submission object has been finalized and its ready to be given
* out to plugins/code that hook to this event.
*
* When it should be used:
*
* - We dont want to modify the $submission data and plan to execute our code after the form has been submitted
* successfully.
*
* Example Use Case:
* - Send Email Notifications
* - Submit data to Campaigns
*/
JFactory::getApplication()->triggerEvent('onConvertFormsSubmissionAfterSave', [&$submission]);
return $submission;
}
/**
* Get a conversion item
*
* @param interger $pk The conversion row primary key
* @param bool $prepare Whether to prepare the submission fields.
*
* @return object The conversion object
*/
public function getItem($pk = null, $prepare = true)
{
if (!$item = parent::getItem($pk))
{
return;
}
$this->prepareItem($item, $prepare);
return $item;
}
/**
* Prepares the submission item.
*
* @param object $item The submission item.
* @param bool $prepare Whether to prepare the submission fields.
*
* @return void
*/
protected function prepareItem(&$item, $prepare = true)
{
JPluginHelper::importPlugin('convertformstools');
// There's no need to change the timezone on the backend as the date properties are mainly used in the Calendar fields
// which are already modifying the timezone offset with the filter="user_utc" property.
if (JFactory::getApplication()->isClient('site'))
{
$item->created = Helper::formatDate($item->created);
$item->modified = Helper::formatDate($item->modified);
}
if ($item->user_id)
{
$item->user_name = JFactory::getUser($item->user_id)->name;
}
// Load Form & Campaign Model
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_convertforms/models', 'ConvertFormsModel');
$modelForm = JModelLegacy::getInstance('Form', 'ConvertFormsModel', ['ignore_request' => true]);
$modelCampaign = JModelLegacy::getInstance('Campaign', 'ConvertFormsModel', ['ignore_request' => true]);
$item->form = $modelForm->getItem($item->form_id);
$item->campaign = $modelCampaign->getItem($item->campaign_id);
// On J4 we get infinite loop if we inject the prepared fields to $data.
// Thus, we don't prepare the submission on this method in order to not pollute the $data object.
// Instead we use the preprocessForm() method with a cloned object.
if ($prepare)
{
$this->prepare($item);
}
return $item;
}
/**
* Prepares the submission by adding the submitted fields values.
*
* @param object $submission
*
* @return void
*/
public function prepare(&$submission)
{
if (!$submission || is_null($submission->id))
{
return;
}
// Note: Form may be already available in the $submission object.
if (!$form = Form::load($submission->form_id, false, true))
{
return;
}
$fields = [];
// Make sure we're manipualating an array.
$submission_params = array_change_key_case((array) $submission->params);
foreach ($form['fields'] as $field)
{
// Skip fields with no name like reCAPTCHA, HTML e.t.c
if (!isset($field['name']))
{
continue;
}
$field_name = strtolower($field['name']);
$submitted_value = isset($submission_params[$field_name]) ? $submission_params[$field_name] : '';
// Make sure the type of field is valid
if (!$class = FieldsHelper::getFieldClass($field['type'], $field))
{
continue;
}
$prepared_field = (object) [
'options' => new Registry($field),
'class' => $class,
'label' => isset($field['label']) && !empty($field['label']) ? JText::_($field['label']) : $field['name'],
'value' => $class->prepareValue($submitted_value),
'value_html' => $class->prepareValueHTML($submitted_value),
'value_raw' => $submitted_value
];
$fields[$field_name] = $prepared_field;
}
// @todo - Stop using 'prepare_fields' property and switch over to the standard 'fields' property.
$submission->prepared_fields = $fields;
}
}

View File

@@ -0,0 +1,531 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
/**
* Conversions Class
*/
class ConvertFormsModelConversions extends JModelList
{
/**
* Constructor.
*
* @param array An optional associative array of configuration settings.
*
* @see JController
*/
public function __construct($config = array())
{
if (empty($config['filter_fields']))
{
$config['filter_fields'] = array(
'id', 'a.id',
'state', 'a.state',
'created', 'a.created',
'search',
'campaign_id', 'a.campaign_id',
'form_id', 'a.form_id',
'created_from', 'created_to',
'columns', 'a.columns',
'period', 'a.period'
);
}
parent::__construct($config);
}
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @param string $ordering An optional ordering field.
* @param string $direction An optional direction (asc|desc).
*
* @return void
*
* @since 1.6
*/
protected function populateState($ordering = 'a.id', $direction = 'desc')
{
// Get the previously set form ID before populating the State.
$session = JFactory::getSession();
$registry = $session->get('registry');
$previous_form_id = $registry->get($this->context . '.filter.form_id');
// List state information.
parent::populateState($ordering, $direction);
$state = $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state');
$this->setState('filter.state', $state);
$formID = $this->getUserStateFromRequest($this->context . '.filter.form_id', 'filter_form_id', $this->getLastFormID());
$this->setState('filter.form_id', $formID);
$campaignID = $this->getUserStateFromRequest($this->context . '.filter.campaign_id', 'filter_campaign_id');
$this->setState('filter.campaign_id', $campaignID);
$period = $this->getUserStateFromRequest($this->context . '.filter.period', 'filter_period');
$this->setState('filter.period', $period);
$columns = $this->getUserStateFromRequest($this->context . '.filter.columns', 'filter_columns');
$columns = is_array($columns) ? array_filter($columns) : (array) $columns;
$sameForm = !is_null($previous_form_id) ? $previous_form_id == $formID : true;
// Get form fields from the database when the user has switched to another form using
// the search filters or when the filters frorm has been reset.
if (!$sameForm || empty($columns))
{
$columns = \ConvertForms\Helper::getColumns($formID);
// Pre-select the first 8 only
$columns = array_slice($columns, 0, 8);
}
$this->setState('filter.columns', $columns);
}
/**
* Allows preprocessing of the JForm object.
*
* @param JForm $form The form object
* @param array $data The data to be merged into the form object
* @param string $group The plugin group to be executed
*
* @return void
*
* @since 3.6.1
*/
protected function preprocessForm(Joomla\CMS\Form\Form $form, $data, $group = 'content')
{
if (!isset($data->filter))
{
$data->filter = [];
} else
{
if (is_object($data->filter))
{
$data->filter = (array) $data->filter;
}
}
$data->filter['form_id'] = $this->getState('filter.form_id');
$columns = $this->getState('filter.columns');
$data->filter['columns'] = $columns;
parent::preprocessForm($form, $data, $group);
}
/**
* Method to build an SQL query to load the list data.
*
* @return string An SQL query
*/
public function getListQuery()
{
// Create a new query object.
$db = JFactory::getDBO();
$query = $db->getQuery(true);
// Select some fields from the item table
$query
->select('a.*')
->from('#__convertforms_conversions a');
// Filter State
$filter = $this->getState('filter.state');
if ($filter !== 'skip')
{
if (is_numeric($filter))
{
$query->where($db->quoteName('a.state') . ' = ' . (int) $filter);
}
if (is_array($filter))
{
$query->where('(' . $db->quoteName('a.state') . ' IN (' . implode(',', $filter) . '))');
}
if (is_null($filter) || $filter == '')
{
$query->where('(a.state = 0 OR a.state = 1)');
}
}
// Join Forms Table
if ($this->getState('filter.join_forms') != 'skip')
{
$query->select("c.name as form_name");
$query->join('LEFT', $db->quoteName('#__convertforms', 'c') . ' ON
(' . $db->quoteName('a.form_id') . ' = ' . $db->quoteName('c.id') . ')');
}
// Filter the list over the search string if set.
$search = $this->getState('filter.search');
if (!empty($search))
{
if (stripos($search, 'id:') === 0)
{
$ids = str_replace('id:', '', $search);
$ids = array_map('trim', explode(',', $ids));
$query->where('a.id IN (' . implode(', ', (array) $ids) . ')');
} else
{
$query->where('a.params LIKE "%' . $search . '%" ');
}
}
// Filter by ID
if ($id = $this->getState('filter.id'))
{
$query->where('a.id IN (' . implode(', ', (array) $id) . ')');
}
// Filter by Campaign ID
if ($campaign_id = $this->getState('filter.campaign_id'))
{
$query->where('a.campaign_id IN (' . implode(', ', (array) $campaign_id) . ')');
}
// Filter Form
if ($form_id = $this->getState('filter.form_id'))
{
$query->where('a.form_id = ' . $form_id);
}
// Period
if ($period = $this->getState('filter.period'))
{
switch ($period)
{
case 'today':
$date_from = 'now';
$date_to = 'now';
break;
case 'yesterday':
$date_from = '-1 day';
$date_to = '-1 day';
break;
case 'this_week':
$date_from = 'monday this week';
$date_to = 'sunday this week';
break;
case 'this_month':
$date_from = 'first day of this month';
$date_to = 'last day of this month';
break;
case 'this_year':
$date_from = 'first day of January';
$date_to = 'last day of December';
break;
case 'last_week':
$date_from = 'monday previous week';
$date_to = 'sunday previous week';
break;
case 'last_month':
$date_from = 'first day of previous month';
$date_to = 'last day of previous month';
break;
case 'last_year':
$date_from = 'first day of January ' . (date('Y') - 1);
$date_to = 'last day of December ' . (date('Y') - 1);
break;
default:
$date_from = $this->getState('filter.created_from');
$date_to = $this->getState('filter.created_to');
break;
}
// MySQL optimizer won't use an index once a column in the WHERE clause is wrapped with a function.
// So we should never never never use MONTH(), YEAR(), DATE() methods again if we do care about performance.
if ($date_from)
{
$query->where($db->quoteName('a.created') . ' >= ' . $db->q(JHtml::date($date_from, 'Y-m-d 00:00:00')));
}
if ($date_to)
{
$query->where($db->quoteName('a.created') . ' <= ' . $db->q(JHtml::date($date_to, 'Y-m-d 23:59:59')));
}
}
// Filter User
$filter_user = $this->getState('filter.user_id');
if ($filter_user != '')
{
if (is_numeric($filter_user))
{
$query->where($db->quoteName('a.user_id') . ' = ' . $filter_user);
} else
{
$query->where('(' . $db->quoteName('a.state') . ' IN (' . $filter_user . '))');
}
}
// Add the list ordering clause.
$orderCol = $this->state->get('list.ordering', 'a.id');
$orderDirn = $this->state->get('list.direction', 'desc');
$query->order($db->escape($orderCol . ' ' . $orderDirn));
return $query;
}
/**
* Exports leads in CSV file
* Leads can be exported by passing either row IDs or Campaign IDs
*
* @param array $ids Array of row IDs
* @param array $campaign_ids Array of Campaign IDs
*
* @return void
*/
public function export($ids = array(), $campaign_ids = array(), $save_to = null)
{
// Increase memory size and execution time to prevent PHP errors on datasets > 20K
set_time_limit(300); // 5 Minutes
ini_set('memory_limit', '-1');
$filename = '';
if (is_array($ids) && count($ids))
{
$this->setState('filter.id', $ids);
}
if (is_array($campaign_ids) && count($campaign_ids))
{
$filename = '_Campaign' . $campaign_ids[0];
$this->setState('filter.state', 1);
$this->setState('filter.campaign_id', $campaign_ids);
} else
{
$this->setState('filter.state', 'skip');
}
$this->setState('filter.join_campaigns', 'skip');
$this->setState('filter.join_forms', 'skip');
$rows = $this->getItems();
$this->prepareRowsForExporting($rows);
$columns = array_keys($rows[0]);
$filename = 'ConvertForms_Submissions_' . $filename . '_' . date('Y-m-d') . '.csv';
$excel_security = (bool) ConvertForms\Helper::getComponentParams()->get('excel_security', true);
return $this->createCSV($rows, $columns, $excel_security, $filename, $save_to);
}
/**
* Prepares rows with their custom fields for exporting
*
* @param object &$rows The rows object
*
* @return void
*/
private function prepareRowsForExporting(&$rows)
{
$columns = array(
'id',
'created',
'name',
'email'
);
$rows_ = [];
// Find custom fields per row
foreach ($rows as $key => $row)
{
$rows_[$key]['id'] = $row->id;
$rows_[$key]['created'] = (string) $row->created;
foreach ($row->params as $pkey => $param)
{
$pkey = trim(strtolower($pkey));
if (strpos($pkey, 'sync_') !== false)
{
continue;
}
$value = is_array($param) ? implode(', ', $param) : $param;
$rows_[$key][$pkey] = $value;
if (!in_array($pkey, $columns))
{
array_push($columns, $pkey);
}
}
}
$rowsNew = array();
// Fix rows based on columns
foreach ($columns as $ckey => $column)
{
foreach ($rows_ as $rkey => $row)
{
$value = isset($row[$column]) ? $row[$column] : '';
// Remove newline characters to prevent the row from forcing a new line. We should integrate this fix in the Export class too.
$value = str_replace(["\r\n", "\n", "\r"], ' ', $value);
$rowsNew[$rkey][$column] = $value;
}
}
$rows = $rowsNew;
}
/**
* Create the CSV file
*
* CSV Injection info: https://vel.joomla.org/articles/2140-introducing-csv-injection
*
* @param array $rows CSV Rows to print
* @param array $columns CSV Columns to print
* @param boolean $excel_security If enabled, certain row values will be prefixed by a tab to avoid any CSV injection
*
* @return mixed
*/
public function createCSV($rows, $columns, $excel_security, $filename, $save_to = null)
{
$csvPath = is_null($save_to) ? 'php://output' : $save_to . $filename;
if (!$save_to)
{
// Create the downloadable file
$this->downloadFile($filename);
ob_start();
}
$output = fopen($csvPath, 'w');
// Support UTF-8 on Microsoft Excel
fputs($output, "\xEF\xBB\xBF");
fputcsv($output, $columns);
foreach ($rows as $key => $row)
{
// Prevent CSV Injection
if ($excel_security)
{
foreach ($row as $rowKey => &$rowValue)
{
$firstChar = substr($rowValue, 0, 1);
// Prefixe values starting with a =, +, - or @ by a tab character
if (in_array($firstChar, array('=', '+', '-', '@')))
{
$rowValue = ' ' . $rowValue;
}
}
}
fputcsv($output, $row);
}
fclose($output);
if ($save_to)
{
return $csvPath;
}
echo ob_get_clean();
die();
}
/**
* Sets propert headers to document to force download of the file
*
* @param string $filename Filename
*
* @return void
*/
public function downloadFile($filename)
{
// disable caching
$now = gmdate("D, d M Y H:i:s");
header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate");
header("Last-Modified: {$now} GMT");
// force download
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// disposition / encoding on response body
header("Content-Disposition: attachment;filename={$filename}");
header("Content-Transfer-Encoding: binary");
}
/**
* [getItems description]
*
* @return object
*/
public function getItems()
{
if (!$items = parent::getItems())
{
return [];
};
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_convertforms/models', 'ConvertFormsModel');
$submission_model = JModelLegacy::getInstance('Conversion', 'ConvertFormsModel', ['ignore_request' => true]);
foreach ($items as $key => $item)
{
$items[$key]->params = json_decode($item->params);
$item->created = \NRFramework\Functions::applySiteTimezoneToDate($item->created);
$submission_model->prepare($item);
}
return $items;
}
private function getLastFormID()
{
$model = JModelLegacy::getInstance('Forms', 'ConvertFormsModel', ['ignore_request' => true]);
$model->setState('list.limit', 1);
$model->setState('list.direction', 'asc');
$forms = $model->getItems();
return empty($forms) ? null : $forms[0]->id;
}
}

View File

@@ -0,0 +1,315 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
// import Joomla modelform library
jimport('joomla.application.component.modeladmin');
/**
* Item Model
*/
class ConvertFormsModelForm extends JModelAdmin
{
/**
* Returns a reference to the a Table object, always creating it.
*
* @param type The table type to instantiate
* @param string A prefix for the table class name. Optional.
* @param array Configuration array for model. Optional.
* @return JTable A database object
* @since 2.5
*/
public function getTable($type = 'Form', $prefix = 'ConvertFormsTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
/**
* Method to get the record form.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
* @return mixed A JForm object on success, false on failure
* @since 2.5
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm('com_convertforms.form', 'form', array('control' => 'jform', 'load_data' => $loadData));
if (empty($form))
{
return false;
}
return $form;
}
protected function preprocessForm(Joomla\CMS\Form\Form $form, $data, $group = 'content')
{
$files = array(
"form_design"
);
foreach ($files as $key => $value)
{
$form->loadFile($value, false);
}
// Call all ConvertForms plugins
JPluginHelper::importPlugin('convertforms');
// load translation strings
$this->loadTranslations();
parent::preprocessForm($form, $data, $group);
}
/**
* Enqueues translations for the back-end
*
* @return void
*/
private function loadTranslations()
{
JText::script('COM_CONVERTFORMS_SUBMISSION_ID');
JText::script('COM_CONVERTFORMS_SUBMISSION_DATE');
JText::script('COM_CONVERTFORMS_SUBMISSION_USER_ID');
JText::script('COM_CONVERTFORMS_SUBMISSION_CAMPAIGN_ID');
JText::script('COM_CONVERTFORMS_SUBMISSION_FORM_ID');
JText::script('COM_CONVERTFORMS_SUBMISSION_VISITOR_ID');
JText::script('COM_CONVERTFORMS_SUBMISSIONS_COUNT');
JText::script('COM_CONVERTFORMS_ALL_FIELDS');
JText::script('COM_CONVERTFORMS_ALL_FIELDS_NO_LABELS');
JText::script('COM_CONVERTFORMS_ALL_FILLED_ONLY_FIELDS');
}
/**
* Prepare form fieldsets by tab into an array
*
* @return array
*/
public function getTabs()
{
$form = $this->getForm();
// Tabs
$tabs = array(
"fields" => array(
"label" => "COM_CONVERTFORMS_FIELDS",
"icon" => "icon-list-2"
),
"design" => array(
"label" => "COM_CONVERTFORMS_DESIGN",
"icon" => "icon-picture"
),
"behavior" => array(
"label" => "COM_CONVERTFORMS_BEHAVIOR",
"icon" => "icon-options"
),
"conversion" => array(
"label" => "COM_CONVERTFORMS_SUBMISSION",
"icon" => "icon-generic"
)
);
foreach ($tabs as $key => $tab)
{
$tabs[$key]["fields"] = $this->getFieldsetbyTab($form, $key);
}
return $tabs;
}
/**
* Return form fieldsets by tab attribute
*
* @param JForm $form The form
* @param string $tab The tab name
*
* @return array Found fieldsets
*/
private function getFieldsetbyTab($form, $tab)
{
$fieldsets = $form->getXML()->fieldset;
$found = array();
foreach ($fieldsets as $key => $fieldset)
{
if ($tab == (string) $fieldset["tab"])
{
$found[] = $fieldset;
}
}
return $found;
}
public function getItem($pk = null)
{
if ($item = parent::getItem($pk)) {
$params = $item->params;
if (is_array($params) && count($params)) {
foreach ($params as $key => $value) {
if (!isset($item->$key) && !is_object($value)) {
$item->$key = $value;
}
}
unset($item->params);
}
}
return $item;
}
/**
* Method to get the data that should be injected in the form.
*
* @return mixed The data for the form.
*/
protected function loadFormData()
{
// Check the session for previously entered form data.
$data = JFactory::getApplication()->getUserState('com_convertforms.edit.form.data', array());
if (!empty($data))
{
$params = json_decode($data['params'], true);
$data = array_merge($data, $params);
unset($data['params']);
return $data;
}
// Load existing form template
if ($template = JFactory::getApplication()->input->get('template', null))
{
return ConvertForms\Helper::loadFormTemplate($template);
}
if (empty($data))
{
$data = $this->getItem();
if (is_null($data->name))
{
$data->name = JText::_('COM_CONVERTFORMS_UNTITLED_BOX');
}
}
return $data;
}
/**
* Method to save the form data.
*
* @param array The form data.
*
* @return boolean True on success.
* @since 1.6
*/
public function save($data)
{
$params = json_decode($data['params'], true);
if (is_null($params))
{
$params = array();
}
// Validate field options
foreach ($params['fields'] as $key => &$field)
{
if (!isset($field['type']))
{
continue;
}
$class = ConvertForms\FieldsHelper::getFieldClass($field['type']);
if (!method_exists($class, 'onBeforeFormSave'))
{
continue;
}
if (!$class->onBeforeFormSave($this, $params, $field))
{
return false;
}
}
$data['params'] = json_encode($params);
return parent::save($data);
}
/**
* Method to validate form data.
*/
public function validate($form, $data, $group = null)
{
// Prevent saving form with an empty name
if (empty($data["name"]))
{
$data["name"] = JText::_("COM_CONVERTFORMS_UNTITLED_BOX");
}
$newdata = array();
$params = array();
$this->_db->setQuery('SHOW COLUMNS FROM #__convertforms');
$dbkeys = $this->_db->loadObjectList('Field');
$dbkeys = array_keys($dbkeys);
foreach ($data as $key => $val)
{
if (in_array($key, $dbkeys))
{
$newdata[$key] = $val;
}
else
{
$params[$key] = $val;
}
}
$newdata['params'] = json_encode($params);
return $newdata;
}
/**
* Method to copy an item
*
* @access public
* @return boolean True on success
*/
public function copy($id)
{
$item = $this->getItem($id);
unset($item->_errors);
$item->id = 0;
$item->published = 0;
$item->name = JText::sprintf('NR_COPY_OF', $item->name);
$item = $this->validate(null, (array) $item);
return ($this->save($item));
}
}

View File

@@ -0,0 +1,283 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
class ConvertFormsModelForms extends JModelList
{
/**
* File extension used for exported files
*
* @var string
*/
private $fileExtension = ".cnvf";
/**
* Constructor.
*
* @param array An optional associative array of configuration settings.
*
* @see JController
*/
public function __construct($config = array())
{
if (empty($config['filter_fields']))
{
$config['filter_fields'] = array(
'id', 'a.id',
'state', 'a.state',
'created', 'a.created',
'ordering', 'a.ordering',
'search',
'name','a.name',
'leads', 'issues'
);
}
parent::__construct($config);
}
/**
* Method to auto-populate the model state.
*
* This method should only be called once per instantiation and is designed
* to be called on the first call to the getState() method unless the model
* configuration flag to ignore the request is set.
*
* Note. Calling getState in this method will result in recursion.
*
* @param string $ordering An optional ordering field.
* @param string $direction An optional direction (asc|desc).
*
* @return void
*
* @since 3.7.0
*/
protected function populateState($ordering = 'a.id', $direction = 'desc')
{
// List state information.
parent::populateState($ordering, $direction);
}
/**
* Method to build an SQL query to load the list data.
*
* @return string An SQL query
*/
protected function getListQuery()
{
// Create a new query object.
$db = JFactory::getDBO();
$query = $db->getQuery(true);
// Select some fields from the item table
$query
->select('a.*')
->from('#__convertforms a');
// Filter State
$filter = $this->getState('filter.state');
if (is_numeric($filter))
{
$query->where('a.state = ' . ( int ) $filter);
}
else if (is_array($filter))
{
$query->where('a.state IN (' . implode(',', $filter) . ')');
}
else if ($filter == '')
{
$query->where('(a.state IN (0,1,2))');
}
// Filter the list over the search string if set.
$search = $this->getState('filter.search');
if (!empty($search))
{
if (stripos($search, 'id:') === 0)
{
$query->where('a.id = ' . ( int ) substr($search, 3));
}
else
{
$search = $db->quote('%' . $db->escape($search, true) . '%');
$query->where(
'( `name` LIKE ' . $search . ' )'
);
}
}
// Add the list ordering clause.
$orderCol = $this->state->get('list.ordering', 'a.id');
$orderDirn = $this->state->get('list.direction', 'desc');
if ($orderCol == 'leads')
{
$query->select('(select count(submissions.id) from #__convertforms_conversions as submissions where submissions.form_id = a.id and submissions.state IN (1,2)) as leads');
}
$query->order($db->escape($orderCol . ' ' . $orderDirn));
return $query;
}
/**
* Import Method
* Import the selected items specified by id
* and set Redirection to the list of items
*/
public function import($model)
{
$app = JFactory::getApplication();
$file = $app->input->files->get("file");
if (!is_array($file) || !isset($file['name']))
{
$app->enqueueMessage(JText::_('NR_PLEASE_CHOOSE_A_VALID_FILE'));
$app->redirect('index.php?option=com_convertforms&view=forms&layout=import');
}
$ext = explode(".", $file['name']);
if ($ext[count($ext) - 1] != substr($this->fileExtension, 1))
{
$app->enqueueMessage(JText::_('NR_PLEASE_CHOOSE_A_VALID_FILE'));
$app->redirect('index.php?option=com_convertforms&view=forms&layout=import');
}
jimport('joomla.filesystem.file');
$publish_all = $app->input->getInt('publish_all', 0);
$data = file_get_contents($file['tmp_name']);
if (empty($data))
{
$app->enqueueMessage(JText::_('File is empty!'));
$app->redirect('index.php?option=com_convertforms&view=forms');
return;
}
$items = json_decode($data, true);
if (is_null($items))
{
$items = array();
}
$msg = JText::_('Items saved');
foreach ($items as $item)
{
$item['id'] = 0;
if ($publish_all == 0)
{
unset($item['published']);
}
else if ($publish_all == 1)
{
$item['published'] = 1;
}
$items[] = $item;
$saved = $model->save($item);
if ($saved != 1)
{
$msg = JText::_('Error Saving Item') . ' ( ' . $saved . ' )';
}
}
$app->enqueueMessage($msg);
$app->redirect('index.php?option=com_convertforms&view=forms');
}
/**
* Export Method
* Export the selected items specified by id
*/
public function export($ids)
{
$db = $this->getDbo();
$query = $db->getQuery(true)
->select('*')
->from('#__convertforms')
->where('id IN ( ' . implode(', ', $ids) . ' )');
$db->setQuery($query);
$rows = $db->loadObjectList();
$string = json_encode($rows);
$filename = JText::_("COM_CONVERTFORMS") . ' Items';
if (count($rows) == 1)
{
$name = Joomla\String\StringHelper::strtolower(html_entity_decode($rows['0']->name));
$name = preg_replace('#[^a-z0-9_-]#', '_', $name);
$name = trim(preg_replace('#__+#', '_', $name), '_-');
$filename = JText::_("COM_CONVERTFORMS") . ' Item (' . $name . ')';
}
// SET DOCUMENT HEADER
if (preg_match('#Opera(/| )([0-9].[0-9]{1,2})#', $_SERVER['HTTP_USER_AGENT']))
{
$UserBrowser = "Opera";
}
elseif (preg_match('#MSIE ([0-9].[0-9]{1,2})#', $_SERVER['HTTP_USER_AGENT']))
{
$UserBrowser = "IE";
}
else
{
$UserBrowser = '';
}
$mime_type = ($UserBrowser == 'IE' || $UserBrowser == 'Opera') ? 'application/octetstream' : 'application/octet-stream';
@ob_end_clean();
ob_start();
header('Content-Type: ' . $mime_type);
header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
if ($UserBrowser == 'IE')
{
header('Content-Disposition: inline; filename="' . $filename . $this->fileExtension . '"');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
}
else
{
header('Content-Disposition: attachment; filename="' . $filename . $this->fileExtension . '"');
header('Pragma: no-cache');
}
// PRINT STRING
echo $string;
die;
}
/**
* Returns Items Object and transforms params JSON field to object
*
* @return object
*/
public function getItems()
{
$items = parent::getItems();
foreach ($items as $key => $item)
{
$params = json_decode($item->params);
$items[$key] = (object) array_merge((array) $item, (array) $params);
unset($items[$key]->params);
}
return $items;
}
}

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset addfieldpath="plugins/system/nrframework/fields"></fieldset>
<fieldset name="main" addfieldpath="administrator/components/com_convertforms/models/forms/fields">
<field name="name" type="text"
label="NR_NAME"
description="COM_CONVERTFORMS_CAMPAIGNS_NAME_DESC"
class="input-xlarge"
required="true"
/>
<field name="state" type="list"
label="JSTATUS"
description="NR_FIELD_STATE_DESC"
class="chzn-color-state"
size="1"
default="1">
<option value="1">JPUBLISHED</option>
<option value="0">JUNPUBLISHED</option>
<option value="2">JARCHIVED</option>
<option value="-2">JTRASHED</option>
</field>
<field name="service" type="cfservices"
label="COM_CONVERTFORMS_CHOOSE_SERVICE"
description="COM_CONVERTFORMS_CAMPAIGN_SYNC_DESC"
class="chzn-color-state">
</field>
<field name="id" type="hidden"
label="JGLOBAL_FIELD_ID_LABEL"
description="JGLOBAL_FIELD_ID_DESC"
default="0"
readonly="true"
class="readonly"
/>
</fieldset>
</form>

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset name="main" addfieldpath="administrator/components/com_convertforms/models/forms/fields">
<field name="state" type="list"
label="JSTATUS"
description="NR_FIELD_STATE_DESC"
class="chzn-color-state"
size="1"
default="1">
<option value="1">JPUBLISHED</option>
<option value="0">JUNPUBLISHED</option>
<option value="2">JARCHIVED</option>
<option value="-2">JTRASHED</option>
</field>
<field name="id" type="text"
label="JGLOBAL_FIELD_ID_LABEL"
description="JGLOBAL_FIELD_ID_DESC"
default="0"
readonly="true"
class="readonly"
/>
<field name="form_id" type="convertforms"
label="COM_CONVERTFORMS_FORM"
readonly="true"
/>
<field name="visitor_id" type="text"
label="COM_CONVERTFORMS_VISITOR_ID"
readonly="true"
/>
<field name="user_id" type="user"
label="Joomla User"
/>
<field name="created" type="calendar"
label="NR_CREATED_DATE"
description="NR_CREATED_DATE_DESC"
size="40"
translateformat="true"
showtime="true"
filter="user_utc"
readonly="true"
/>
<field name="modified" type="calendar"
label="NR_MODIFIFED_DATE"
description="NR_MODIFIFED_DATE_DESC"
size="40"
translateformat="true"
showtime="true"
filter="user_utc"
readonly="true"
/>
<fields name="params">
<field name="leadnotes" type="textarea"
label="COM_CONVERTFORMS_NOTES"
rows="10"
class="span12"
/>
</fields>
</fieldset>
<fieldset name="params" addfieldpath='/plugins/system/nrframework/fields'>
<field name="params"/>
</fieldset>
</form>

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset name="submission" addfieldpath="plugins/system/nrframework/fields">
</fieldset>
<fieldset name="submission" addfieldpath="administrator/components/com_convertforms/models/forms/fields/">
<field name="filter_form_id" type="convertforms"
label="COM_CONVERTFORMS_FORM"
description="COM_CONVERTFORMS_FORM"
required="true">
</field>
<field name="filter_search" type="text"
label="COM_CONVERTFORMS_FILTER_SEARCH"
description="COM_CONVERTFORMS_FILTER_SEARCH_DESC"
/>
<field name="filter_period" type="list"
label="COM_CONVERTFORMS_PERIOD"
default="">
<option value="">NR_ANY</option>
<option value="today">COM_CONVERTFORMS_TODAY</option>
<option value="yesterday">COM_CONVERTFORMS_YESTERDAY</option>
<option value="this_week">COM_CONVERTFORMS_THIS_WEEK</option>
<option value="this_month">COM_CONVERTFORMS_THIS_MONTH</option>
<option value="this_year">COM_CONVERTFORMS_THIS_YEAR</option>
<option value="last_week">COM_CONVERTFORMS_LAST_WEEK</option>
<option value="last_month">COM_CONVERTFORMS_LAST_MONTH</option>
<option value="last_year">COM_CONVERTFORMS_LAST_YEAR</option>
<option value="daterange">COM_CONVERTFORMS_DATE_RANGE</option>
</field>
<field name="filter_created_from" type="calendar"
label="COM_CONVERTFORMS_START_DATE"
hint="COM_CONVERTFORMS_START_DATE"
format="%Y-%m-%d"
showon="filter_period:daterange"
class="input-medium"
/>
<field name="filter_created_to" type="calendar"
label="COM_CONVERTFORMS_END_DATE"
hint="COM_CONVERTFORMS_END_DATE"
format="%Y-%m-%d"
showon="filter_period:daterange"
/>
<field name="filter_state" type="status"
label="State"
default="1"
/>
<field name="export_type" type="list"
label="Export as"
default="csv">
<option value="csv">CSV</option>
<option value="json">JSON</option>
</field>
<field name="advanced" type="nrtoggle"
label="Advanced options"
/>
<field name="limit" type="list"
label="Batch"
default="10000"
showon="advanced:1">
<option value="1000">1,000</option>
<option value="5000">5,000</option>
<option value="10000">10,000</option>
<option value="30000">30,000</option>
<option value="50000">50,000</option>
</field>
<!-- <field name="state" type="status"
label="JSTATE"
showon="advanced:1">
<option value="">JOPTION_SELECT_PUBLISHED</option>
</field> -->
</fieldset>
</form>

View File

@@ -0,0 +1,40 @@
<?php
/**
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
// No direct access to this file
defined('_JEXEC') or die;
JFormHelper::loadFieldClass('list');
class JFormFieldCampaigns extends JFormFieldList
{
/**
* Method to get a list of options for a list input.
*
* @return array An array of JHtml options.
*/
protected function getOptions()
{
$lists = ConvertForms\Helper::getCampaigns();
if (!count($lists))
{
return;
}
$options = array();
foreach ($lists as $option)
{
$options[] = JHTML::_('select.option', $option->id, $option->name);
}
$options = array_merge(parent::getOptions(), $options);
return $options;
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
JFormHelper::loadFieldClass('list');
class JFormFieldCFServices extends JFormFieldList
{
/**
* Method to get a list of options for a list input.
*
* @return array An array of JHtml options.
*/
protected function getOptions()
{
// Trigger all ConvertForms plugins
JPluginHelper::importPlugin('convertforms');
// Get a list with all available services
$services = JFactory::getApplication()->triggerEvent('onConvertFormsServiceName');
$options[] = JHTML::_('select.option', '0', JText::_('JDISABLED'));
// Alphabetically sort services
asort($services);
foreach ($services as $option)
{
$options[] = JHTML::_('select.option', $option['alias'], $option['name']);
}
return array_merge(parent::getOptions(), $options);
}
}

View File

@@ -0,0 +1,137 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
require_once JPATH_PLUGINS . '/system/nrframework/helpers/field.php';
class JFormFieldNR_Choices extends NRFormField
{
/**
* Default Choices
*
* @var array
*/
private $defaultChoices = array(
1 => array("label" => "First Choice"),
2 => array("label" => "Second Choice"),
3 => array("label" => "Third Choice")
);
/**
* Get Input HTML
*
* @return string
*/
protected function getInput()
{
$this->addMedia();
$choiceType = $this->get("choicetype", "dropdown");
// Settings
$showValuesFieldName = $this->name . '[showvalues]';
$showValuesFieldChecked = isset($this->value["showvalues"]) ? "checked" : "";
$showCalcValuesFieldName = $this->name . '[showcalcvalues]';
$showCalcValuesFieldChecked = isset($this->value["showcalcvalues"]) ? "checked" : "";
// Choices
$choices = $this->getChoices();
$nextid = max(array_keys($choices)) + 1;
$html[] = '
<div id="nr_choices_' . $this->id . '" class="nr_choices" data-min="1" data-fieldname="' . $this->name . '" data-nextid="' . $nextid . '">
';
foreach ($choices as $key => $value)
{
// Skip empty choices
if (!isset($value["label"]) || $value["label"] == '')
{
continue;
}
$choiceName = $this->name . '[choices][' . $key . ']';
$checked = (isset($value["default"]) && (bool) $value["default"] === true) ? "checked" : "";
$choiceValue = isset($value["value"]) ? $value["value"] : "";
$choiceCalcValue = isset($value["calc-value"]) ? $value["calc-value"] : "";
$choiceLabel = $value["label"];
$html[] = '
<div class="nr-choice-item" data-id=' . $key . '>
<div>
<input tabindex="-1"
class="nr-choice-default norender"
type="'.($choiceType == "dropdown" ? "radio" : "checkbox") .'"
name="' . $choiceName . '[default]"
value="1" '.$checked .'>
</div>
<div class="nr-choice-sort">
<span class="cf-icon-menu"></span>
</div>
<div class="nr-choice-input">
<input placeholder="' . JText::_('COM_CONVERTFORMS_ENTER_LABEL') . '" class="form-control nr-choice-label" name="' . $choiceName . '[label]" value="' . htmlspecialchars($choiceLabel) . '" type="text"/>
<input '.(!$showValuesFieldChecked ? "style=\"display:none;\"" : "").' placeholder="Enter saved value" class="form-control nr-choice-value" name="' . $choiceName . '[value]" value="'.$choiceValue.'" type="text"/>
<input '.(!$showCalcValuesFieldChecked ? "style=\"display:none;\"" : "").' placeholder="Enter Calculation Value" class="form-control nr-choice-calc-value" name="' . $choiceName . '[calc-value]" value="'.$choiceCalcValue.'" type="text"/>
</div>
<div class="nr-choice-control">
<a tabindex="-1" href="#" class="nr-choice-add"><span class="cf-icon-plus"></span></a>
<a tabindex="-1" href="#" class="nr-choice-remove"><span class="cf-icon-minus"></span></a>
</div>
</div>
';
}
// Add settings fields
$html[] = '
</div>
<div class="nr-choice-settings">
<span>
<input value"1" class="showvalues" type="checkbox" id="' . $showValuesFieldName . '" name="' . $showValuesFieldName . '" '.$showValuesFieldChecked.'>
<label title="' . JText::_('COM_CONVERTFORMS_FIELD_OPTIONS_SHOW_VALUES_DESC') . '" for="' . $showValuesFieldName . '">' . JText::_('COM_CONVERTFORMS_FIELD_OPTIONS_SHOW_VALUES') . '</label>
</span>
<span>
<input value"1" class="showcalcvalues" type="checkbox" id="' . $showCalcValuesFieldName . '" name="' . $showCalcValuesFieldName . '" '.$showCalcValuesFieldChecked.'>
<label title="' . JText::_('COM_CONVERTFORMS_FIELD_OPTIONS_CALC_VALUES_DESC') . '" for="' . $showCalcValuesFieldName . '">' . JText::_('COM_CONVERTFORMS_FIELD_OPTIONS_CALC_VALUES') . '</label>
</span>
</div>
';
return implode(" ", $html);
}
/**
* Get Field Choices
*
* @return array
*/
private function getChoices()
{
// Setup some default choices if we don't have saved data
if (!isset($this->value) || !isset($this->value["choices"]) || count($this->value["choices"]) == 0)
{
return $this->defaultChoices;
}
return $this->value["choices"];
}
/**
* Adds CSS and JavaScript files to DOM
*/
private function addMedia()
{
JHtml::script('https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js');
JHtml::script('com_convertforms/choices.js', ['relative' => true, 'version' => 'auto']);
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
JFormHelper::loadFieldClass('list');
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_convertforms/' . 'models');
class JFormFieldConvertForms extends JFormFieldList
{
/**
* Method to get a list of options for a list input.
*
* @return array An array of JHtml options.
*/
protected function getOptions()
{
$model = JModelLegacy::getInstance('Forms', 'ConvertFormsModel', ['ignore_request' => true]);
$state = isset($this->element['state']) ? (string) $this->element['state'] : 1;
$model->setState('filter.state', explode(',', $state));
$convertforms = $model->getItems();
$options = array();
foreach ($convertforms as $key => $convertform)
{
$name = $convertform->state != 1 ? $convertform->name . ' (' . JText::_('JUNPUBLISHED') . ')' : $convertform->name;
$options[] = JHTML::_('select.option', $convertform->id, $name . ' (' . $convertform->id . ')');
}
return array_merge(parent::getOptions(), $options);
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
class JFormFieldCSSClasses extends JFormFieldText
{
/**
* Layout class prefix
*
* @var string
*/
private $class_prefix = 'cf-';
/**
* List of available layout classes
*
* @var array
*/
private $layouts = array(
'one-half, one-half',
'one-third, one-third, one-third',
'one-fourth, one-fourth, one-fourth, one-fourth',
'one-third, two-thirds',
'two-thirds, one-third',
'one-fourth, one-fourth, two-fourths',
'two-fourths, one-fourth, one-fourth',
'one-fourth, two-fourths, one-fourth'
);
/**
* Display a layouts button next to the field label
*
* @return string
*/
protected function getLabel()
{
$html = '
<a class="cf-layout-btn" href="#"
data-show-label="' . JText::_('COM_CONVERTFORMS_SHOW_LAYOUTS') . '"
data-hide-label="' . JText::_('COM_CONVERTFORMS_HIDE_LAYOUTS') . '">
' . JText::_('COM_CONVERTFORMS_SHOW_LAYOUTS') .
'</a>';
return parent::getLabel() . $html;
}
/**
* Method to get a list of options for a list input.
*
* @return array An array of JHtml options.
*/
protected function getInput()
{
$uniqueClasses = array();
$html = '
<div class="cf-layout-classes">
<span>' . JText::_('COM_CONVERTFORMS_SELECT_LAYOUT') . '</span>
<div class="cf-layout-list">';
foreach ($this->layouts as $key => $layout)
{
$classes = explode(',', $layout);
$html .= '<div class="cf-layout">';
foreach ($classes as $key => $class)
{
$class = trim($class);
$classLabel = ucfirst(str_replace('-', ' ', $class));
$html .= ' <span title="' . $classLabel . '" class="' . $this->class_prefix . $class . '"></span>';
}
$html .= '</div>';
}
$html .= '</div></div>';
return $html . parent::getInput();
}
}

View File

@@ -0,0 +1,140 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
use ConvertForms\FieldsHelper;
class JFormFieldFormFields extends JFormField
{
/**
* Disable field label
*
* @return void
*/
protected function getLabel()
{
return;
}
/**
* Method to attach a JForm object to the field.
*
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object.
* @param mixed $value The form field value to validate.
* @param string $group The field name group control value.
*
* @return boolean True on success.
*
* @since 3.6
*/
public function setup(SimpleXMLElement $element, $value, $group = null)
{
if (!parent::setup($element, $value, $group))
{
return false;
}
if ($this->value)
{
// Convert JSON passed in the default property to array
if (is_string($this->value))
{
$this->value = json_decode($this->value, true);
}
// Migration Fixes
foreach ($this->value as $key => &$value)
{
if (is_object($value))
{
$value = (array) $value;
}
$value['key'] = (int) str_replace('fields', '', $key);
}
}
return true;
}
/**
* Get field input
*
* @return string
*/
protected function getInput()
{
$html = JLayoutHelper::render('layout', array(
'formControl' => $this->name . '[' . $this->fieldname . 'X]',
'items' => $this->renderItems(),
'fieldgroups' => FieldsHelper::getFieldTypes(),
'nextid' => $this->getNextID()
),
__DIR__ . '/formfields/');
$this->addMediaFiles();
return $html;
}
private function getNextID()
{
$max = 0;
if (is_array($this->value))
{
foreach ($this->value as $key => $item)
{
$max = $item['key'] > $max ? $item['key'] : $max;
}
}
return $max + 1;
}
private function renderItems()
{
$items = array();
if (!$this->value || !is_array($this->value))
{
return $items;
}
$i = 0;
foreach ($this->value as $key => $item)
{
if (!$class = FieldsHelper::getFieldClass($item['type']))
{
continue;
}
$formControl = $this->name . '[' . $this->fieldname . $item['key'] . ']';
$items[] = array(
'form' => $class->getOptionsForm($formControl, $item),
'data' => $item
);
$i++;
}
return $items;
}
private function addMediaFiles()
{
JHtml::script('com_convertforms/choices.js', ['relative' => true, 'version' => 'auto']);
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
extract($displayData);
$activeTab = count($items) > 0 ? 'fmAllFields' : 'fmaddField';
JHtml::script('https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js');
?>
<div class="fm" data-formcontrol="<?php echo $formControl ?>" data-nextid="<?php echo $nextid; ?>">
<?php
echo JHtml::_('bootstrap.startTabSet', 'fieldsManager', array('active' => $activeTab));
echo JHtml::_('bootstrap.addTab', 'fieldsManager', 'fmaddField', JText::_('COM_CONVERTFORMS_ADD_FIELD'));
?>
<div class="fmAvailableFields">
<?php foreach ($fieldgroups as $group => $fieldgroup) {
?>
<div class="fmFieldGroup">
<h5><?php echo $fieldgroup['title'] ?></h5>
<div class="fmFields">
<?php foreach ($fieldgroup['fields'] as $key => $field) {
$isProOnly = !$field['class'];
?>
<div>
<button class="cf-btn btn-dark addField" type="button" data-type="<?php echo $field['name']; ?>" title="<?php echo $field['desc']; ?>"<?php if ($isProOnly) { ?> data-pro-only="<?php echo str_replace('Field', '', $field['title']) . ' Field' ?>"<?php } ?>>
<?php echo $field['title'] ?>
<?php if ($isProOnly) { ?>
<span class="icon-lock right"></span>
<?php } ?>
</button>
</div>
<?php } ?>
</div>
</div>
<?php } ?>
</div>
<?php
echo JHtml::_('bootstrap.endTab');
echo JHtml::_('bootstrap.addTab', 'fieldsManager', 'fmAllFields', JText::_('COM_CONVERTFORMS_ALL_FIELDS'));
?>
<div class="fmAddedFields">
<?php foreach ($items as $key => $item) { ?>
<div class="item" data-key="<?php echo $item['data']['key'] ?>">
<span class="fmFieldLabel"></span>
<span class="fmFieldControl">
<a href="#" class="copyField" title="<?php echo JText::_('COM_CONVERTFORMS_FIELDS_COPY') ?>">
<span class="cf-icon-copy"></span>
</a>
<a href="#" class="removeField" title="<?php echo JText::_('COM_CONVERTFORMS_FIELDS_DELETE') ?>">
<span class="cf-icon-cancel"></span>
</a>
</span>
</div>
<?php } ?>
</div>
<?php
echo JHtml::_('bootstrap.endTab');
echo JHtml::_('bootstrap.addTab', 'fieldsManager', 'fmItems', JText::_('JOPTIONS'));
?>
<div class="fmItems">
<?php
foreach ($items as $key => $item)
{
echo $item['form'];
}
?>
</div>
<?php
echo JHtml::_('bootstrap.endTab');
echo JHtml::_('bootstrap.endTabSet');
?>
</div>

View File

@@ -0,0 +1,86 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
JFormHelper::loadFieldClass('checkboxes');
class JFormFieldLeadColumns extends JFormFieldCheckboxes
{
/**
* Method to get a list of options for a list input.
*
* @return array An array of JHtml options.
*/
protected function getOptions()
{
$formID = $this->getFormID();
$form_fields = ConvertForms\Helper::getColumns($formID);
$optionsForm = [];
foreach ($form_fields as $key => $field)
{
$label = ucfirst(str_replace('param_', '', $field));
if (strpos($field, 'param_') === false)
{
$label = JText::_('COM_CONVERTFORMS_' . $label);
}
$optionsForm[] = (object) [
'value' => $field,
'text' => $label
];
}
return $optionsForm;
}
protected function getInput()
{
JFactory::getDocument()->addScriptDeclaration('
function cfSubmissionColumnsApply(that) {
// Reset task in case it was previously set and would trigger the task on submit such as submissions export
let task = document.querySelector("input[type=\"hidden\"][name=\"task\"]");
if (task) {
task.value = "";
}
that.form.submit();
}
');
$html = '
<div class="chooseColumns">
<a class="btn btn-secondary" data-bs-toggle="collapse" data-toggle="collapse" href="#" data-target=".chooseColumnsOptions" data-bs-target=".chooseColumnsOptions">'
. JText::_('COM_CONVERTFORMS_CHOOSE_COLUMNS') . '
</a>
<div class="collapse chooseColumnsOptions">
<div>
' . parent::getInput() . '
<button class="btn btn-sm btn-success" onclick="cfSubmissionColumnsApply(this);">'
. JText::_('JAPPLY') .
'</button>
</div>
</div>
</div>
';
return $html;
}
private function getFormID()
{
return $this->form->getData()->get('filter.form_id');
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
class JFormFieldServiceLists extends JFormFieldText
{
/**
* Method to get a list of options for a list input.
*
* @return array An array of JHtml options.
*/
protected function getInput()
{
$this->addMedia();
return implode(" ", array(
parent::getInput(),
'<button type="button" class="btn btn-secondary viewLists">
<span class="icon-loop"></span> Lists
</button>
<ul class="cflists"></ul>'
));
}
/**
* Adds field's JavaScript and CSS files to the document
*/
private function addMedia()
{
JHtml::stylesheet('com_convertforms/servicelists.css', ['relative' => true, 'version' => 'auto']);
JHtml::script('com_convertforms/servicelists.js', ['relative' => true, 'version' => 'auto']);
}
}

View File

@@ -0,0 +1,97 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2021 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
JFormHelper::loadFieldClass('media');
class JFormFieldSignature extends JFormFieldMedia
{
/**
* Allow editing the signature field on the backend
*
* @return string
*/
protected function getInput()
{
JFactory::getDocument()->addStyleDeclaration('
.previewSignature {
max-width:600px;
position:relative;
}
.previewSignature .btn-download {
position:absolute;
right:10px;
top:10px;
display:none;
}
.previewSignature:hover .btn-download {
display:block;
}
');
$this->class = '';
$parent = parent::getInput();
if (!defined('nrJ4'))
{
JFactory::getDocument()->addStyleDeclaration('
.previewSignature {
border:solid 1px #ccc;
border-radius:3px;
box-sizing: border-box;
}
.previewSignature * {
box-sizing: inherit;
}
.previewSignature .pop-helper, .previewSignature .tooltip {
display:none !important;
}
.previewSignature .input-prepend {
width:100%;
display:flex;
height:34px;
}
.previewSignature .input-prepend > * {
flex:0;
height:100%;
}
.previewSignature .input-prepend input {
flex:1;
border-radius: 0 0 0 3px;
padding-left: 10px;
}
.previewSignature .field-media-wrapper {
margin-bottom: -1px;
margin-left: -1px;
}
.previewSignature .img-prv {
padding:10px;
background-color:#f2f2f2;
text-align:center;
}
');
$parent = '<div class="img-prv"><img src="' . JURI::root() . '/' . $this->value . '"/></div>' . $parent;
}
return '
<div class="previewSignature">' .
$parent . '
<a href="' . JURI::root() . '/' . $this->value . '" title="' . \JText::_('COM_CONVERTFORMS_SIGNATURE_DOWNLOAD') . '" class="btn btn-small btn-primary btn-sm btn-download" download>
<span class="icon-download"></span>
</a>
</div>
';
}
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* @package Convert Forms
* @version 3.2.12 Free
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2020 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
JFormHelper::loadFieldClass('text');
class JFormFieldTextList extends JFormFieldText
{
/**
* Method to get a list of options for a list input.
*
* @return array An array of JHtml options.
*/
protected function getInput()
{
if (!empty($this->value) && !is_array($this->value))
{
$this->value = (array) $this->value;
}
// Add brackets to field name to accept multiple values
$this->name .= '[]';
$html = '<div class="input_item_list"><div class="input_items">';
if (is_array($this->value) && !empty($this->value))
{
foreach ($this->value as $key => $item)
{
$this->value = $item;
$html .= '<div>' . parent::getInput() . '<button class="btn btn-mini remove_item"><span class="icon-minus"></button></div>';
}
}
$html .= '</div>';
// Add an extra input for template needs
$this->value = '';
$this->disabled = true;
$html .= '<div class="input_item_list_tmpl"> ' . parent::getInput() . '<button class="btn btn-mini remove_item"><span class="icon-minus"></button></div>';
$html .= '<button class="btn btn-mini btn-success add_item"><span class="icon-plus"></span></button></div>';
static $run;
if (!$run)
{
$this->addMedia();
$run = true;
}
return $html;
}
private function addMedia()
{
// Add CSS
JFactory::getDocument()->addStyleDeclaration('
.input_item_list .input_item_list_tmpl {
display:none;
}
.input_item_list div div {
margin-bottom:5px;
display:flex;
display:-webkit-flex;
align-items:center;
-webkit-align-items:center;
}
.input_item_list input {
margin-right:5px;
}
.input_item_list *[class^="icon"] {
margin:0;
pointer-events: none;
}
');
// Add Script
JFactory::getDocument()->addScriptDeclaration('
document.addEventListener("DOMContentLoaded", function(e) {
var els = document.querySelectorAll(".input_item_list");
els.forEach(function(el) {
el.addEventListener("click", function(e) {
e.preventDefault();
// Remove item action
if (e.target.classList.contains("remove_item")) {
var button = e.target;
var container = button.closest(".input_items");
container.removeChild(button.parentNode);
}
// Add new item action
if (e.target.classList.contains("add_item")) {
var el_tmpl = el.querySelector(".input_item_list_tmpl");
var cln = el_tmpl.cloneNode(true);
cln.querySelector("input").disabled = false;
cln.classList.remove("input_item_list_tmpl");
el.querySelector(".input_items").appendChild(cln);
}
});
});
});
');
}
}

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="filter">
<field
name="search"
type="text"
label="JSEARCH_FILTER_LABEL"
hint="JSEARCH_FILTER"
/>
<field
name="state"
type="status"
filter="-2,0,1"
label="JPUBLISHED"
onchange="this.form.submit();">
<option value="">JOPTION_SELECT_PUBLISHED</option>
</field>
</fields>
<fields name="list">
<field
name="fullordering"
type="list"
label="NR_LIST_FULL_ORDERING"
description="NR_LIST_FULL_ORDERING_DESC"
onchange="this.form.submit();"
default="a.id DESC">
<option value="">JGLOBAL_SORT_BY</option>
<option value="a.state ASC">JSTATUS_ASC</option>
<option value="a.state DESC">JSTATUS_DESC</option>
<option value="a.name ASC">JGLOBAL_TITLE_ASC</option>
<option value="a.name DESC">JGLOBAL_TITLE_DESC</option>
<option value="a.id ASC">JGRID_HEADING_ID_ASC</option>
<option value="a.id DESC">JGRID_HEADING_ID_DESC</option>
</field>
<field
name="limit"
type="limitbox"
class="input-mini"
default="10"
label="NR_LIST_LIMIT"
description="NN_LIST_LIMIT_DESC"
onchange="this.form.submit();"
/>
</fields>
</form>

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="filter" addfieldpath="administrator/components/com_convertforms/models/forms/fields">
<field name="search" type="text"
label="JSEARCH_FILTER_LABEL"
hint="JSEARCH_FILTER"
/>
<field name="form_id" type="convertforms"
label="COM_CONVERTFORMS_FORM"
description="COM_CONVERTFORMS_FORM"
state="0,1"
onchange="this.form.submit();">
<option disabled="disabled">COM_CONVERTFORMS_FORM_SELECT</option>
</field>
<field name="period" type="list"
label="COM_CONVERTFORMS_PERIOD"
onchange="if (document.getElementById('filter_period').value == 'daterange') return; this.form.submit();">
<option value="">COM_CONVERTFORMS_PERIOD_SELECT</option>
<option value="today">COM_CONVERTFORMS_TODAY</option>
<option value="yesterday">COM_CONVERTFORMS_YESTERDAY</option>
<option value="this_week">COM_CONVERTFORMS_THIS_WEEK</option>
<option value="this_month">COM_CONVERTFORMS_THIS_MONTH</option>
<option value="this_year">COM_CONVERTFORMS_THIS_YEAR</option>
<option value="last_week">COM_CONVERTFORMS_LAST_WEEK</option>
<option value="last_month">COM_CONVERTFORMS_LAST_MONTH</option>
<option value="last_year">COM_CONVERTFORMS_LAST_YEAR</option>
<option value="daterange">COM_CONVERTFORMS_DATE_RANGE</option>
</field>
<field name="created_from" type="calendar"
label="COM_CONVERTFORMS_START_DATE"
hint="COM_CONVERTFORMS_START_DATE"
format="%Y-%m-%d"
onchange="this.form.submit();"
showon="period:daterange"
class="input-medium"
/>
<field name="created_to" type="calendar"
label="COM_CONVERTFORMS_END_DATE"
hint="COM_CONVERTFORMS_END_DATE"
format="%Y-%m-%d"
onchange="this.form.submit();"
showon="period:daterange"
class="input-medium"
/>
<field name="state" type="status"
label="JPUBLISHED"
onchange="this.form.submit();">
<option value="">JOPTION_SELECT_PUBLISHED</option>
</field>
<field name="columns" type="leadcolumns"
label="COM_CONVERTFORMS_CHOOSE_COLUMNS"
onchange="this.form.submit();"
/>
</fields>
<fields name="list">
<field
name="fullordering"
type="list"
label="NR_LIST_FULL_ORDERING"
description="NR_LIST_FULL_ORDERING_DESC"
onchange="this.form.submit();"
default="a.id DESC">
<option value="">JGLOBAL_SORT_BY</option>
<option value="a.id ASC">JGRID_HEADING_ID_ASC</option>
<option value="a.id DESC">JGRID_HEADING_ID_DESC</option>
<option value="a.state ASC">JSTATUS_ASC</option>
<option value="a.state DESC">JSTATUS_DESC</option>
<option value="a.created ASC">JDATE_ASC</option>
<option value="a.created DESC">JDATE_DESC</option>
<option value="a.form_id ASC">COM_CONVERTFORMS_FORM_ASCENDING</option>
<option value="a.form_id DESC">COM_CONVERTFORMS_FORM_DESCENDING</option>
</field>
<field
name="limit"
type="limitbox"
class="input-mini"
default="10"
label="NR_LIST_LIMIT"
description="NN_LIST_LIMIT_DESC"
onchange="this.form.submit();"
/>
</fields>
</form>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="filter">
<field
name="search"
type="text"
label="JSEARCH_FILTER_LABEL"
hint="JSEARCH_FILTER"
/>
<field
name="state"
type="status"
filter="-2,0,1"
label="JPUBLISHED"
onchange="this.form.submit();">
<option value="">JOPTION_SELECT_PUBLISHED</option>
</field>
</fields>
<fields name="list">
<field
name="fullordering"
type="list"
label="NR_LIST_FULL_ORDERING"
description="NR_LIST_FULL_ORDERING_DESC"
onchange="this.form.submit();"
default="a.id DESC">
<option value="">JGLOBAL_SORT_BY</option>
<option value="a.state ASC">JSTATUS_ASC</option>
<option value="a.state DESC">JSTATUS_DESC</option>
<option value="a.name ASC">JGLOBAL_TITLE_ASC</option>
<option value="a.name DESC">JGLOBAL_TITLE_DESC</option>
<option value="a.id ASC">JGRID_HEADING_ID_ASC</option>
<option value="a.id DESC">JGRID_HEADING_ID_DESC</option>
<option value="leads ASC">COM_CONVERTFORMS_SUBMISSIONS_ASC</option>
<option value="leads DESC">COM_CONVERTFORMS_SUBMISSIONS_DESC</option>
</field>
<field
name="limit"
type="limitbox"
class="input-mini"
default="10"
label="NR_LIST_LIMIT"
description="NN_LIST_LIMIT_DESC"
onchange="this.form.submit();"
/>
</fields>
</form>

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset name="submission" label="Submission" tab="conversion">
<field name="save_data_to_db" type="nrtoggle"
label="COM_CONVERTFORMS_SAVE_DATA_TO_DB"
description="COM_CONVERTFORMS_SAVE_DATA_TO_DB_DESC"
checked="true"
/>
<field name="submission_state" type="list"
label="COM_CONVERTFORMS_SUBMISSION_DEFAULT_STATE"
description="COM_CONVERTFORMS_SUBMISSION_DEFAULT_STATE_DESC"
class="chzn-color-state"
size="1"
default="1"
showon="save_data_to_db:1">
<option value="1">JPUBLISHED</option>
<option value="0">JUNPUBLISHED</option>
<option value="2">JARCHIVED</option>
<option value="-2">JTRASHED</option>
</field>
<field name="campaign" type="campaigns"
label="COM_CONVERTFORMS_COLLECT_LEADS_USING"
description="COM_CONVERTFORMS_COLLECT_LEADS_USING_DESC"
required="true"
/>
<field name="onsuccess" type="list"
label="COM_CONVERTFORMS_SUCCESSFUL_SUBMISSION"
description="COM_CONVERTFORMS_SUCCESSFUL_SUBMISSION_DESC"
default="msg">
<option value="msg">COM_CONVERTFORMS_DISPLAY_MSG</option>
<option value="url">COM_CONVERTFORMS_REDIRECT_USER</option>
</field>
<field name="successmsg" type="textarea"
label="COM_CONVERTFORMS_SUCCESS_TEXT"
description="COM_CONVERTFORMS_SUCCESS_TEXT_DESC"
default="Thanks for contacting us! We will get in touch with you shortly."
class="editorx show-smart-tags"
showon="onsuccess:msg">
</field>
<field name="resetform" type="nrtoggle"
label="COM_CONVERTFORMS_RESET_FORM"
description="COM_CONVERTFORMS_RESET_FORM_DESC"
checked="true"
showon="onsuccess:msg"
/>
<field name="hideform" type="nrtoggle"
label="COM_CONVERTFORMS_HIDE_FORM"
description="COM_CONVERTFORMS_HIDE_FORM_DESC"
checked="true"
showon="onsuccess:msg"
/>
<field name="hidetext" type="nrtoggle"
label="COM_CONVERTFORMS_HIDE_TEXT"
description="COM_CONVERTFORMS_HIDE_TEXT_DESC"
showon="onsuccess:msg"
/>
<field name="successurl" type="text"
label="COM_CONVERTFORMS_SUCCESS_URL"
description="COM_CONVERTFORMS_SUCCESS_URL_DESC"
hint="http://"
showon="onsuccess:url">
</field>
<field name="passdata" type="list"
label="COM_CONVERTFORMS_PASS_DATA"
description="COM_CONVERTFORMS_PASS_DATA_DESC"
showon="onsuccess:url">
<option value="">JNO</option>
<option value="1">COM_CONVERTFORMS_PASS_DATA_GET</option>
<option value="2">COM_CONVERTFORMS_PASS_DATA_POST</option>
</field>
</fieldset>
<fieldset name="behavior" label="COM_CONVERTFORMS_BEHAVIOR" tab="behavior" addfieldpath="plugins/system/nrframework/fields">
<field name="state" type="list"
label="JSTATUS"
description="NR_FIELD_STATE_DESC"
class="chzn-color-state"
size="1"
default="1">
<option value="1">JPUBLISHED</option>
<option value="0">JUNPUBLISHED</option>
<option value="2">JARCHIVED</option>
<option value="-2">JTRASHED</option>
</field>
<field name="honeypot" type="nrtoggle"
label="COM_CONVERTFORMS_HONEYPOT"
description="COM_CONVERTFORMS_HONEYPOT_DESC"
checked="true"
/>
<field name="id" type="hidden"
label="JGLOBAL_FIELD_ID_LABEL"
description="JGLOBAL_FIELD_ID_DESC"
default="0"
readonly="true"
class="readonly"
/>
</fieldset>
<fieldset name="phpscripts" label="COM_CONVERTFORMS_PHPSCRIPT" tab="behavior">
<fields name="phpscripts">
<field name="formprepare" type="textarea"
label="COM_CONVERTFORMS_PHPSCRIPT_FORM_PREPARE"
description="COM_CONVERTFORMS_PHPSCRIPT_FORM_PREPARE_DESC"
rows="10"
/>
<field name="formdisplay" type="textarea"
label="COM_CONVERTFORMS_PHPSCRIPT_FORM_DISPLAY"
description="COM_CONVERTFORMS_PHPSCRIPT_FORM_DISPLAY_DESC"
rows="10"
/>
<field name="formprocess" type="textarea"
label="COM_CONVERTFORMS_PHPSCRIPT_FORM_PROCESS"
description="COM_CONVERTFORMS_PHPSCRIPT_FORM_PROCESS_DESC"
rows="10"
/>
<field name="afterformsubmission" type="textarea"
label="COM_CONVERTFORMS_PHPSCRIPT_AFTER_FORM_SUBMISSION"
description="COM_CONVERTFORMS_PHPSCRIPT_AFTER_FORM_SUBMISSION_DESC"
rows="10"
/>
<field name="notephpscripts" type="note"
description="COM_CONVERTFORMS_PHPSCRIPT_NOTE"
class="alert"
/>
</fields>
</fieldset>
</form>

View File

@@ -0,0 +1,405 @@
<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset name="box" label="Box" tab="design" addfieldpath="administrator/components/com_convertforms/models/forms/fields">
<field name="name" type="text"
label="NR_NAME"
hint="NR_NAME"
description="COM_CONVERTFORMS_FORMS_NAME_DESC"
/>
<field name="autowidth" type="list"
label="COM_CONVERTFORMS_BOX_WIDTH_TYPE"
description="COM_CONVERTFORMS_BOX_WIDTH_TYPE_DESC"
default="custom">
<option value="auto">NR_AUTO</option>
<option value="custom">NR_CUSTOM</option>
</field>
<field name="width" type="nrnumber"
label="COM_CONVERTFORMS_FORM_WIDTH"
description="COM_CONVERTFORMS_FORM_WIDTH_DESC"
default="500"
min="0"
step="50"
addon="px"
showon="autowidth:custom"
/>
<field name="bgcolor" type="color"
default="rgba(255, 255, 255, 1)"
keywords="transparent,none"
format="rgba"
label="NR_BACKGROUND_COLOR"
description="NR_BACKGROUND_COLOR_DESC"
position="bottom"
/>
<field name="bgimage" type="list"
label="COM_CONVERTFORMS_BACKGROUND_IMAGE"
description="COM_CONVERTFORMS_BACKGROUND_IMAGE_DESC"
filter="intval"
size="1"
default="0">
<option value="0">NR_NONE</option>
<option value="1">NR_UPLOAD</option>
<option value="2">COM_CONVERTFORMS_CUSTOM_URL</option>
</field>
<field name="bgurl" type="text"
hint="http://"
label="COM_CONVERTFORMS_BACKGROUND_URL"
description="COM_CONVERTFORMS_BACKGROUND_URL_DESC"
showon="bgimage:2"
/>
<field name="bgfile" type="media"
label="COM_CONVERTFORMS_BACKGROUND_FILE"
description="COM_CONVERTFORMS_BACKGROUND_FILE_DESC"
showon="bgimage:1"
/>
<field name="bgrepeat" type="list"
showon="bgimage:1,2"
label="NR_BGIMAGE_REPEAT"
description="NR_BGIMAGE_REPEAT_DESC"
default="no-repeat">
<option value="no-repeat">NR_REPEAT_NO</option>
<option value="repeat-x">NR_REPEAT_X</option>
<option value="repeat-y">NR_REPEAT_Y</option>
<option value="repeat">NR_REPEAT</option>
</field>
<field name="bgsize" type="list"
showon="bgimage:1,2"
label="NR_BGIMAGE_SIZE"
description="NR_BGIMAGE_SIZE_DESC"
default="auto">
<option value="auto">NR_AUTO</option>
<option value="cover">NR_IMAGE_SIZE_COVER</option>
<option value="contain">NR_IMAGE_SIZE_CONTAIN</option>
<option value="100% 100%">100% 100%</option>
</field>
<field name="bgposition" type="list"
showon="bgimage:1,2"
label="NR_BGIMAGE_POSITION"
description="NR_BGIMAGE_POSITION_DESC"
default="left top">
<option value="left top">Left Top</option>
<option value="left center">Left Center</option>
<option value="left bottom">Left Bottom</option>
<option value="right top">Right Top</option>
<option value="right center">Right Center</option>
<option value="right bottom">Right Bottom</option>
<option value="center top">Center Top</option>
<option value="center center">Center Center</option>
<option value="center bottom">Center Bottom</option>
</field>
<field name="spacer1"
type="spacer" hr="true"
/>
<field name="text" type="textarea"
label="COM_CONVERTFORMS_MESSAGE"
description="COM_CONVERTFORMS_MESSAGE_DESC"
class="editorx show-smart-tags"
filter="raw"
hint="Enter your message here"
/>
<field name="font" type="nrfonts"
class="nrfont"
label="COM_CONVERTFORMS_BODY_FONT"
description="COM_CONVERTFORMS_BODY_FONT_DESC"
default="Arial">
<option value=" ">JDEFAULT</option>
</field>
<field name="padding" type="nrnumber"
label="NR_PADDING"
description="NR_PADDING_DESC"
addon="px"
min="0"
step="5"
default="0">
</field>
<field name="borderradius" type="nrnumber"
label="COM_CONVERTFORMS_BOX_RADIUS"
description="COM_CONVERTFORMS_BORDER_RADIUS_DESC"
addon="px"
default="0"
min="0"
step="5"
/>
<field name="spacer2"
type="spacer" hr="true"
/>
<field name="borderstyle" type="list"
label="COM_CONVERTFORMS_FORM_BORDER_STYLE"
description="COM_CONVERTFORMS_FORM_BORDER_STYLE_DESC"
default="none">
<option value="none">NR_NONE</option>
<option value="solid">Solid</option>
<option value="dotted">Dotted</option>
<option value="dashed">Dashed</option>
<option value="double">Double</option>
<option value="groove">Groove</option>
<option value="ridge">Ridge</option>
<option value="inset">Inset</option>
<option value="outset">Outset</option>
</field>
<field name="bordercolor" type="color"
label="COM_CONVERTFORMS_FORM_BORDER_COLOR"
description="COM_CONVERTFORMS_FORM_BORDER_COLOR_DESC"
showon="borderstyle:solid,dotted,dashed,double,groove,ridge,inset,outset"
position="bottom"
/>
<field name="borderwidth" type="nrnumber"
addon="px"
default="2"
min="0"
label="COM_CONVERTFORMS_FORM_BORDER_WIDTH"
description="COM_CONVERTFORMS_FORM_BORDER_WIDTH_DESC"
showon="borderstyle:solid,dotted,dashed,double,groove,ridge,inset,outset"
/>
</fieldset>
<fieldset name="image" label="NR_IMAGE" tab="design">
<field name="image" type="list"
label="COM_CONVERTFORMS_IMAGE_SOURCE"
description="COM_CONVERTFORMS_IMAGE_SOURCE_DESC"
filter="intval"
size="1"
default="0">
<option value="0">NR_NONE</option>
<option value="1">NR_UPLOAD</option>
<option value="2">COM_CONVERTFORMS_CUSTOM_URL</option>
</field>
<field name="imageurl" type="text"
hint="http://"
label="COM_CONVERTFORMS_IMAGE_URL"
description="COM_CONVERTFORMS_IMAGE_URL_DESC"
showon="image:2"
/>
<field name="imagefile" type="media"
label="NR_IMAGE_SELECT"
description="COM_CONVERTFORMS_IMAGE_SOURCE"
showon="image:1"
/>
<field name="imgposition" type="list"
showon="image:1,2"
label="COM_CONVERTFORMS_IMAGE_POSITION"
description="COM_CONVERTFORMS_IMAGE_POSITION_DESC"
default="img-above">
<option value="img-above">COM_CONVERTFORMS_IMAGE_ABOVE</option>
<option value="img-below">COM_CONVERTFORMS_IMAGE_BELOW</option>
<option value="img-right">COM_CONVERTFORMS_IMAGE_RIGHT</option>
<option value="img-left">COM_CONVERTFORMS_IMAGE_LEFT</option>
</field>
<field name="imageautowidth" type="list"
label="COM_CONVERTFORMS_IMAGE_WIDTH_TYPE"
description="COM_CONVERTFORMS_IMAGE_WIDTH_TYPE_DESC"
default="auto"
showon="image:1,2">
<option value="auto">NR_AUTO</option>
<option value="custom">NR_CUSTOM</option>
</field>
<field name="imagewidth" type="nrnumber"
label="NR_WIDTH"
description="NR_WIDTH_DESC"
addon="px"
min="0"
step="10"
default="200"
showon="imageautowidth:custom[AND]image:1,2"
/>
<field name="imagesize" type="nrnumber"
label="COM_CONVERTFORMS_IMAGE_SIZE"
description="COM_CONVERTFORMS_IMAGE_SIZE_DESC"
addon="Columns"
max="16"
min="1"
default="6"
filter="intval"
showon="imgposition:img-right,img-left[AND]image:1,2"
/>
<field name="imagehposition" type="nrnumber"
label="COM_CONVERTFORMS_HORIZONTAL_POSITION"
description="COM_CONVERTFORMS_HORIZONTAL_POSITION_DESC"
addon="px"
default="0"
step="5"
showon="image:1,2"
/>
<field name="imagevposition" type="nrnumber"
label="COM_CONVERTFORMS_VERTICAL_POSITION"
description="COM_CONVERTFORMS_VERTICAL_POSITION_DESC"
addon="px"
default="0"
step="5"
showon="image:1,2"
/>
<field name="imagealt" type="text"
label="COM_CONVERTFORMS_IMAGE_ALT"
description="COM_CONVERTFORMS_IMAGE_ALT_DESC"
showon="image:1,2"
/>
<field name="hideimageonmobile" type="nrtoggle"
label="COM_CONVERTFORMS_HIDE_IMAGE_ON_MOBILE"
description="COM_CONVERTFORMS_HIDE_IMAGE_ON_MOBILE_DESC"
showon="image:1,2"
/>
</fieldset>
<fieldset name="layouts" label="Form" tab="design">
<field name="formposition" type="list"
label="COM_CONVERTFORMS_FORM_POSITION"
description="COM_CONVERTFORMS_FORM_POSITION_DESC"
showlabels="false"
default="form-bottom">
<option value="form-left">NR_LEFT</option>
<option value="form-bottom">NR_BOTTOM</option>
<option value="form-right">NR_RIGHT</option>
</field>
<field name="formsize" type="nrnumber"
label="COM_CONVERTFORMS_FORM_SIZE"
description="COM_CONVERTFORMS_COLUMNS_DESC"
addon="Columns"
max="16"
min="1"
default="16"
filter="intval"
showon="formposition:form-left,form-right"
/>
<field name="formbgcolor" type="color"
default=""
keywords="transparent,none"
format="rgba"
label="NR_BACKGROUND_COLOR"
description="NR_BACKGROUND_COLOR_DESC"
position="bottom"
/>
</fieldset>
<fieldset name="fields" label="COM_CONVERTFORMS_FIELDS" tab="fields">
<field name="fields" type="formfields"
hiddenLabel="true"
default='{
"fields0": {
"key": "0",
"type": "email",
"name": "email",
"label": "Enter your email address",
"placeholder": "Enter your email address"
},
"fields1": {
"key": "1",
"type": "text",
"name": "name",
"label": "Enter your name",
"placeholder": "Enter your name"
},
"fields2": {
"key": "2",
"type": "submit",
"text": "Submit"
}
}'
/>
</fieldset>
<fieldset name="formbuilder" label="COM_CONVERTFORMS_FIELDS" tab="design">
<field name="labelscolor" type="color"
default="#888"
label="COM_CONVERTFORMS_LABELS_COLOR"
description="NR_COLOR_DESC"
position="bottom"
/>
<field name="labelsfontsize" type="nrnumber"
default="15"
label="COM_CONVERTFORMS_LABELS_FONT_SIZE"
description="COM_CONVERTFORMS_LABELS_FONT_SIZE"
addon="px"
/>
<field name="labelposition" type="list"
label="COM_CONVERTFORMS_LABEL_POSITION"
description="COM_CONVERTFORMS_LABEL_POSITION_DESC"
default="top">
<option value="top">Top Aligned</option>
<option value="left">Left Aligned</option>
</field>
<field name="required_indication" type="nrtoggle"
label="COM_CONVERTFORMS_REQUIRED_INDICATION"
description="COM_CONVERTFORMS_REQUIRED_INDICATION_DESC"
checked="true"
/>
<field name="inputfontsize" type="nrnumber"
addon="px"
default="15"
min="0"
label="COM_CONVERTFORMS_INPUT_FONT_SIZE"
description="COM_CONVERTFORMS_INPUT_FONT_SIZE_DESC"
/>
<field name="inputcolor" type="color"
default="#888"
label="COM_CONVERTFORMS_INPUT_COLOR"
description="NR_COLOR_DESC"
position="bottom"
/>
<field name="inputbg" type="color"
default="#fff"
label="COM_CONVERTFORMS_INPUT_BGCOLOR"
description="NR_COLOR_DESC"
position="bottom"
/>
<field name="inputalign" type="list"
label="COM_CONVERTFORMS_FORM_TEXT_ALIGN"
description="COM_CONVERTFORMS_FORM_TEXT_ALIGN_DESC"
default="left">
<option value="left">NR_LEFT</option>
<option value="center">NR_CENTER</option>
<option value="right">NR_RIGHT</option>
</field>
<field name="inputbordercolor" type="color"
label="COM_CONVERTFORMS_INPUT_BORDER_COLOR"
description="NR_COLOR_DESC"
default="#ccc"
position="bottom"
/>
<field name="inputborderradius" type="nrnumber"
label="COM_CONVERTFORMS_BORDER_RADIUS"
description="COM_CONVERTFORMS_BORDER_RADIUS_DESC"
addon="px"
default="3"
min="0"
step="1"
/>
<field name="inputvpadding" type="nrnumber"
addon="px"
default="10"
min="0"
label="COM_CONVERTFORMS_VPADDING_SIZE"
description="COM_CONVERTFORMS_INPUT_PADDING_DESC"
/>
<field name="inputhpadding" type="nrnumber"
addon="px"
default="10"
min="0"
label="COM_CONVERTFORMS_HPADDING_SIZE"
description="COM_CONVERTFORMS_INPUT_PADDING_DESC"
/>
<field name="help_text_position" type="list"
label="COM_CONVERTFORMS_HELP_TEXT_POSITION"
description="COM_CONVERTFORMS_HELP_TEXT_POSITION_DESC"
default="after">
<option value="after">COM_CONVERTFORMS_HELP_TEXT_AFTER_INPUT</option>
<option value="before">COM_CONVERTFORMS_HELP_TEXT_BEFORE_INPUT</option>
</field>
</fieldset>
<fieldset name="advanced" label="Advanced" tab="design">
<field name="footer" type="textarea"
label="COM_CONVERTFORMS_FOOTER"
description="COM_CONVERTFORMS_FOOTER_DESC"
filter="raw"
class="editorx show-smart-tags"
/>
<field name="customcss" type="textarea"
label="COM_CONVERTFORMS_CUSTOM_CSS"
description="COM_CONVERTFORMS_CUSTOM_CSS_DESC"
rows="10"
/>
<field name="customcode" type="textarea"
label="COM_CONVERTFORMS_CUSTOM_CODE"
description="COM_CONVERTFORMS_CUSTOM_CODE_DESC"
rows="10"
/>
<field name="classsuffix" type="text"
label="COM_CONVERTFORMS_CLASS_SUFFIX"
description="COM_CONVERTFORMS_CLASS_SUFFIX_DESC"
/>
</fieldset>
</form>