1099 lines
39 KiB
PHP
1099 lines
39 KiB
PHP
<?php namespace JanVince\SmallContactForm\Components;
|
|
|
|
use Cms\Classes\ComponentBase;
|
|
use JanVince\SmallContactForm\Models\Settings;
|
|
use JanVince\SmallContactForm\Models\Message;
|
|
|
|
use Validator;
|
|
use Illuminate\Support\MessageBag;
|
|
use Redirect;
|
|
use Request;
|
|
use Input;
|
|
use Session;
|
|
use Flash;
|
|
use Form;
|
|
use Log;
|
|
use App;
|
|
use Twig;
|
|
use ReCaptcha\ReCaptcha;
|
|
|
|
|
|
class SmallContactForm extends ComponentBase
|
|
{
|
|
|
|
private $validationRules;
|
|
private $validationMessages;
|
|
|
|
private $postData = [];
|
|
private $post;
|
|
|
|
private $errorAutofocus;
|
|
|
|
private $formDescription;
|
|
private $formDescriptionOverride;
|
|
|
|
private $formRedirect;
|
|
private $formRedirectOverride;
|
|
|
|
public function componentDetails() {
|
|
return [
|
|
'name' => 'janvince.smallcontactform::lang.controller.contact_form.name',
|
|
'description' => 'janvince.smallcontactform::lang.controller.contact_form.description'
|
|
];
|
|
}
|
|
|
|
public function defineProperties(){
|
|
|
|
return [
|
|
|
|
'form_description' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.form_description',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.form_description_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
],
|
|
|
|
'disable_fields' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.disable_fields',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.disable_fields_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_form',
|
|
],
|
|
'send_btn_label' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.send_btn_label',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.send_btn_label_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_form',
|
|
],
|
|
'form_success_msg' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.form_success_msg',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.form_success_msg_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_form',
|
|
],
|
|
'form_error_msg' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.form_error_msg',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.form_error_msg_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_form',
|
|
],
|
|
|
|
|
|
'disable_notifications' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.disable_notifications',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.disable_notifications_comment',
|
|
'type' => 'checkbox',
|
|
'default' => false,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_notifications',
|
|
],
|
|
'notification_address_to' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.notification_address_to',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.notification_address_to_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_notifications',
|
|
],
|
|
'notification_address_from' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.notification_address_from',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.notification_address_from_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_notifications',
|
|
],
|
|
'notification_address_from_name' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.notification_address_from_name',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.notification_address_from_name_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_notifications',
|
|
],
|
|
'notification_template' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.notification_template',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.notification_template_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_notifications',
|
|
],
|
|
'notification_subject' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.notification_subject',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.notification_subject_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_notifications',
|
|
],
|
|
|
|
|
|
'disable_autoreply' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.disable_autoreply',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.disable_autoreply_comment',
|
|
'type' => 'checkbox',
|
|
'default' => false,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_autoreply',
|
|
],
|
|
'autoreply_address_from' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.autoreply_address_from',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.autoreply_address_from_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_autoreply',
|
|
],
|
|
'autoreply_address_from_name' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.autoreply_address_from_name',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.autoreply_address_from_name_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_autoreply',
|
|
],
|
|
'autoreply_address_replyto' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.autoreply_address_replyto',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.autoreply_address_replyto_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_autoreply',
|
|
],
|
|
'autoreply_template' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.autoreply_template',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.autoreply_template_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_autoreply',
|
|
],
|
|
'autoreply_subject' => [
|
|
'title' => 'janvince.smallcontactform::lang.components.properties.autoreply_subject',
|
|
'description' => 'janvince.smallcontactform::lang.components.properties.autoreply_subject_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_autoreply',
|
|
],
|
|
|
|
'allow_redirect' => [
|
|
'title' => 'janvince.smallcontactform::lang.settings.redirect.allow_redirect',
|
|
'description' => 'janvince.smallcontactform::lang.settings.redirect.allow_redirect_comment',
|
|
'type' => 'checkbox',
|
|
'default' => false,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_redirect',
|
|
],
|
|
|
|
'redirect_url' => [
|
|
'title' => 'janvince.smallcontactform::lang.settings.redirect.redirect_url',
|
|
'description' => 'janvince.smallcontactform::lang.settings.redirect.redirect_url_comment',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_redirect',
|
|
],
|
|
|
|
'redirect_url_external' => [
|
|
'title' => 'janvince.smallcontactform::lang.settings.redirect.redirect_url_external',
|
|
'description' => 'janvince.smallcontactform::lang.settings.redirect.redirect_url_external_comment',
|
|
'type' => 'checkbox',
|
|
'default' => false,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_redirect',
|
|
],
|
|
|
|
'ga_success_event_allow' => [
|
|
'title' => 'janvince.smallcontactform::lang.settings.ga.ga_success_event_allow',
|
|
'type' => 'checkbox',
|
|
'default' => false,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_ga',
|
|
],
|
|
|
|
'ga_success_event_category' => [
|
|
'title' => 'janvince.smallcontactform::lang.settings.form_fields.event_category',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_ga',
|
|
],
|
|
|
|
'ga_success_event_action' => [
|
|
'title' => 'janvince.smallcontactform::lang.settings.form_fields.event_action',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_ga',
|
|
],
|
|
|
|
'ga_success_event_label' => [
|
|
'title' => 'janvince.smallcontactform::lang.settings.form_fields.event_label',
|
|
'type' => 'string',
|
|
'default' => null,
|
|
'group' => 'janvince.smallcontactform::lang.components.groups.override_ga',
|
|
],
|
|
|
|
];
|
|
|
|
}
|
|
|
|
public function onRun() {
|
|
|
|
$this->page['currentLocale'] = App::getLocale();
|
|
|
|
$this->page['formSentAlias'] = Session::get('formSentAlias', null);
|
|
$this->page['formError'] = Session::get('formError', null);
|
|
$this->page['formSuccess'] = Session::get('formSuccess', null);
|
|
|
|
$this->formDescription = $this->property('form_description');
|
|
$this->formRedirect = $this->property('redirect_url');
|
|
|
|
// Inject CSS assets if required
|
|
if(Settings::getTranslated('add_assets') && Settings::getTranslated('add_css_assets')){
|
|
$this->addCss('/modules/system/assets/css/framework.extras.css');
|
|
$this->addCss('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css');
|
|
}
|
|
|
|
// Inject JS assets if required
|
|
if(Settings::getTranslated('add_assets') && Settings::getTranslated('add_js_assets')){
|
|
$this->addJs('https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js');
|
|
$this->addJs('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js');
|
|
$this->addJs('/modules/system/assets/js/framework.js');
|
|
$this->addJs('/modules/system/assets/js/framework.extras.js');
|
|
}
|
|
|
|
}
|
|
|
|
public function onRender() {
|
|
|
|
// Component markup parameters are accesible only from onRender method!
|
|
if($this->formDescription != $this->property('form_description') ) {
|
|
$this->formDescriptionOverride = $this->property('form_description');
|
|
}
|
|
|
|
if($this->formRedirect != $this->property('redirect_url') ) {
|
|
$this->formRedirectOverride = $this->property('redirect_url');
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Form handler
|
|
*/
|
|
public function onFormSend(){
|
|
|
|
/**
|
|
* Validation
|
|
*/
|
|
$this->setFieldsValidationRules();
|
|
$errors = [];
|
|
|
|
$this->post = Input::all();
|
|
|
|
// IP protection is enabled (has highest priority)
|
|
// But privacy must allow messages saving
|
|
if( Settings::getTranslated('add_ip_protection') and !Settings::getTranslated('privacy_disable_messages_saving') ) {
|
|
|
|
$max = ( Settings::getTranslated('add_ip_protection_count') ? intval(Settings::getTranslated('add_ip_protection_count')) : intval(e(trans('janvince.smallcontactform::lang.settings.antispam.add_ip_protection_count_placeholder'))) );
|
|
|
|
if( empty($max) ) {
|
|
$max = 3;
|
|
}
|
|
|
|
$currentIp = Request::ip();
|
|
|
|
if( empty($currentIp) ) {
|
|
Log::error('SMALL CONTACT FORM ERROR: Could not get remote IP address!');
|
|
$errors[] = e(trans('janvince.smallcontactform::lang.settings.antispam.add_ip_protection_error_get_ip'));
|
|
} else {
|
|
|
|
$message = new Message;
|
|
|
|
if($message->testIPAddress($currentIp) >= $max) {
|
|
$errors[] = ( Settings::getTranslated('add_ip_protection_error_too_many_submits') ? Settings::getTranslated('add_ip_protection_error_too_many_submits') : e(trans('janvince.smallcontactform::lang.settings.antispam.add_ip_protection_error_too_many_submits_placeholder')) );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Antispam validation if allowed
|
|
if( Settings::getTranslated('add_antispam')) {
|
|
$this->validationRules[('_protect-' . $this->alias)] = 'size:0';
|
|
|
|
if( !empty($this->post['_form_created']) ) {
|
|
|
|
try {
|
|
$delay = ( Settings::getTranslated('antispam_delay') ? intval(Settings::getTranslated('antispam_delay')) : intval(e(trans('janvince.smallcontactform::lang.settings.antispam.antispam_delay_placeholder'))) );
|
|
|
|
if(!$delay) {
|
|
$delay = 5;
|
|
}
|
|
|
|
$formCreatedTime = strtr(Input::get('_form_created'), 'jihgfedcba', '0123456789');
|
|
|
|
$this->post['_form_created'] = intval($formCreatedTime) + $delay;
|
|
|
|
$this->validationRules['_form_created'] = 'numeric|max:' . time();
|
|
}
|
|
catch (\Exception $e)
|
|
{
|
|
Log::error($e->getMessage());
|
|
$errors[] = e(trans('janvince.smallcontactform::lang.settings.antispam.antispam_delay_error_msg_placeholder'));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// reCaptcha validation if enabled
|
|
if(Settings::getTranslated('add_google_recaptcha'))
|
|
{
|
|
try {
|
|
/**
|
|
* Text if allow_url_fopen is disabled
|
|
*/
|
|
if (!ini_get('allow_url_fopen'))
|
|
{
|
|
$recaptcha = new ReCaptcha(Settings::get('google_recaptcha_secret_key'), new \ReCaptcha\RequestMethod\SocketPost());
|
|
}
|
|
else {
|
|
// allow_url_fopen = On
|
|
$recaptcha = new ReCaptcha(Settings::get('google_recaptcha_secret_key'));
|
|
}
|
|
|
|
$response = $recaptcha->setExpectedHostname($_SERVER['SERVER_NAME'])->verify(post('g-recaptcha-response'), $_SERVER['REMOTE_ADDR']);
|
|
}
|
|
catch(\Exception $e)
|
|
{
|
|
Log::error($e->getMessage());
|
|
$errors[] = e(trans('janvince.smallcontactform::lang.settings.antispam.google_recaptcha_error_msg_placeholder'));
|
|
}
|
|
|
|
if(!$response->isSuccess()) {
|
|
$errors[] = ( Settings::getTranslated('google_recaptcha_error_msg') ? Settings::getTranslated('google_recaptcha_error_msg') : e(trans('janvince.smallcontactform::lang.settings.antispam.google_recaptcha_error_msg_placeholder')));
|
|
}
|
|
|
|
}
|
|
|
|
// Validate sent data
|
|
$validator = Validator::make($this->post, $this->validationRules, $this->validationMessages);
|
|
$validator->valid();
|
|
$this->validationMessages = $validator->messages();
|
|
$this->setPostData($validator->messages());
|
|
|
|
if(empty($this->post['gapja'] or $this->post['gapja'] !='anti-spam')){
|
|
$errors[] ='Gapja must be filled with valid data';
|
|
}
|
|
|
|
if($validator->failed() or count($errors)){
|
|
|
|
// Form main error msg (can be overriden by component property)
|
|
if ( $this->property('form_error_msg') ) {
|
|
|
|
$errors[] = $this->property('form_error_msg');
|
|
|
|
} else {
|
|
|
|
$errors[] = ( Settings::getTranslated('form_error_msg') ? Settings::getTranslated('form_error_msg') : e(trans('janvince.smallcontactform::lang.settings.form.error_msg_placeholder')));
|
|
|
|
}
|
|
|
|
// Validation error msg for Antispam field
|
|
if( empty($this->postData[('_protect' . $this->alias)]['error']) && !empty($this->postData['_form_created']['error']) ) {
|
|
$errors[] = ( Settings::getTranslated('antispam_delay_error_msg') ? Settings::getTranslated('antispam_delay_error_msg') : e(trans('janvince.smallcontactform::lang.settings.antispam.antispam_delay_error_msg_placeholder')));
|
|
}
|
|
|
|
Flash::error(implode(PHP_EOL, $errors));
|
|
|
|
if (Request::ajax()) {
|
|
|
|
$this->page['formSentAlias'] = $this->alias;
|
|
$this->page['formError'] = true;
|
|
$this->page['formSuccess'] = null;
|
|
|
|
} else {
|
|
|
|
Session::flash('formSentAlias', $this->alias);
|
|
Session::flash('formError', true);
|
|
|
|
}
|
|
|
|
// Fill hidden fields if request has errors to maintain
|
|
$this->formDescriptionOverride = post('_form_description');
|
|
$this->formRedirectOverride = post('_form_redirect');
|
|
|
|
} else {
|
|
|
|
// Form main success msg (can be overriden by component property)
|
|
if ($this->property('form_success_msg')) {
|
|
|
|
$successMsg = $this->property('form_success_msg');
|
|
|
|
} else {
|
|
|
|
$successMsg = ( Settings::getTranslated('form_success_msg') ? Settings::getTranslated('form_success_msg') : e(trans('janvince.smallcontactform::lang.settings.form.success_msg_placeholder')) );
|
|
|
|
}
|
|
|
|
$message = new Message;
|
|
|
|
// Store data in DB
|
|
$formDescription = !empty($this->post['_form_description']) ? e($this->post['_form_description']) : $this->property('form_description');
|
|
$messageObject = $message->storeFormData($this->postData, $this->alias, $formDescription);
|
|
|
|
// Send autoreply
|
|
$message->sendAutoreplyEmail($this->postData, $this->getProperties(), $this->alias, $formDescription, $messageObject);
|
|
|
|
// Send notification
|
|
$message->sendNotificationEmail($this->postData, $this->getProperties(), $this->alias, $formDescription, $messageObject);
|
|
|
|
/**
|
|
* Flash messages
|
|
*/
|
|
Flash::success($successMsg);
|
|
|
|
if (Request::ajax()) {
|
|
|
|
$this->postData = [];
|
|
$this->page['formSentAlias'] = $this->alias;
|
|
$this->page['formSuccess'] = true;
|
|
$this->page['formError'] = null;
|
|
|
|
} else {
|
|
|
|
Session::flash('formSentAlias', $this->alias);
|
|
Session::flash('formSuccess', true);
|
|
|
|
}
|
|
|
|
/**
|
|
* Keep properties overrides after Ajax request (onRender method is not called)
|
|
*/
|
|
if (Request::ajax()) {
|
|
|
|
$this->formDescriptionOverride = post('_form_description');
|
|
$this->formRedirectOverride = post('_form_redirect');
|
|
|
|
}
|
|
|
|
/**
|
|
* Redirects
|
|
*
|
|
* Redirect to defined page or to prevent repeated sending of form
|
|
* Clear data after success AJAX send
|
|
*/
|
|
if( Settings::getTranslated('allow_redirect') or $this->property('allow_redirect') ) {
|
|
|
|
// Component markup parameter (eg. {{ component 'contactForm' redirect_url = '/form-success-'~page.id }} ) overrides component property
|
|
if(!empty($this->post['_form_redirect'])) {
|
|
|
|
$propertyRedirectUrl = e($this->post['_form_redirect']);
|
|
|
|
} else {
|
|
|
|
$propertyRedirectUrl = $this->property('redirect_url');
|
|
|
|
}
|
|
|
|
// If redirection is allowed but no URL provided, just refresh (if not AJAX)
|
|
if(empty($propertyRedirectUrl) and empty(Settings::getTranslated('redirect_url'))) {
|
|
|
|
Log::warning('SCF: Form redirect is allowed but no URL was provided!');
|
|
|
|
if (!Request::ajax()) {
|
|
|
|
return Redirect::refresh();
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Overrides take precedence
|
|
if( !empty(Settings::getTranslated('redirect_url_external')) and !empty($this->property('redirect_url_external')) ) {
|
|
|
|
$path = $propertyRedirectUrl ? $propertyRedirectUrl : Settings::getTranslated('redirect_url');
|
|
|
|
} else {
|
|
|
|
$path = $propertyRedirectUrl ? url($propertyRedirectUrl) : url(Settings::getTranslated('redirect_url'));
|
|
|
|
}
|
|
|
|
return Redirect::to($path);
|
|
|
|
} else {
|
|
|
|
if (!Request::ajax()) {
|
|
|
|
return Redirect::refresh();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Get plugin settings
|
|
* Twig access: contactForm.fields
|
|
* @return array
|
|
*/
|
|
public function fields(){
|
|
|
|
$fields = Settings::getTranslated('form_fields', []);
|
|
|
|
if( !empty($this->property('disable_fields')) ) {
|
|
|
|
$disabledFields = explode( '|', $this->property('disable_fields') );
|
|
|
|
if(!is_array($disabledFields)) {
|
|
return $fields;
|
|
}
|
|
|
|
foreach ($fields as $key => $value) {
|
|
|
|
if( isset($value['name']) and in_array(trim($value['name']), $disabledFields) ) {
|
|
unset($fields[$key]);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $fields;
|
|
}
|
|
|
|
/**
|
|
* Get form attributes
|
|
*/
|
|
public function getFormAttributes(){
|
|
|
|
$attributes = [];
|
|
|
|
$attributes['request'] = $this->alias . '::onFormSend';
|
|
$attributes['files'] = true;
|
|
|
|
// Disabled hard coded hash URL in 1.41.0 as dynamic redirect is now available
|
|
// $attributes['url'] = '#scf-' . $this->alias;
|
|
|
|
$attributes['method'] = 'POST';
|
|
$attributes['class'] = null;
|
|
$attributes['id'] = 'scf-form-id-' . $this->alias;
|
|
|
|
if( Settings::getTranslated('form_allow_ajax', 0) ) {
|
|
|
|
$attributes['data-request'] = $this->alias . '::onFormSend';
|
|
$attributes['data-request-validate'] = 'data-request-validate';
|
|
$attributes['data-request-files'] = 'data-request-files';
|
|
$attributes['data-request-update'] = "'". $this->alias ."::scf-message':'#scf-message-". $this->alias ."','". $this->alias ."::scf-form':'#scf-form-". $this->alias ."'";
|
|
|
|
}
|
|
|
|
if( Settings::getTranslated('form_css_class') ) {
|
|
$attributes['class'] .= Settings::getTranslated('form_css_class');
|
|
}
|
|
|
|
if( !empty(Input::all()) ) {
|
|
$attributes['class'] .= ' was-validated';
|
|
}
|
|
|
|
if( Settings::getTranslated('form_send_confirm_msg') and Settings::getTranslated('form_allow_confirm_msg') ) {
|
|
|
|
$attributes['data-request-confirm'] = Settings::getTranslated('form_send_confirm_msg');
|
|
|
|
}
|
|
|
|
// Disable browser validation if enabled
|
|
if(!empty(Settings::getTranslated('form_disable_browser_validation'))){
|
|
$attributes['novalidate'] = "novalidate";
|
|
}
|
|
|
|
return $attributes;
|
|
|
|
}
|
|
|
|
/**
|
|
* Generate field HTML code
|
|
* @return string
|
|
*/
|
|
public function getFieldHtmlCode(array $fieldSettings){
|
|
|
|
if(empty($fieldSettings['name']) && empty($fieldSettings['type'])){
|
|
return NULL;
|
|
}
|
|
|
|
$fieldType = Settings::getFieldTypes($fieldSettings['type']);
|
|
$fieldRequired = $this->isFieldRequired($fieldSettings);
|
|
|
|
// If there is a custom code, return it only
|
|
if( !empty($fieldSettings['type']) and $fieldSettings['type'] == 'custom_code' and !empty($fieldSettings['field_custom_code']) ) {
|
|
|
|
if( !empty($fieldSettings['field_custom_code_twig']) ) {
|
|
return(Twig::parse($fieldSettings['field_custom_code']));
|
|
} else {
|
|
return($fieldSettings['field_custom_code']);
|
|
}
|
|
}
|
|
|
|
$output = [];
|
|
|
|
$wrapperCss = ( $fieldSettings['wrapper_css'] ? $fieldSettings['wrapper_css'] : $fieldType['wrapper_class'] );
|
|
|
|
// Add wrapper error class if there are any
|
|
if(!empty($this->postData[$fieldSettings['name']]['error'])){
|
|
$wrapperCss .= ' has-error';
|
|
}
|
|
|
|
$output[] = '<div class="' . $wrapperCss . '">';
|
|
|
|
// Checkbox wrapper
|
|
if ($fieldSettings['type'] == 'checkbox') {
|
|
$output[] = '<div class="checkbox">';
|
|
}
|
|
|
|
// Label classic
|
|
if( !empty($fieldSettings['label']) and !empty($fieldType['label']) ){
|
|
$output[] = '<label class="control-label ' . ( !empty($fieldSettings['label_css']) ? $fieldSettings['label_css'] : '' ) . ' ' . ( $fieldRequired ? 'required' : '' ) . '" for="' . ($this->alias . '-' . $fieldSettings['name']) . '" ' . (Settings::getTranslated('form_use_placeholders') ? ' style="display: none;" ' : '') . '>' . Settings::getDictionaryTranslated($fieldSettings['label']) . '</label>';
|
|
}
|
|
|
|
// Label as container
|
|
if( !empty($fieldSettings['label']) and empty($fieldType['label']) ){
|
|
$output[] = '<label class="' . ( !empty($fieldSettings['label_css']) ? $fieldSettings['label_css'] : '' ) . '">';
|
|
}
|
|
|
|
|
|
// Add help-block if there are errors
|
|
if(!empty($this->postData[$fieldSettings['name']]['error'])){
|
|
$output[] = '<small class=" invalid-feedback">' . Settings::getDictionaryTranslated($this->postData[$fieldSettings['name']]['error']) . "</small>";
|
|
}
|
|
|
|
// Field attributes
|
|
$attributes = [
|
|
'id' => $this->alias . '-' . $fieldSettings['name'],
|
|
'class' => null
|
|
];
|
|
|
|
$tagClass = $fieldSettings['field_css'] ? $fieldSettings['field_css'] : $fieldType['field_class'];
|
|
|
|
if(!empty($tagClass)) {
|
|
$attributes['class'] = $tagClass;
|
|
}
|
|
|
|
if(!empty($fieldType['use_name_attribute'])) {
|
|
$attributes['name'] = $fieldSettings['name'];
|
|
}
|
|
|
|
if ( !empty($this->postData[$fieldSettings['name']]['value']) && empty($fieldType['html_close']) ) {
|
|
|
|
if ($fieldSettings['type'] == 'checkbox') {
|
|
$attributes['checked'] = null;
|
|
} else {
|
|
$attributes['value'] = $this->postData[$fieldSettings['name']]['value'];
|
|
}
|
|
}
|
|
|
|
// Placeholders if enabled
|
|
if(Settings::getTranslated('form_use_placeholders') and $fieldSettings['type'] <> 'checkbox'){
|
|
$attributes['placeholder'] = Settings::getDictionaryTranslated($fieldSettings['label']);
|
|
}
|
|
|
|
// Autofocus only when no error
|
|
if(!empty($fieldSettings['autofocus']) && !Flash::error()){
|
|
$attributes['autofocus'] = NULL;
|
|
}
|
|
|
|
// Add custom attributes from field settings
|
|
if(!empty($fieldType['attributes'])){
|
|
$attributes = array_merge($attributes, $fieldType['attributes']);
|
|
}
|
|
|
|
// Add error class if there are any and autofocus field
|
|
if(!empty($this->postData[$fieldSettings['name']]['error'])){
|
|
$attributes['class'] = $attributes['class'] . ' error is-invalid';
|
|
|
|
if(empty($this->errorAutofocus)){
|
|
$attributes['autofocus'] = NULL;
|
|
$this->errorAutofocus = true;
|
|
}
|
|
|
|
}
|
|
|
|
if($fieldRequired){
|
|
$attributes['required'] = NULL;
|
|
}
|
|
|
|
|
|
$output[] = '<' . $fieldType['html_open'] . ' ' . $this->formatAttributes($attributes) . '>';
|
|
|
|
// For dropdown add options
|
|
if( $fieldSettings['type'] == 'dropdown' && count($fieldSettings['field_values']) ) {
|
|
|
|
$valuesCounter = 1;
|
|
|
|
foreach($fieldSettings['field_values'] as $fieldValue) {
|
|
|
|
if( !empty($this->postData[$fieldSettings['name']]['value']) && $this->postData[$fieldSettings['name']]['value'] == $fieldValue['field_value_id'] ){
|
|
$optionAttribute = 'selected';
|
|
} else {
|
|
$optionAttribute = null;
|
|
}
|
|
|
|
$output[] = "<option $optionAttribute value='" . $fieldValue['field_value_id'] . "'>" . $fieldValue['field_value_content'] . "</option>";
|
|
|
|
$valuesCounter++;
|
|
|
|
}
|
|
|
|
}
|
|
// For pair tags insert value between
|
|
if(!empty($this->postData[$fieldSettings['name']]['value']) && !empty($fieldType['html_close'])){
|
|
$output[] = $this->postData[$fieldSettings['name']]['value'];
|
|
}
|
|
|
|
// For tags without label put text inline
|
|
if( empty( $fieldType['label'] ) ){
|
|
$output[] = Settings::getDictionaryTranslated($fieldSettings['label']);
|
|
}
|
|
|
|
// If there is a custom content
|
|
if (!empty($fieldSettings['type']) and $fieldSettings['type'] == 'custom_content' and !empty($fieldSettings['field_custom_content'])) {
|
|
$output[] = $fieldSettings['field_custom_content'];
|
|
}
|
|
|
|
if(!empty($fieldType['html_close'])){
|
|
$output[] = '</' . $fieldType['html_close'] . '>';
|
|
}
|
|
|
|
// Label as container
|
|
if( !empty($fieldSettings['label']) and empty($fieldType['label']) ){
|
|
$output[] = '</label>';
|
|
}
|
|
|
|
// Checkbox wrapper
|
|
if ($fieldSettings['type'] == 'checkbox') {
|
|
$output[] = '</div>';
|
|
}
|
|
|
|
$output[] = "</div>";
|
|
|
|
return(implode('', $output));
|
|
|
|
}
|
|
|
|
/**
|
|
* Generate antispam field HTML code
|
|
* @return string
|
|
*/
|
|
public function getAntispamFieldHtmlCode(){
|
|
|
|
if( !Settings::getTranslated('add_antispam') ){
|
|
return NULL;
|
|
}
|
|
|
|
$output = [];
|
|
|
|
$output[] = '<div id="_protect-wrapper-' . $this->alias . '" class="form-group _protect-wrapper' . (Input::get('_protect-'.$this->alias) ? 'has-error' : '') . '">';
|
|
|
|
$output[] = '<label class="control-label">' . ( Settings::getTranslated('antispam_label') ? Settings::getTranslated('antispam_label') : e(trans('janvince.smallcontactform::lang.settings.antispam.antispam_label_placeholder')) ) . '</label>';
|
|
|
|
$output[] = '<input type="hidden" name="_form_created" value="' . strtr(time(), '0123456789', 'jihgfedcba') . '">';
|
|
|
|
// Add help-block if there are errors
|
|
if(!empty($this->postData[('_protect'.$this->alias)]['error'])){
|
|
$output[] = '<small class="help-block">' . ( Settings::getTranslated('antispam_error_msg') ? Settings::getTranslated('antispam_error_msg') : e(trans('janvince.smallcontactform::lang.settings.antispam.antispam_error_msg_placeholder')) ) . "</small>";
|
|
}
|
|
|
|
// Field attributes
|
|
$attributes = [
|
|
'id' => '_protect-'.$this->alias,
|
|
'name' => '_protect',
|
|
'class' => '_protect form-control',
|
|
'value' => 'http://',
|
|
];
|
|
|
|
// Add error class if field is not empty
|
|
if( Input::get('_protect-'.$this->alias) ){
|
|
$attributes['class'] = $attributes['class'] . ' error';
|
|
|
|
if(empty($this->errorAutofocus)){
|
|
$attributes['autofocus'] = NULL;
|
|
$this->errorAutofocus = true;
|
|
}
|
|
|
|
}
|
|
|
|
$output[] = '<input ' . $this->formatAttributes($attributes) . '>';
|
|
|
|
$output[] = "</div>";
|
|
|
|
$output[] = "
|
|
<script>
|
|
document.getElementById('_protect-" . $this->alias . "').setAttribute('value', '');
|
|
document.getElementById('_protect-wrapper-" . $this->alias . "').style.display = 'none';
|
|
</script>
|
|
";
|
|
|
|
return(implode('', $output));
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Generate description field HTML code
|
|
* @return string
|
|
*/
|
|
public function getDescriptionFieldHtmlCode(){
|
|
|
|
if( !$this->formDescriptionOverride ){
|
|
return NULL;
|
|
}
|
|
|
|
$output = [];
|
|
|
|
// Field attributes
|
|
$attributes = [
|
|
'id' => '_form_description-'.$this->alias,
|
|
'type' => 'hidden',
|
|
'name' => '_form_description',
|
|
'class' => '_form_description form-control',
|
|
'value' => $this->formDescriptionOverride,
|
|
];
|
|
|
|
$output[] = '<input ' . $this->formatAttributes($attributes) . '>';
|
|
|
|
return(implode('', $output));
|
|
|
|
}
|
|
|
|
/**
|
|
* Generate redirect field HTML code
|
|
* @return string
|
|
*/
|
|
public function getRedirectFieldHtmlCode(){
|
|
|
|
if (empty(Settings::getTranslated('allow_redirect')) and empty($this->property('allow_redirect'))) {
|
|
return NULL;
|
|
}
|
|
|
|
if( !$this->formRedirectOverride ){
|
|
return NULL;
|
|
}
|
|
|
|
$output = [];
|
|
|
|
// Field attributes
|
|
$attributes = [
|
|
'id' => '_form_redirect-'.$this->alias,
|
|
'type' => 'hidden',
|
|
'name' => '_form_redirect',
|
|
'class' => '_form_redirect form-control',
|
|
'value' => $this->formRedirectOverride,
|
|
];
|
|
|
|
$output[] = '<input ' . $this->formatAttributes($attributes) . '>';
|
|
|
|
return(implode('', $output));
|
|
|
|
}
|
|
|
|
/**
|
|
* Generate success GA event field HTML code
|
|
* @return string
|
|
*/
|
|
public function getGaSuccessEventHtmlCode($addScriptTag = false)
|
|
{
|
|
|
|
// If GA success event is not allowed
|
|
if (empty(Settings::getTranslated('ga_success_event_allow')) and empty($this->property('ga_success_event_allow'))) {
|
|
return;
|
|
}
|
|
|
|
$output = [];
|
|
|
|
// Field attributes
|
|
$attributes = [
|
|
'hitType' => 'event',
|
|
'eventCategory' => ($this->property('ga_success_event_category') ? e($this->property('ga_success_event_category')) : Settings::getTranslated('ga_success_event_category')),
|
|
'eventAction' => ($this->property('ga_success_event_action') ? e($this->property('ga_success_event_action')) : Settings::getTranslated('ga_success_event_action')),
|
|
'eventLabel' => ($this->property('ga_success_event_label') ? e($this->property('ga_success_event_label')) : Settings::getTranslated('ga_success_event_label')),
|
|
];
|
|
|
|
if($addScriptTag) {
|
|
$output[] = "<script>";
|
|
}
|
|
|
|
$output[] = "ga('send', { " . $this->formatAttributes($attributes, true) . " }); ";
|
|
|
|
if ($addScriptTag) {
|
|
$output[] = "</script>";
|
|
}
|
|
|
|
return (implode('', $output));
|
|
}
|
|
|
|
/**
|
|
* Generate submit button field HTML code
|
|
* @return string
|
|
*/
|
|
public function getSubmitButtonHtmlCode(){
|
|
|
|
if( !count($this->fields()) ){
|
|
return e(trans('janvince.smallcontactform::lang.controller.contact_form.no_fields'));
|
|
}
|
|
|
|
$output = [];
|
|
|
|
$wrapperCss = ( Settings::getTranslated('send_btn_wrapper_css') ? Settings::getTranslated('send_btn_wrapper_css') : e(trans('janvince.smallcontactform::lang.settings.buttons.send_btn_wrapper_css_placeholder')) );
|
|
|
|
$output[] = '<div id="submit-wrapper-' . $this->alias . '" class="' . $wrapperCss . '">';
|
|
|
|
$output[] = '<button type="submit" data-attach-loading class="oc-loader ' . ( Settings::getTranslated('send_btn_css_class') ? Settings::getTranslated('send_btn_css_class') : e(trans('janvince.smallcontactform::lang.settings.buttons.send_btn_css_class_placeholder')) ) . (Settings::getTranslated('google_recaptcha_version') == 'v2invisible' ? ' g-recaptcha' : '') . '"'. (Settings::getTranslated('google_recaptcha_version') == 'v2invisible' ? (' data-sitekey="' . Settings::getTranslated('google_recaptcha_site_key') . '"') : '') . (Settings::getTranslated('google_recaptcha_version') == 'v2invisible' ? (' data-callback="onSubmit_' . $this->alias . '"') : '') . '>';
|
|
|
|
if ($this->property('send_btn_label')) {
|
|
|
|
$output[] = $this->property('send_btn_label');
|
|
|
|
} else {
|
|
|
|
$output[] = ( Settings::getTranslated('send_btn_text') ? Settings::getTranslated('send_btn_text') : e(trans('janvince.smallcontactform::lang.settings.buttons.send_btn_text_placeholder')) );
|
|
|
|
}
|
|
|
|
$output[] = '</button>';
|
|
|
|
$output[] = "</div>";
|
|
|
|
return(implode('', $output));
|
|
|
|
}
|
|
|
|
/**
|
|
* Get reCaptcha wrapper class
|
|
* @return string
|
|
*/
|
|
public function getReCaptchaWrapperClass(){
|
|
|
|
$wrapperCss = ( Settings::getTranslated('google_recaptcha_wrapper_css') ? Settings::getTranslated('google_recaptcha_wrapper_css') : e(trans('janvince.smallcontactform::lang.settings.antispam.google_recaptcha_wrapper_css_placeholder')) );
|
|
|
|
return $wrapperCss;
|
|
|
|
}
|
|
|
|
/**
|
|
* Generate validation rules and messages
|
|
*/
|
|
private function setFieldsValidationRules(){
|
|
|
|
$fieldsDefinition = $this->fields();
|
|
|
|
$validationRules = [];
|
|
$validationMessages = [];
|
|
foreach($fieldsDefinition as $field){
|
|
|
|
if(!empty($field['validation'])) {
|
|
$rules = [];
|
|
|
|
foreach($field['validation'] as $rule) {
|
|
|
|
if( $rule['validation_type']=='custom' && !empty($rule['validation_custom_type']) ){
|
|
|
|
if(!empty($rule['validation_custom_pattern'])) {
|
|
|
|
switch ($rule['validation_custom_type']) {
|
|
|
|
/**
|
|
* Keep regex pattern in an array
|
|
*/
|
|
case "regex":
|
|
|
|
$rules[] = [$rule['validation_custom_type'], $rule['validation_custom_pattern']];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$rules[] = $rule['validation_custom_type'] . ':' . $rule['validation_custom_pattern'];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
$rules[] = $rule['validation_custom_type'];
|
|
|
|
}
|
|
|
|
if(!empty($rule['validation_error'])){
|
|
|
|
$validationMessages[($field['name'] . '.' . $rule['validation_custom_type'] )] = Settings::getDictionaryTranslated($rule['validation_error']);
|
|
}
|
|
|
|
} else {
|
|
|
|
$rules[] = $rule['validation_type'];
|
|
|
|
if(!empty($rule['validation_error'])){
|
|
|
|
$validationMessages[($field['name'] . '.' . $rule['validation_type'] )] = Settings::getDictionaryTranslated($rule['validation_error']);
|
|
}
|
|
}
|
|
}
|
|
|
|
$validationRules[$field['name']] = $rules;
|
|
}
|
|
}
|
|
|
|
$this->validationRules = $validationRules;
|
|
$this->validationMessages = $validationMessages;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Generate post data with errors
|
|
*/
|
|
private function setPostData(MessageBag $validatorMessages){
|
|
|
|
foreach( $this->fields() as $field){
|
|
|
|
$this->postData[ $field['name'] ] = [
|
|
'value' => e(Input::get($field['name'])),
|
|
'error' => $validatorMessages->first($field['name']),
|
|
];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Format attributes array
|
|
* @return array
|
|
*/
|
|
private function formatAttributes(array $attributes, $jsArray = false) {
|
|
|
|
$output = [];
|
|
|
|
foreach ($attributes as $key => $value) {
|
|
$output[] = $key . ($jsArray ? ': "' : '="') . $value . '"';
|
|
}
|
|
|
|
return implode(($jsArray ? ', ' : ' '), $output);
|
|
}
|
|
|
|
/**
|
|
* Search for required validation type
|
|
*/
|
|
private function isFieldRequired($fieldSettings){
|
|
|
|
if(empty($fieldSettings['validation'])){
|
|
return false;
|
|
}
|
|
|
|
foreach($fieldSettings['validation'] as $rule) {
|
|
if(!empty($rule['validation_type']) && $rule['validation_type'] == 'required'){
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|