added about us and contact us page, fixed localization changing

This commit is contained in:
Amanmyrat 2022-09-06 13:19:48 +05:00
parent 964f79d117
commit 155b779408
82 changed files with 11839 additions and 36 deletions

View File

@ -45,7 +45,7 @@ class ThemeData extends Model
/**
* @var array Relations
*/
public $attachOne = [];
public $attachOne = ['image' => 'Tps\Shops\Classes\Attachment'];
/**
* @var ThemeData Cached array of objects

View File

@ -0,0 +1,3 @@
# Ignore files and folders:
.DS_Store
.vscode

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Jan Vince
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,202 @@
<?php
namespace JanVince\SmallContactForm;
use \Illuminate\Support\Facades\Event;
use System\Classes\PluginBase;
use System\Classes\PluginManager;
use Config;
use Backend;
use Validator;
use Log;
use JanVince\SmallContactForm\Models\Settings;
class Plugin extends PluginBase {
/**
* @var array Plugin dependencies
*/
public $require = [];
/**
* Returns information about this plugin.
*
* @return array
*/
public function pluginDetails() {
return [
'name' => 'janvince.smallcontactform::lang.plugin.name',
'description' => 'janvince.smallcontactform::lang.plugin.description',
'author' => 'Jan Vince',
'icon' => 'icon-inbox'
];
}
public function boot() {
/**
* Custom Validator rules
*/
Validator::extend('custom_not_regex', function ($attribute, $value, $parameters) {
if (is_array($parameters)) {
$param = $parameters[0];
} else {
$param = $parameters;
}
try {
$result = preg_match($param, $value);
if ($result === 1) {
return false;
} else {
return true;
}
} catch (\Exception $e) {
Log::error('Error in Small Contact Form custom_not_regex validation rule! ' . $e->getMessage());
}
return false;
});
}
public function registerSettings() {
return [
'settings' => [
'label' => 'janvince.smallcontactform::lang.plugin.name',
'description' => 'janvince.smallcontactform::lang.plugin.description',
'category' => 'Small plugins',
'icon' => 'icon-inbox',
'class' => 'JanVince\SmallContactForm\Models\Settings',
'keywords' => 'small contact form message recaptcha antispam',
'order' => 990,
'permissions' => ['janvince.smallcontactform.access_settings'],
]
];
}
public function registerNavigation(){
return [
'smallcontactform' => [
'label' => 'janvince.smallcontactform::lang.navigation.main_label',
'url' => Backend::url('janvince/smallcontactform/messages'),
'icon' => 'icon-inbox',
'permissions' => ['janvince.smallcontactform.access_messages'],
'order' => 990,
],
];
}
public function registerPermissions(){
return [
'janvince.smallcontactform.access_messages' => [
'label' => 'janvince.smallcontactform::lang.permissions.access_messages',
'tab' => 'janvince.smallcontactform::lang.plugin.name',
],
'janvince.smallcontactform.access_settings' => [
'label' => 'janvince.smallcontactform::lang.permissions.access_settings',
'tab' => 'janvince.smallcontactform::lang.plugin.name',
],
'janvince.smallcontactform.delete_messages' => [
'label' => 'janvince.smallcontactform::lang.permissions.delete_messages',
'tab' => 'janvince.smallcontactform::lang.plugin.name',
],
'janvince.smallcontactform.export_messages' => [
'label' => 'janvince.smallcontactform::lang.permissions.export_messages',
'tab' => 'janvince.smallcontactform::lang.plugin.name',
],
];
}
public function registerComponents()
{
return [
'JanVince\SmallContactForm\Components\SmallContactForm' => 'contactForm',
];
}
public function registerPageSnippets()
{
return [
'JanVince\SmallContactForm\Components\SmallContactForm' => 'contactForm',
];
}
public function registerMailTemplates()
{
return Settings::getTranslatedTemplates();
}
public function registerMarkupTags()
{
return [
'filters' => [
],
'functions' => [
'trans' => function($value) { return e(trans($value)); },
'html_entity_decode' => function($value) { return html_entity_decode($value); },
'settingsGet' => function($value, $default = NULL) { return Settings::get($value, $default); }
]
];
}
/**
* Custom list types
*/
public function registerListColumnTypes()
{
return [
'strong' => function($value) { return '<strong>'. $value . '</strong>'; },
'text_preview' => function($value) { $content = mb_substr(strip_tags($value), 0, 150); if(mb_strlen($content) > 150) { return ($content . '...'); } else { return $content; } },
'array_preview' => function($value) { $content = mb_substr(strip_tags( implode(' --- ', $value) ), 0, 150); if(mb_strlen($content) > 150) { return ($content . '...'); } else { return $content; } },
'switch_icon_star' => function($value) { return '<div class="text-center"><span class="'. ($value==1 ? 'oc-icon-circle text-success' : 'text-muted oc-icon-circle text-draft') .'">' . ($value==1 ? e(trans('janvince.smallcontactform::lang.models.message.columns.new')) : e(trans('janvince.smallcontactform::lang.models.message.columns.read')) ) . '</span></div>'; },
'switch_extended_input' => function($value) { if($value){return '<span class="list-badge badge-success"><span class="icon-check"></span></span>';} else { return '<span class="list-badge badge-danger"><span class="icon-minus"></span></span>';} },
'switch_extended' => function($value) { if($value){return '<span class="list-badge badge-success"><span class="icon-check"></span></span>';} else { return '<span class="list-badge badge-danger"><span class="icon-minus"></span></span>';} },
'attached_images_count' => function($value){ return (count($value) ? count($value) : NULL); },
'image_preview' => function($value) {
$width = Settings::get('records_list_preview_width') ? Settings::get('records_list_preview_width') : 50;
$height = Settings::get('records_list_preview_height') ? Settings::get('records_list_preview_height') : 50;
if($value){ return "<img src='".$value->getThumb($width, $height)."' style='width: auto; height: auto; max-width: ".$width."px; max-height: ".$height."px'>"; }
},
'scf_files_link' => function($value){
if(!empty($value)) {
$output = [];
foreach($value as $file) {
$output[] = "<div><a class='btn btn-primary' href='".$file->getPath()."'>Open file</a></div>";
}
return implode('', $output);
}
},
];
}
public function registerReportWidgets()
{
return [
'JanVince\SmallContactForm\ReportWidgets\Messages' => [
'label' => 'janvince.smallcontactform::lang.reportwidget.partials.messages.label',
'context' => 'dashboard'
],
'JanVince\SmallContactForm\ReportWidgets\NewMessage' => [
'label' => 'janvince.smallcontactform::lang.reportwidget.partials.new_message.label',
'context' => 'dashboard'
],
];
}
}

View File

@ -0,0 +1,446 @@
# Small Contact form
> Simple but flexible contact form builder with custom fields, validation and passive antispam.
## Installation
**GitHub** clone into `/plugins` dir:
```sh
git clone https://github.com/jan-vince/smallcontactform
```
**OctoberCMS backend**
Just look for 'Small Contact Form' in search field in:
> Settings > Updates & Plugins > Install plugins
### Permissions
> Settings > Administrators
You can set permissions to restrict access to *Settings > Small plugins > Contact form* and to messages list.
### Installation with composer
* Edit composer.json by adding new repository
```
"repositories": [
{
"type": "vcs",
"url": "https://github.com/jan-vince/smallcontactform"
}
]
```
* run in command line
```sh
composer require janvince/smallcontactform
```
## Setup new Contact form
> Settings > Small Contact form
### FORM
* You can set your own CSS class name and general success/error messages.
* If you need it, placeholders can be used instead of labels
* Form can be hidden after successful submit.
#### Enable AJAX
By default, sending form will trigger page reload. With AJAX, everything can be done without page reloading which will be more user friendly.
*If user's browser doesn't support (or has disabled) JavaScript, form will still work with page reloads after send.*
* For AJAX enabled form, before send confirmation dialog can be required.
#### Add Assets
If you want to start quickly, you can enable Add assets checkbox - and then Add CSS and JS assets.
This will include necessary styles (Bootstrap, AJAX, October AJAX) and scripts (jQuery, Bootstrap, October AJAX framework and extras).
But you have to include Twig tags ````{% styles %}```` and ````{% scripts %}```` into your layout or page like this:
````
<html>
<head>
{% styles %}
</head>
<body>
{% page %}
{% scripts %}
</body>
</html>
````
If you want to insert assets by hand, you can do it this way (or similar):
````
<html>
<head>
<link href="{{['~/modules/system/assets/css/framework.extras.css']|theme }}.css" rel="stylesheet">
</head>
<body>
{% page %}
<script type="text/javascript" src="{{ [
'@jquery',
'@framework',
'@framework.extras']|theme}}.js">
</script>
</body>
</html>
````
#### Notes
You can add your notes that can be displayed in mail templates. Field is accesiible with {{ form_notes }}.
Form notes content can be overriden in component's properties.
### SEND BUTTON
* You can set button class and text.
#### Redirection after the form is sent
You have some options to control redirection after form is successfully sent:
* In main form settings you can allow redirection and set fixed URL (internal or external)
* In component properties (on CMS Page or Layout) you can override main redirection settings for a specific form
* You can add a dynamic redirect URL as a markup parameter eg. `{% component 'contactForm' redirect_url = ('/success#'~this.page.id) %}`
> If you use markup parameter do not forget to allow form redirection in form main settings or (rather) in component parameters ! There is no markup parametr to allow redirection.
### FIELDS
Here you can add fields to build your contact (or other) form.
The idea is simple (and solution is so I hope):
* Click to add new field
* Set it's name (this is used for ````<input name="{{name}}" id="{{name}}">````), so it should be lowercase without special characters.
* Set Label if you need one (it is used for descriptive text above input field)
* Set autofocus if you want cursor to automatically jump to this field (if checked more than one field, cursor jumps to first one)
When dropdown is selected there will be values/options repeater shown. You can add as many values you need.
> Hint: you can add dropdown empty option by adding a value with empty ID.
You can also use **Custom code** and have complete control of generated code.
There is also a **Custom content** field to add formated content in place of a field.
#### Field data validation
You can select from predefined rules or add custom Validator rules (read [documentation](https://octobercms.com/docs/services/validation#available-validation-rules)).
Some rules require additional validation pattern some of them not.
* You can add one or more validation rules and error messages for them
* Error messages will be shown above input field
* You can reorder fields by drag and drop left circle (all fields can be collapsed by pressing Ctrl+click (Cmd+click on MacOS) on arrow in right top corners)
> Hint: For dropdown validation you can use `custom` validation type with rule `in` and list of IDs in `pattern` field (eg: 1,2,3).
> Note: There is a `custom_not_regex` validation rule as an inverse to built in `regex`.
### COLUMNS MAPPING
System writes all form data in database, but for quick overview Name, Email and Message columns are visible separately in Messages list.
But you have to help system to identify these columns by mapping to your form fields.
These mappings are also used for autoreply emails where at least Email field mapping is important.
### ANTISPAM
#### Passive antispam
Very simple implementation of passive antispam (inspired by [Nette AntiSpam Control](https://gist.github.com/Michal-Mikolas/2388131)).
The idea behind this is to check how fast is form send and if robots-catching field is filled.
* When allowed, you can set form delay (in seconds) to prevent too fast form sending (mostly by robots). You can add custom error message (will be shown in general error message box above form).
* You can add antispam field label and error message for non JavaScript enabled browsers.
* If JavaScript is working, antispam field is automatically hidden and cleared.
#### Google reCaptcha
Implementation of Google reCaptcha antispam protection.
##### Setup
First you have to create new API keys pair in reCaptcha admin panel.
Hit **Get reCAPTCHA** button on [reCaptcha wellcome page](https://www.google.com/recaptcha). Set label and check reCAPTCHA v2 option and hit button Register. Note that you will have to add `localhost` to the allowed domains list if you want the recaptcha validation to work locally.
Copy Site key and Secret key to Contact Form's settings fields.
If you want Contact Form to automatically include server scripts in your layout, check the button in Form settings.
#### Check sender's IP
You can add an extra form protection with limit submits from one IP address.
This check has own error message and custom field to set maximum submits.
### EMAIL
Mails can be sent directly or queued ([OctoberCMS queue](https://octobercms.com/docs/services/queues) must be configured!).
Don't forget to configure mail preferences in *Settings > Mail > Mail configuration*!
#### Data in email templates
There are variables available in all email templates:
* **fields** is array of [ 'field name' => 'post value' ]
* **fieldsDetails** is array of [ 'field name' => ['name', 'value', 'type', ...] ]
* **uploads** is array of uploads (of class `System\Models\File`)
* **messageObject** is a model instance of a selected message
#### Allow autoreply
Email can be send to form sender as confirmation.
* You have to enter email address and name - it will be used as FROM field
* Email subject can be manually added here (or edited in *Settings > Mail > Mail templates (code: janvince.smallcontactform::mail.autoreply)*)
* Email TO address and name have to be assigned to form fields (in selections only corresponding field types are shown - if you don't see one, try to check it's type in Fields tab)
* Email REPLY TO address can be set
* Message field can be also assigned (and will be saved separately into database)
#### Allow notifications
Once a Contact form is sent a notification can be immediately send to a provided email address (or comma-separated list of addresses).
*A **Reply to** address of notification email will be set to an email address from Contact form (if this field is used).*
You can also force **From** address to be set to the one entered in Contact form - but not all email systems support this!
## TRANSLATION
You can allow translation with [RainLab Translate](https://octobercms.com/plugin/rainlab-translate) plugin.
> After installation of Translate plugin, please add at least two languages in *Settings > Translate > Manage languages*.
> For translations to work there must be a localePicker component included in your layout/page.
#### Form texts
Most of Small Contact form texts can be edited right in *Settings > Small plugins > Contact form*.
#### Custom form fields
Translate plugin doesn't supports translation of individual repeater fields yet, so form field texts (label, validation error messages) have to be - for now - translated in a dictionary: *Settings > Translate > Translate messages*
> Please note that form fields labels will be shown in dictionary after first form render (on your frontend page) and validation error messages after first send.
#### Email templates
You can create your own email templates in *Settings > Mail > Mail templates* (for hint look inside of default templates starting with *janvince.smallcontactform::*).
Remember your email templates CODE and put in in Small Contact form email settings in *Settings > Small plugins > Contact form > Email tab*. For each language there can be specific template.
There are `{{fields}}` and `{{fieldsDetails}}` arrays available inside of email templates.
You can also use `{{url}}` variable to get original request URL.
*If your custom form field has name eg. 'email', you use it in template with ````{{fields.email}}````.*
You can itterate over uploaded files with:
```
{% for item in uploads %}
<a href="{{ item.getPath }}">Uploaded file</a>
{% endfor %}
```
You can access model data with eg. `{{ messageObject.id }}`.
## GOOGLE ANALYTICS
> if you want to use these settings, be sure to have Google Analytics scripts included on your site. You can use [Rainlab Google Analytics plugin](https://octobercms.com/plugin/rainlab-googleanalytics).
### Events
You can allow events to be send to your GA account when the form is successfully sent.
There are (translatable) fields for category, action and label.
*All event settings can be overriden in component property so if you use more then one form, you can custommize events for each of them.*
## MESSAGES LIST
All sent data from Contact form are saved and listed in backend Messages list.
If email, name and message fields are assigned on *Settings > Small plugins > contact form > Columns mapping tab*, they will be saved and shown in separate columns.
You can click on a record to see all form data. The message will be marked as read.
## DASHBOARD REPORT WIDGETS
There are available report widgets to be used on OctoberCMS dashboard.
#### Messages stats
Shows basic messages statistics.
#### New messages
Shows number of new messages. The color changes to green if there are any.
You can simply click widget to open Messages list.
## Overriding form settings
You can override some of the form settings in component dropdown (on page or layout) or by passing them in component call.
#### Form settings
*There is also an Alias column that contain component's alias of the used form and is saved in messages log (this field is invisible by default in messages table).*
````
[contactForm myForm]
form_description = 'Form used in home page'
disable_fields = 'name|message'
send_btn_label = 'Go'
form_success_msg = 'Ok, sent :)'
form_error_msg = 'Houston, we have a problem'
````
You can override form's property in Twig component tag, eg:
````
{% component 'myForm' form_description = 'My other description' send_btn_label = 'Stay in touch' %}
````
This can be even more complex:
````
{% set myVar = 12345 %}
{% component 'myForm' form_description = ('Current value: ' ~ myVar) %}
````
In email template you can access some of these variables like this:
````
Form alias: {{fields.form_alias}}
Form description: {{fields.form_description}}
````
> When you override form description in ````{% component form_description = 'My description' %}````, description will be added as a **hidden field** into a form. Do not use this to store private data as this is easily visible in page HTML code!
#### Override notification email options
You can set different email address to which notification about sent form will be delivered and also change a notification template.
*Template must exist in Settings > Mail > Mail configuration*.
If you add a locale string to ````notification_template```` property (like ````notification_template_en````) than that one has priority and will be used if ````App::getLocale()```` returns ````en````.
````
[contactForm salesForm]
disable_notifications = true
notification_address_to = 'sales@domain.com'
notification_address_from = 'contactform@domain.com'
notification_template = 'notification-sales'
notification_template_en = 'notification-sales-en'
notification_template_cs = 'notification-sales-cs'
notification_subject = 'Notification sent by form {{ fields.form_alias }} on {{ "now"|date }}'
````
> Local strings in `notification_template` canot be used in Twig!
#### Override autoreply email options
You can set different email address and name for autoreply message and also use different autoreply template.
*Template must exist in Settings > Mail > Mail configuration*.
If you add a locale string to ````autoreply_template```` or ````autoreply_address_from_name```` property (like ````autoreply_template_en```` or ````autoreply_address_from_name_en````) than that one has priority and will be used if ````App::getLocale()```` returns ````en````.
````
[contactForm orderForm]
autoreply_address_from = 'order@domain.com'
autoreply_address_from_name = 'Orders'
autoreply_address_from_name_en = 'Orders'
autoreply_address_from_name_cs = 'Objednávky'
autoreply_template = 'autoreply-order'
autoreply_template_en = 'autoreply-order-en'
autoreply_template_cs = 'autoreply-order-cs'
autoreply_subject = 'Autoreply sent by form {{ fields.form_alias }} on {{ "now"|date }}'
````
> Do you know that you can use form variables in an email template subject. In Settings > Mail templates create new template and set the Subject field to eg: `My form {{ fields.form_alias }}`.
#### Disable some form fields
You can disable some of defined form fields by passing their names in ````disable_fields```` component property.
Several fields can be added while separated with pipe ````|````.
````
[contactForm]
disable_fields = 'phone|name|confirmation'
````
Or you can disable some of functions:
````
[contactForm]
disable_notifications = true
disable_autoreply = true
````
----
## HOWTO
### Fight SPAM
#### Prohibit sending URLs in a (message) field.
* Use Custom rule
* Add your validation error text
* Use validation rule: `custom_not_regex`
* Use validation: `/(http|https|ftp|ftps)\:\/\/?/`
![Custom regex to prevent sending URLs](https://www.vince.cz/storage/app/media/OctoberCMS/scf-custom-regex-urls.png)
### Add an empty option to dropdown field
You can easily add an empty option with empty ID and some value.
![Dropdown empty field](https://www.vince.cz/storage/app/media/OctoberCMS/scf-settings-dropdown.png)
#### Validate dropdown field
If you want to validate dropdown options, you can use custom validation rule `in` with list of IDs as a validation pattern.
![Dropdown validation](https://www.vince.cz/storage/app/media/OctoberCMS/scf-settings-dropdown-validation.png)
----
> My thanks goes to:
> [OctoberCMS](http://www.octobercms.com) team members and supporters for this great system.
> [Andrew Measham](https://unsplash.com/@andrewmeasham) for his photo.
> [Font Awesome](http://fontawesome.io/icons/) for nice icons.
Created by [Jan Vince](http://www.vince.cz), freelance web designer from Czech Republic.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
<div id="scf-{{ __SELF__ }}">
<div id="scf-message-{{ __SELF__ }}">
{% partial __SELF__ ~ '::scf-message' %}
</div>
<div id="scf-form-{{ __SELF__ }}">
{% partial __SELF__ ~ '::scf-form' %}
</div>
</div>

View File

@ -0,0 +1,61 @@
{% if formSentAlias == __SELF__.alias and formError is empty and settingsGet('form_hide_after_success', 0) %}
{# no errors and set to hide after send #}
{% else %}
{{ form_open(__SELF__.getFormAttributes) }}
{% for field in __SELF__.fields %}
{{ __SELF__.getFieldHtmlCode(field)|raw }}
{% endfor %}
{{ __SELF__.getAntispamFieldHtmlCode({})|raw }}
{{ __SELF__.getDescriptionFieldHtmlCode({})|raw }}
{{ __SELF__.getRedirectFieldHtmlCode({})|raw }}
{% if (settingsGet('google_recaptcha_version') is null or settingsGet('google_recaptcha_version') == 'v2checkbox') and settingsGet('add_google_recaptcha') and settingsGet('google_recaptcha_site_key') %}
<div class="{{__SELF__.getReCaptchaWrapperClass()}}">
<div class="g-recaptcha" data-sitekey="{{ settingsGet('google_recaptcha_site_key') }}"></div>
</div>
{% endif %}
{{ __SELF__.getSubmitButtonHtmlCode({})|raw }}
{{ form_close() }}
{% if settingsGet('add_google_recaptcha') and settingsGet('google_recaptcha_scripts_allow') %}
<script src='https://www.google.com/recaptcha/api.js{{ settingsGet("google_recaptcha_locale_allow") and currentLocale ? ("?hl="~currentLocale) }}' async defer></script>
{% if settingsGet('google_recaptcha_version') == 'v2invisible' %}
<script>
function onSubmit_{{ __SELF__.alias }}(token) {
return new Promise(function(resolve, reject) {
//Your code logic goes here
document.getElementById("{{'scf-form-id-'~__SELF__.alias}}").submit();
resolve();
}); //end promise
}
</script>
{% endif %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,197 @@
{% if formSentAlias == __SELF__.alias and formError is empty and settingsGet('form_hide_after_success', 0) %}
{# no errors and set to hide after send #}
{% else %}
{{ form_open(__SELF__.getFormAttributes) }}
<div class="contact_box">
<div class="contact_box-row">
<h2 class="contact_box-title wow fadeInUp" data-wow-duration=".3s" data-wow-delay=".1s">
Отправьте нам сообщение
</h2>
<span>
<svg width="31" height="25" viewBox="0 0 31 25" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M25.7077 0.833496H5.29102C4.13069 0.833496 3.0179 1.29443 2.19742 2.1149C1.37695 2.93538 0.916016 4.04817 0.916016 5.2085V19.7918C0.916016 20.9522 1.37695 22.0649 2.19742 22.8854C3.0179 23.7059 4.13069 24.1668 5.29102 24.1668H25.7077C26.868 24.1668 27.9808 23.7059 28.8013 22.8854C29.6217 22.0649 30.0827 20.9522 30.0827 19.7918V5.2085C30.0827 4.04817 29.6217 2.93538 28.8013 2.1149C27.9808 1.29443 26.868 0.833496 25.7077 0.833496ZM24.7306 3.75016L15.4994 10.6772L6.2681 3.75016H24.7306ZM25.7077 21.2502H5.29102C4.90424 21.2502 4.53331 21.0965 4.25982 20.823C3.98633 20.5495 3.83268 20.1786 3.83268 19.7918V5.57308L14.6243 13.6668C14.8768 13.8562 15.1838 13.9585 15.4994 13.9585C15.8149 13.9585 16.1219 13.8562 16.3744 13.6668L27.166 5.57308V19.7918C27.166 20.1786 27.0124 20.5495 26.7389 20.823C26.4654 21.0965 26.0945 21.2502 25.7077 21.2502Z"
fill="#171717" fill-opacity="0.5" />
</svg>
</span>
</div>
{% for field in __SELF__.fields %}
{{ __SELF__.getFieldHtmlCode(field)|raw }}
{% endfor %}
{{ __SELF__.getAntispamFieldHtmlCode({})|raw }}
{{ __SELF__.getDescriptionFieldHtmlCode({})|raw }}
{{ __SELF__.getRedirectFieldHtmlCode({})|raw }}
{% if (settingsGet('google_recaptcha_version') is null or settingsGet('google_recaptcha_version') == 'v2checkbox') and settingsGet('add_google_recaptcha') and settingsGet('google_recaptcha_site_key') %}
<div class="{{__SELF__.getReCaptchaWrapperClass()}}">
<div class="g-recaptcha" data-sitekey="{{ settingsGet('google_recaptcha_site_key') }}"></div>
</div>
{% endif %}
<div class="contact_btn wow fadeInUp" data-wow-duration=".3s" data-wow-delay=".27s">
<button type="submit">
Отправить
<span>
<svg width="14" height="12" viewBox="0 0 14 12" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M1.16732 6.83329H11.0507L8.02565 10.4666C7.95561 10.5509 7.90286 10.6481 7.8704 10.7528C7.83794 10.8574 7.82641 10.9675 7.83647 11.0766C7.85678 11.2969 7.9638 11.5002 8.13398 11.6416C8.30416 11.7831 8.52356 11.8511 8.74392 11.8308C8.96428 11.8105 9.16753 11.7035 9.30898 11.5333L13.4756 6.5333C13.5037 6.49353 13.5288 6.45175 13.5507 6.40829C13.5507 6.36663 13.5923 6.34163 13.609 6.29996C13.6468 6.20441 13.6665 6.1027 13.6673 5.99996C13.6665 5.89722 13.6468 5.79551 13.609 5.69996C13.609 5.6583 13.5673 5.6333 13.5507 5.59163C13.5288 5.54818 13.5037 5.5064 13.4756 5.46663L9.30898 0.466628C9.23063 0.372559 9.13251 0.296909 9.02161 0.245058C8.91071 0.193207 8.78974 0.166429 8.66732 0.166628C8.47261 0.166247 8.28391 0.23406 8.13398 0.358294C8.0496 0.428252 7.97985 0.514169 7.92872 0.611125C7.8776 0.708081 7.8461 0.814171 7.83604 0.923318C7.82597 1.03247 7.83754 1.14253 7.87008 1.2472C7.90262 1.35187 7.95548 1.44909 8.02565 1.53329L11.0507 5.16663H1.16732C0.946304 5.16663 0.734342 5.25443 0.578062 5.41071C0.421782 5.56699 0.333984 5.77895 0.333984 5.99996C0.333984 6.22098 0.421782 6.43294 0.578062 6.58922C0.734342 6.7455 0.946304 6.83329 1.16732 6.83329Z"
fill="#292929" />
</svg>
</span>
</button>
</div>
</div>
<div class="contact_info">
<h4 class="contact_info-title wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".1s">
Контактная информация
</h4>
<a href="tel:+993 12 46-87-87" class="contact_info-txt wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".13s">
<span>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M17.4 22.0001C13.3173 21.9948 9.40331 20.3706 6.5164 17.4837C3.62949 14.5968 2.00529 10.6828 2 6.60011C2 5.38012 2.48464 4.21009 3.34731 3.34742C4.20998 2.48476 5.38 2.00011 6.6 2.00011C6.85834 1.99815 7.11625 2.02159 7.37 2.07011C7.61531 2.10641 7.85647 2.1667 8.09 2.25011C8.25425 2.30774 8.40061 2.40725 8.51461 2.53879C8.62861 2.67033 8.7063 2.82934 8.74 3.00011L10.11 9.00011C10.1469 9.16298 10.1425 9.33249 10.0971 9.4932C10.0516 9.6539 9.96671 9.80067 9.85 9.92011C9.72 10.0601 9.71 10.0701 8.48 10.7101C9.46499 12.871 11.1932 14.6063 13.35 15.6001C14 14.3601 14.01 14.3501 14.15 14.2201C14.2694 14.1034 14.4162 14.0185 14.5769 13.9731C14.7376 13.9276 14.9071 13.9232 15.07 13.9601L21.07 15.3301C21.2353 15.3685 21.3881 15.4483 21.5141 15.562C21.64 15.6757 21.735 15.8196 21.79 15.9801C21.8744 16.2175 21.938 16.4617 21.98 16.7101C22.0202 16.9614 22.0403 17.2156 22.04 17.4701C22.0216 18.6849 21.5233 19.8431 20.654 20.6918C19.7847 21.5405 18.6149 22.0108 17.4 22.0001V22.0001ZM6.6 4.00011C5.91125 4.00275 5.25146 4.27752 4.76443 4.76455C4.27741 5.25157 4.00263 5.91136 4 6.60011C4.00265 10.1532 5.41528 13.56 7.92769 16.0724C10.4401 18.5848 13.8469 19.9975 17.4 20.0001C18.0888 19.9975 18.7485 19.7227 19.2356 19.2357C19.7226 18.7487 19.9974 18.0889 20 17.4001V17.0701L15.36 16.0001L15.07 16.5501C14.62 17.4201 14.29 18.0501 13.45 17.7101C11.7929 17.117 10.2887 16.1621 9.04673 14.915C7.80477 13.6678 6.85622 12.1597 6.27 10.5001C5.91 9.72011 6.59 9.36011 7.45 8.91011L8 8.64011L6.93 4.00011H6.6Z"
fill="white" />
</svg>
</span>
+993 12 46-87-87
</a>
<div class="contact_info-txt wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".17s">
<span>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M12 2C9.89206 1.99989 7.86926 2.83176 6.37124 4.31479C4.87323 5.79782 4.02108 7.81216 4 9.92C4 15.4 11.05 21.5 11.35 21.76C11.5311 21.9149 11.7616 22.0001 12 22.0001C12.2384 22.0001 12.4689 21.9149 12.65 21.76C13 21.5 20 15.4 20 9.92C19.9789 7.81216 19.1268 5.79782 17.6288 4.31479C16.1307 2.83176 14.1079 1.99989 12 2ZM12 19.65C10.33 18.06 6 13.65 6 9.92C6 8.3287 6.63214 6.80258 7.75736 5.67736C8.88258 4.55214 10.4087 3.92 12 3.92C13.5913 3.92 15.1174 4.55214 16.2426 5.67736C17.3679 6.80258 18 8.3287 18 9.92C18 13.62 13.67 18.06 12 19.65Z"
fill="white" />
<path
d="M12 6C11.3078 6 10.6311 6.20527 10.0555 6.58986C9.47993 6.97444 9.03133 7.52107 8.76642 8.16061C8.50152 8.80015 8.4322 9.50388 8.56725 10.1828C8.7023 10.8618 9.03564 11.4854 9.52513 11.9749C10.0146 12.4644 10.6383 12.7977 11.3172 12.9327C11.9961 13.0678 12.6999 12.9985 13.3394 12.7336C13.9789 12.4687 14.5256 12.0201 14.9101 11.4445C15.2947 10.8689 15.5 10.1922 15.5 9.5C15.5 8.57174 15.1313 7.6815 14.4749 7.02513C13.8185 6.36875 12.9283 6 12 6V6ZM12 11C11.7033 11 11.4133 10.912 11.1666 10.7472C10.92 10.5824 10.7277 10.3481 10.6142 10.074C10.5007 9.79994 10.4709 9.49834 10.5288 9.20736C10.5867 8.91639 10.7296 8.64912 10.9393 8.43934C11.1491 8.22956 11.4164 8.0867 11.7074 8.02882C11.9983 7.97094 12.2999 8.00065 12.574 8.11418C12.8481 8.22771 13.0824 8.41997 13.2472 8.66665C13.412 8.91332 13.5 9.20333 13.5 9.5C13.5 9.89782 13.342 10.2794 13.0607 10.5607C12.7794 10.842 12.3978 11 12 11Z"
fill="white" />
</svg>
</span>
Atatürk köçesi 80, Aşgabat 744000, Туркменистан
</div>
<div class="contact_info-media">
<a href="#" class="wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".1s">
<svg width="30" height="30" viewBox="0 0 30 30" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M15.0063 8.26172C11.2798 8.26172 8.27393 11.2676 8.27393 14.9941C8.27393 18.7207 11.2798 21.7266 15.0063 21.7266C18.7329 21.7266 21.7388 18.7207 21.7388 14.9941C21.7388 11.2676 18.7329 8.26172 15.0063 8.26172ZM15.0063 19.3711C12.5981 19.3711 10.6294 17.4082 10.6294 14.9941C10.6294 12.5801 12.5923 10.6172 15.0063 10.6172C17.4204 10.6172 19.3833 12.5801 19.3833 14.9941C19.3833 17.4082 17.4146 19.3711 15.0063 19.3711V19.3711ZM23.5845 7.98633C23.5845 8.85937 22.8813 9.55664 22.0142 9.55664C21.1411 9.55664 20.4438 8.85352 20.4438 7.98633C20.4438 7.11914 21.147 6.41602 22.0142 6.41602C22.8813 6.41602 23.5845 7.11914 23.5845 7.98633ZM28.0435 9.58008C27.9438 7.47656 27.4634 5.61328 25.9224 4.07812C24.3872 2.54297 22.5239 2.0625 20.4204 1.95703C18.2524 1.83398 11.7544 1.83398 9.58643 1.95703C7.48877 2.05664 5.62549 2.53711 4.08447 4.07227C2.54346 5.60742 2.06885 7.4707 1.96338 9.57422C1.84033 11.7422 1.84033 18.2402 1.96338 20.4082C2.06299 22.5117 2.54346 24.375 4.08447 25.9102C5.62549 27.4453 7.48291 27.9258 9.58643 28.0312C11.7544 28.1543 18.2524 28.1543 20.4204 28.0312C22.5239 27.9316 24.3872 27.4512 25.9224 25.9102C27.4575 24.375 27.938 22.5117 28.0435 20.4082C28.1665 18.2402 28.1665 11.748 28.0435 9.58008V9.58008ZM25.2427 22.7344C24.7856 23.8828 23.9009 24.7676 22.7466 25.2305C21.0181 25.916 16.9165 25.7578 15.0063 25.7578C13.0962 25.7578 8.98877 25.9102 7.26611 25.2305C6.11768 24.7734 5.23291 23.8887 4.77002 22.7344C4.08447 21.0059 4.24268 16.9043 4.24268 14.9941C4.24268 13.084 4.09033 8.97656 4.77002 7.25391C5.22705 6.10547 6.11182 5.2207 7.26611 4.75781C8.99463 4.07227 13.0962 4.23047 15.0063 4.23047C16.9165 4.23047 21.0239 4.07812 22.7466 4.75781C23.895 5.21484 24.7798 6.09961 25.2427 7.25391C25.9282 8.98242 25.77 13.084 25.77 14.9941C25.77 16.9043 25.9282 21.0117 25.2427 22.7344Z"
fill="white" />
</svg>
</a>
<a href="#" class="wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".13s">
<svg width="31" height="30" viewBox="0 0 31 30" fill="none"
xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_59_2738)">
<path
d="M27.84 8.88957C27.8591 9.15605 27.8591 9.42259 27.8591 9.68908C27.8591 17.8172 21.6726 27.1827 10.3654 27.1827C6.88193 27.1827 3.64592 26.1738 0.923828 24.4226C1.41877 24.4797 1.89461 24.4987 2.40859 24.4987C5.28291 24.4987 7.92889 23.5279 10.0418 21.8718C7.33879 21.8147 5.07355 20.0444 4.29309 17.6078C4.67383 17.6649 5.05451 17.703 5.4543 17.703C6.00631 17.703 6.55838 17.6268 7.0723 17.4936C4.25506 16.9225 2.14205 14.4479 2.14205 11.4594V11.3833C2.96055 11.8401 3.9124 12.1256 4.92121 12.1637C3.26512 11.0596 2.18014 9.17509 2.18014 7.0431C2.18014 5.90099 2.48465 4.85404 3.01768 3.94033C6.04434 7.67128 10.5938 10.1078 15.6953 10.3743C15.6002 9.91748 15.543 9.44164 15.543 8.96574C15.543 5.57738 18.2842 2.81726 21.6915 2.81726C23.4618 2.81726 25.0608 3.55964 26.1839 4.75888C27.5734 4.4924 28.9059 3.97841 30.0862 3.27412C29.6293 4.70181 28.6585 5.90105 27.3831 6.66242C28.6204 6.52923 29.8197 6.18652 30.9237 5.71068C30.0863 6.9289 29.0393 8.01388 27.84 8.88957V8.88957Z"
fill="white" />
</g>
<defs>
<clipPath id="clip0_59_2738">
<rect width="30" height="30" fill="white" transform="translate(0.923828)" />
</clipPath>
</defs>
</svg>
</a>
<a href="#" class="wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".17s">
<svg width="31" height="30" viewBox="0 0 31 30" fill="none"
xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_59_2740)">
<path
d="M30.4551 15C30.4551 6.97266 23.9512 0.46875 15.9238 0.46875C7.89648 0.46875 1.39258 6.97266 1.39258 15C1.39258 22.2527 6.70645 28.2645 13.6533 29.3555V19.2006H9.96191V15H13.6533V11.7984C13.6533 8.15684 15.8213 6.14531 19.1418 6.14531C20.732 6.14531 22.3949 6.42891 22.3949 6.42891V10.0031H20.5621C18.7574 10.0031 18.1943 11.1234 18.1943 12.2725V15H22.2244L21.5799 19.2006H18.1943V29.3555C25.1412 28.2645 30.4551 22.2527 30.4551 15Z"
fill="white" />
</g>
<defs>
<clipPath id="clip0_59_2740">
<rect width="30" height="30" fill="white" transform="translate(0.923828)" />
</clipPath>
</defs>
</svg>
</a>
<a href="#" class="wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".2s">
<svg width="31" height="30" viewBox="0 0 31 30" fill="none"
xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_59_2744)">
<path
d="M29.5513 8.12932C29.2241 6.89755 28.2603 5.92745 27.0365 5.59823C24.8183 5 15.9234 5 15.9234 5C15.9234 5 7.02862 5 4.81034 5.59823C3.58654 5.9275 2.62268 6.89755 2.29555 8.12932C1.70117 10.362 1.70117 15.0202 1.70117 15.0202C1.70117 15.0202 1.70117 19.6784 2.29555 21.9111C2.62268 23.1429 3.58654 24.0726 4.81034 24.4018C7.02862 25 15.9234 25 15.9234 25C15.9234 25 24.8182 25 27.0365 24.4018C28.2603 24.0726 29.2241 23.1429 29.5513 21.9111C30.1457 19.6784 30.1457 15.0202 30.1457 15.0202C30.1457 15.0202 30.1457 10.362 29.5513 8.12932V8.12932ZM13.0143 19.2495V10.7909L20.4486 15.0203L13.0143 19.2495V19.2495Z"
fill="white" />
</g>
<defs>
<clipPath id="clip0_59_2744">
<rect width="30" height="30" fill="white" transform="translate(0.923828)" />
</clipPath>
</defs>
</svg>
</a>
</div>
<div class="wave wow fadeInUp" data-wow-duration=".3s" data-wow-delay=".1s">
<svg width="418" height="334" viewBox="0 0 418 334" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M296.241 83.892C350.241 6.692 462.741 -3.608 512.241 0.891999C588.74 36.2253 746.84 115.192 767.24 148.392C792.74 189.892 793.74 321.392 741.74 447.392C689.74 573.392 591.24 535.892 330.74 552.392C70.2402 568.892 94.7405 518.892 34.2405 439.392C-26.2595 359.892 6.24053 384.392 34.2405 329.392C62.2405 274.392 73.2405 274.392 171.241 231.392C269.241 188.392 228.741 180.392 296.241 83.892Z"
fill="#FFB100" />
</svg>
</div>
</div>
{{ form_close() }}
{% if settingsGet('add_google_recaptcha') and settingsGet('google_recaptcha_scripts_allow') %}
<script src='https://www.google.com/recaptcha/api.js{{ settingsGet("google_recaptcha_locale_allow") and currentLocale ? ("?hl="~currentLocale) }}' async defer></script>
{% if settingsGet('google_recaptcha_version') == 'v2invisible' %}
<script>
function onSubmit_{{ __SELF__.alias }}(token) {
return new Promise(function(resolve, reject) {
//Your code logic goes here
document.getElementById("{{'scf-form-id-'~__SELF__.alias}}").submit();
resolve();
}); //end promise
}
</script>
{% endif %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,28 @@
{% if formSentAlias == __SELF__.alias %}
{% if formSuccess %}
{{ __SELF__.getGaSuccessEventHtmlCode(true)|raw }}
{% flash success %}
<div class="alert alert-{{ type == 'error' ? 'danger' : type }}">
{{ html_entity_decode(message)|nl2br }}
</div>
{% endflash %}
{% elseif formError %}
{% flash error %}
<div class="alert alert-{{ type == 'error' ? 'danger' : type }}">
{{ html_entity_decode(message)|nl2br }}
</div>
{% endflash %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,29 @@
{
"name": "janvince/smallcontactform-plugin",
"description": "Simple but flexible multi language contact form builder with custom fields, validation and passive antispam",
"homepage": "http://www.vince.cz",
"type": "october-plugin",
"keywords": [
"october",
"cms",
"octobercms",
"laravel",
"contact",
"form"
],
"license": "MIT",
"authors": [
{
"name": "Jan Vince"
}
],
"support": {
"issues": "https://github.com/jan-vince/smallcontactform/issues"
},
"require": {
"php": ">=7.0",
"composer/installers": "~1.0",
"google/recaptcha": "^1.2@dev"
},
"minimum-stability": "dev"
}

View File

@ -0,0 +1,158 @@
<?php namespace Janvince\SmallContactform\Controllers;
use BackendMenu;
use Backend\Classes\Controller;
use JanVince\SmallContactForm\Models\Settings;
use JanVince\SmallContactForm\Models\Message;
use Flash;
use App;
use Carbon\Carbon;
use Redirect;
use Backend;
/**
* Messages Back-end Controller
*/
class Messages extends Controller
{
public $requiredPermissions = ['janvince.smallcontactform.access_messages'];
public $implement = [
'Backend.Behaviors.ListController',
'Backend.Behaviors.ImportExportController',
];
public $listConfig = 'config_list.yaml';
public $importExportConfig = 'config_export.yaml';
public function __construct()
{
parent::__construct();
BackendMenu::setContext('JanVince.SmallContactForm', 'smallcontactform', 'messages');
}
/**
* Generate messages statsitics
* @param $part
*/
public function getRecordsStats( $part ){
switch( $part ){
case 'all_count':
return Message::count();
break;
case 'read_count':
return Message::isRead()->count();
break;
case 'new_count':
return Message::isNew()->count();
break;
case 'latest_message_date':
$data = Message::orderBy( 'created_at', 'DESC' )->first();
if ( !empty( $data->created_at ) ) {
Carbon::setLocale( App::getLocale() );
return Carbon::createFromFormat( 'Y-m-d H:i:s', $data->created_at )->diffForHumans();
}
return NULL;
break;
case 'latest_message_name':
$data = Message::orderBy( 'created_at', 'DESC' )->first();
if( !empty( $data->name ) ) {
return $data->name;
}
return NULL;
break;
default:
return NULL;
break;
}
}
/**
* Preview page view
* @param $id
*/
public function preview( $id ){
$message = Message::find( $id );
if ( $message ) {
$this->vars['message'] = $message;
$message->new_message = 0;
$message->save();
} else{
Flash::error( e( trans( 'janvince.smallcontactform::lang.controller.preview.record_not_found') ) );
return Redirect::to( Backend::url( 'janvince/smallcontactform/messages' ) );
}
}
/**
* Index page view
*/
public function index(){
parent::index();
if (!$this->user->hasAccess('janvince.smallcontactform.access_messages')) {
Flash::error( e(trans('janvince.smallcontactform::lang.controllers.index.unauthorized')) );
return Redirect::to( Backend::url('/') );
}
}
/**
* Mark messages as read
* @param $record
*/
public function onMarkRead(){
if (!$this->user->hasAccess('janvince.smallcontactform.access_messages')) {
Flash::error( e(trans('janvince.smallcontactform::lang.controllers.index.unauthorized')) );
return;
}
if ( ($checkedIds = post('checked')) && is_array($checkedIds) && count($checkedIds) ) {
foreach ($checkedIds as $item) {
if (!$record = Message::find($item)) {
continue;
}
$record->new_message = 0;
$record->save();
}
Flash::success( e(trans('janvince.smallcontactform::lang.controller.scoreboard.mark_read_success')) );
return $this->listRefresh();
}
}
}

View File

@ -0,0 +1,72 @@
<div class="scoreboard">
<div data-control="toolbar">
<div class="scoreboard-item control-chart" data-control="chart-pie">
<ul>
<li data-color="#95b753"><?= e(trans('janvince.smallcontactform::lang.controller.scoreboard.new_count')) ?> <span><?= $this->getRecordsStats('new_count'); ?></span></li>
<li data-color="#d1d1d1"><?= e(trans('janvince.smallcontactform::lang.controller.scoreboard.read_count')) ?> <span><?= $this->getRecordsStats('read_count'); ?></span></li>
</ul>
</div>
<div class="scoreboard-item title-value">
<h4><?= e(trans('janvince.smallcontactform::lang.controller.scoreboard.new_count')) ?></h4>
<p><?= $this->getRecordsStats('new_count'); ?></p>
<p class="description"><?= e(trans('janvince.smallcontactform::lang.controller.scoreboard.new_description')) ?></p>
</div>
<div class="scoreboard-item title-value">
<h4><?= e(trans('janvince.smallcontactform::lang.controller.scoreboard.latest_record')) ?></h4>
<p class="oc-icon-user"><?= $this->getRecordsStats('latest_message_name'); ?></p>
<p class="description"><?= $this->getRecordsStats('latest_message_date'); ?></p>
</div>
</div>
</div>
<div data-control="toolbar">
<?php if ($this->user->hasAccess('janvince.smallcontactform.delete_messages')): ?>
<button
class="btn btn-default oc-icon-trash-o"
disabled="disabled"
onclick="$(this).data('request-data', {
checked: $('.control-list').listWidget('getChecked')
})"
data-request="onDelete"
data-request-confirm="<?= e(trans('backend::lang.list.delete_selected_confirm')) ?>"
data-trigger-action="enable"
data-trigger=".control-list input[type=checkbox]"
data-trigger-condition="checked"
data-request-success="$(this).prop('disabled', true)"
data-stripe-load-indicator>
<?= e(trans('backend::lang.list.delete_selected')) ?>
</button>
<?php endif ?>
<button
class="btn btn-default oc-icon-check-square"
disabled="disabled"
onclick="$(this).data('request-data', {
checked: $('.control-list').listWidget('getChecked')
})"
data-request="onMarkRead"
data-request-confirm="<?= e(trans('janvince.smallcontactform::lang.controller.scoreboard.mark_read_confirm')) ?>"
data-trigger-action="enable"
data-trigger=".control-list input[type=checkbox]"
data-trigger-condition="checked"
data-request-success="$(this).prop('disabled', true)"
data-stripe-load-indicator>
<?= e(trans('janvince.smallcontactform::lang.controller.scoreboard.mark_read')) ?>
</button>
<a href="<?= Backend::url('system/settings/update/janvince/smallcontactform/settings'); ?>" class="btn btn-info oc-icon-cogs"><?= e(trans('janvince.smallcontactform::lang.controller.scoreboard.settings_btn')) ?></a>
<?php if ($this->user->hasAccess('janvince.smallcontactform.export_messages')): ?>
<a
href="<?= Backend::url('janvince/smallcontactform/messages/export/') ?>"
class="btn btn-default oc-icon-download">
<?= e(trans('janvince.smallcontactform::lang.controllers.messages.export')) ?>
</a>
<?php endif ?>
</div>

View File

@ -0,0 +1,10 @@
# ===================================
# Import/Export Behavior Config
# ===================================
export:
title: janvince.smallcontactform::lang.controllers.messages.export
modelClass: JanVince\SmallContactForm\Models\MessageExport
list: $/janvince/smallcontactform/models/message/columns_export.yaml
redirect: /janvince/smallcontactform/messages
fileName: scf-export.csv

View File

@ -0,0 +1,10 @@
# ===================================
# Filter Scope Definitions
# ===================================
scopes:
date:
label: janvince.smallcontactform::lang.controller.filter.columns.date
type: daterange
conditions: date >= ':after' AND date <= ':before'

View File

@ -0,0 +1,43 @@
# ===================================
# List Behavior Config
# ===================================
# Model List Column configuration
list: $/janvince/smallcontactform/models/message/columns.yaml
# Model Class name
modelClass: JanVince\SmallContactForm\Models\Message
# List Title
title: "janvince.smallcontactform::lang.controllers.messages.list_title"
# Message to display if the list is empty
noRecordsMessage: backend::lang.list.no_records
recordUrl: 'janvince/smallcontactform/messages/preview/:id'
# Records to display per page
recordsPerPage: 20
# Displays the list column set up button
showSetup: true
# Displays the sorting link on each column
showSorting: true
# Default sorting column
defaultSort:
column: created_at
direction: desc
# Display checkboxes next to each record
showCheckboxes: true
# Toolbar widget configuration
toolbar:
# Partial for toolbar buttons
buttons: list_toolbar
# Search widget configuration
search:
prompt: backend::lang.list.search_prompt

View File

@ -0,0 +1,25 @@
<?php Block::put('breadcrumb') ?>
<ul>
<li><a href="<?= Backend::url('janvince/smallcontactform/messages') ?>"><?= e(trans('janvince.smallcontactform::lang.controllers.messages.list_title')) ?></a></li>
<li><?= e(trans($this->pageTitle)) ?></li>
</ul>
<?php Block::endPut() ?>
<?= Form::open(['class' => 'layout']) ?>
<div class="layout-row">
<?= $this->exportRender() ?>
</div>
<div class="form-buttons">
<button
type="submit"
data-control="popup"
data-handler="onExportLoadForm"
data-keyboard="false"
class="btn btn-primary">
<?= e(trans('janvince.smallcontactform::lang.controllers.messages.export')) ?>
</button>
</div>
<?= Form::close() ?>

View File

@ -0,0 +1,2 @@
<?= $this->listRender() ?>

View File

@ -0,0 +1,71 @@
<?php Block::put('breadcrumb') ?>
<ul>
<li><a href="<?= Backend::url('janvince/smallcontactform/messages') ?>"><?= e(trans('janvince.smallcontactform::lang.controllers.messages.list_title')); ?></a></li>
<li><?= e(trans('janvince.smallcontactform::lang.controllers.messages.preview')); ?></li>
</ul>
<?php Block::endPut() ?>
<?php if (!$this->fatalError): ?>
<div class="preview">
<h3><?php echo(e(trans('janvince.smallcontactform::lang.controllers.messages.preview_title')) ); ?></h3>
<p><strong><?php echo(e(trans('janvince.smallcontactform::lang.controllers.messages.preview_date')) ); ?></strong> <?php echo($message->created_at->format('j.n.Y H:i:s')); ?></p>
<br>
<p><strong><?php echo(e(trans('janvince.smallcontactform::lang.controllers.messages.preview_content_title')) ); ?></strong></p>
<table>
<?php foreach($message->form_data as $key => $field) : ?>
<tr>
<th class="p-r-md" style="vertical-align: top;"><?php echo($key); ?></th>
<td><?php echo( nl2br(e($field)) ) ?></td>
</tr>
<?php endforeach ?>
<?php if ($message->uploads): ?>
<tr>
<th>Uploads</th>
<td>
<?php foreach($message->uploads as $upload) : ?>
<a href="<?php echo( $upload->getPath() ) ?>" target="blank">
<img src="<?php echo( $upload->getThumb(300,300) ) ?>">
</a>
<?php endforeach ?>
</td>
</tr>
<?php endif ?>
<tr>
<th class="p-r-md"><?php echo(e(trans('janvince.smallcontactform::lang.controllers.messages.remote_ip')) ); ?></th>
<td><?php if(!empty($message->remote_ip)) { echo($message->remote_ip); } ?></td>
<tr>
<th class="p-r-md"><?php echo(e(trans('janvince.smallcontactform::lang.components.properties.form_description')) ); ?></th>
<td><?php if(!empty($message->form_description)) { echo($message->form_description); } ?></td>
</table>
<br>
<br>
</div>
<?php else: ?>
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
<?php endif ?>
<p>
<a href="<?= Backend::url('janvince/smallcontactform/messages') ?>" class="btn btn-default oc-icon-chevron-left">
<?= e(trans('backend::lang.form.return_to_list')) ?>
</a>
</p>

View File

@ -0,0 +1,533 @@
<?php
return [
'plugin' => [
'name' => 'Kontaktní formulář',
'description' => 'Jednoduchý kontaktní formulář',
'category' => 'Small plugins',
],
'permissions' => [
'access_messages' => 'Přístup k seznamu zpráv',
'access_settings' => 'Přístup k nastavení',
'delete_messages' => 'Smazat vybrané zprávy',
'export_messages' => 'Exportovat zprávy',
],
'navigation' => [
'main_label' => 'Kontaktní formulář',
'messages' => 'Zprávy',
],
'controller' => [
'contact_form' => [
'name' => 'Kontaktní formulář',
'description' => 'Přidá do stránky kontaktní formulář',
'no_fields' => 'Přidejte prosím nějaká formulářová pole v administraci systému (Nastavení > Kontaktní formulář > Pole)...',
],
'filter' => [
'date' => 'Rozmezí data',
],
'scoreboard' => [
'records_count' => 'Zprávy',
'latest_record' => 'nejnovější od',
'new_count' => 'Nové',
'new_description' => 'Zpráv',
'read_count' => 'Přečtené',
'all_count' => 'Celkem',
'all_description' => 'Zpráv',
'settings_btn' => 'Nastavení formuláře',
'mark_read' => 'Označit jako přečtené',
'mark_read_confirm' => 'Opravdu chcete vybrané zprávy označit jako přečtené?',
'mark_read_success' => 'Zprávy byly označeny jako přečtené.',
],
'preview' => [
'record_not_found' => 'Zpráva nebyla nalezena!',
],
],
'models' => [
'message' => [
'columns' => [
'id' => 'ID',
'datetime' => 'Datum a čas',
'form_data' => 'Data formuláře',
'name' => 'Jméno',
'email' => 'Email',
'message' => 'Zpráva',
'new_message' => 'Stav',
'new' => 'Nová',
'read' => 'Přečtená',
'remote_ip' => 'IP odesílatele',
'created_at' => 'Datum vytvoření',
'updated_at' => 'Datum aktualizace',
'form_notes' => 'Notes',
]
],
],
'controllers' => [
'messages' => [
'list_title' => 'Zprávy',
'preview' => 'Náhled',
'preview_title' => 'Zpráva z kontaktního formuláře',
'preview_date' => 'Ze dne:',
'preview_content_title' => 'Obsah:',
'remote_ip' => 'odesláno z ip',
'form_alias' => 'Alias',
'form_description' => 'Popisek',
'export' => 'Export',
],
'index' => [
'unauthorized' => 'Neoprávněný přístup!',
],
],
'mail' => [
'templates' => [
'autoreply' => 'Zpráva automatické odpovědi z kontaktního formuláře (Anglicky)',
'notification' => 'Notifikace z kontaktního formuláře (Anglicky)',
'autoreply_cs' => 'Zpráva automatické odpovědi z kontaktního formuláře (Česky)',
'notification_cs' => 'Notifikace z kontaktního formuláře (Česky)',
]
],
'reportwidget' => [
'partials' => [
'messages' => [
'label' => 'Kontaktní formulář - Přehled zpráv',
'title' => 'Přehled zpráv',
'messages_all' => 'Vše',
'messages_new' => 'Nové',
'messages_read' => 'Přečtené',
],
'new_message' => [
'label' => 'Kontaktní formulář - Nové zprávy',
'title' => 'Nové zprávy',
'link_text' => 'Klikněte pro zobrazení přehledu zpráv',
],
],
],
'settings' => [
'form' => [
'css_class' => 'CSS třída formuláře',
'use_placeholders' => 'Používat zástupný text (placeholder)',
'use_placeholders_comment' => 'Místo popisků nad formulářovými poli bude použitý zástupný text',
'disable_browser_validation' => 'Zakázat validaci prohlížečem',
'disable_browser_validation_comment' => 'Nepovolit prohlížeči použít vlastní validaci a zobrazovat výstrahy.',
'success_msg' => 'Zpráva po úspěšném odeslání',
'success_msg_placeholder' => 'Formulář byl v pořádku odeslán.',
'error_msg' => 'Chybová zpráva',
'error_msg_placeholder' => 'Při odesílání formuláře došlo k chybě!',
'allow_ajax' => 'Povolit AJAX',
'allow_ajax_comment' => 'Povolí AJAX, ale umožní fungování formuláře i na prohlížečích s vypnutým JavaScriptem',
'allow_confirm_msg' => 'Požadovat potvrzení před odesláním',
'allow_confirm_msg_comment' => 'Zobrazí potvrzovací okno před odesláním formuláře',
'send_confirm_msg' => 'Text potvrzení',
'send_confirm_msg_placeholder' => 'Opravdu chcete odeslat formulář?',
'hide_after_success' => 'Skrýt formulář po úspěšném odeslání',
'hide_after_success_comment' => 'Po odeslání zobrazí pouze zprávu z potvrzením bez formuláře',
'add_assets' => 'Přidat doplňky',
'add_assets_comment' => 'Automaticky vloží potřebné CSS styly a JS skripty (Více informací je v souboru README.md)',
'add_css_assets' => 'Přidat CSS styly',
'add_css_assets_comment' => 'Vloží všechny potřebné styly',
'add_js_assets' => 'Přidat JS skripty',
'add_js_assets_comment' => 'Vloží všechny potřebné skripty',
'form_ga_event_success' => 'Událost po úspěšném odeslání',
'notes' => 'Poznámky',
'notes_comment' => 'Můžete přidat poznámky, které se pak zobrazí v mailových zprávách.',
],
'sections' => [
'ga_events' => 'Události'
],
'ga' => [
'ga_success_event_allow' => 'Zaznamenat událost po úspěšném odeslání formuláře',
'ga_success_event_gtag' => 'Použitá značka na webu',
'ga_success_event_gtag_empty_option' => 'Vyberte použitou značku',
'ga_success_event_gtag_ga' => 'analytics.js (starší)',
'ga_success_event_gtag_gtag' => 'gtag.js',
],
'buttons' => [
'send_btn_text' => 'Text odesílacího tlačítka',
'send_btn_text_placeholder' => 'Odeslat',
'send_btn_css_class' => 'CSS třída odesílacího tlačítka',
'send_btn_css_class_placeholder' => 'btn btn-primary',
'send_btn_wrapper_css' => 'CSS třída kontejneru',
'send_btn_wrapper_css_placeholder' => 'form-group',
],
'redirect' => [
'allow_redirect' => 'Přesměrovat po úspěšném odeslání',
'allow_redirect_comment' => 'Přesměrovat na jinou stránku po úspěšném odeslání formuláře',
'redirect_url' => 'URL stránky pro přesměrování',
'redirect_url_comment' => 'Vložte URL adresu stránky, kam bude přesměrováno (např. /kontakt/diky)',
'redirect_url_placeholder' => '/kontakt/diky',
'redirect_url_external' => 'Externí URL',
'redirect_url_external_comment' => 'Toto je adresa externí stránky (např. http://www.domain.com)',
],
'form_fields' => [
'prompt' => 'Přidat nové pole formuláře',
'name' => 'NÁZEV POLE',
'name_comment' => 'Malými písmeny bez diakritiky (např. jmeno, email, vase_poznamka, ...)',
'type' => 'Typ pole',
'label' => 'Popisek (label)',
'label_placeholder' => 'Pole formuláře',
'field_styling' => 'Vlastní CSS třídy',
'field_styling_comment' => 'Můžete přidat vlastní styly',
'autofocus' => 'Automaticky zvýraznit (autofocus)',
'autofocus_comment' => 'Po zobrazení nastavit na poli kurzor',
'wrapper_css' => 'CSS třída kontejneru',
'wrapper_css_placeholder' => 'form-group',
'field_css' => 'CSS třida pole',
'field_css_placeholder' => 'form-control',
'label_css' => 'CSS třída popisku (label)',
'label_css_placeholder' => '',
'field_validation' => 'Validační pravidla pole',
'field_validation_comment' => 'Povolí nastavení vlastních validačních pravidel',
'validation' => 'Pravidlo',
'validation_prompt' => 'Přidat pravidlo',
'validation_type' => 'Typ',
'validation_error' => 'Chybová zpráva',
'validation_error_placeholder' => 'Prosím vložte správná data.',
'validation_error_comment' => 'Chybová hláška, která se zobrazí u pole',
'validation_custom_type' => 'Název validačního pravidla',
'validation_custom_type_comment' => 'Vložte název pravidla třídy Validator (např. regex, boolean, ...).<br>Přehled <a href="https://octobercms.com/docs/services/validation#available-validation-rules" target="_blank">validačních pravidel</a>.',
'validation_custom_type_placeholder' => 'regex',
'validation_custom_pattern' => 'Podmínka validačního pravidla',
'validation_custom_pattern_comment' => 'Nechte prázdné nebo doplňte podmínku pravidla (toto je pravá část zápisu validačního pravidla za dvojtečkou - např. [abc] pro pravidlo regex).',
'validation_custom_pattern_placeholder' => "/^[0-9]+$/",
'custom' => 'Vlastní pole',
'custom_description' => 'Vlastní pole s validačními pravidly',
'add_values_prompt' => 'Přidat hodnoty',
'field_value_id' => 'ID hodnoty',
'field_value_content' => 'Obsah',
'hit_type' => 'Hit type',
'event_category' => 'Kategorie události (event category)',
'event_action' => 'Akce události (event action)',
'event_label' => 'Štítek události (event label)',
'custom_code' => 'Vlastní kód',
'custom_code_comment' => 'Vložený kód přepíše automaticky generovaný kód políčka formuláře. Používejte opatrně!',
'custom_code_twig' => 'Povolit Twig',
'custom_code_twig_comment' => 'Můžete povolit parset syntaxe jazyka Twig.',
'custom_content' => 'Vlastní obsah',
'custom_content_comment' => 'Obsah bude přidaný k políčku formuláře.',
],
'form_field_types' => [
'text' => 'Text',
'email' => 'Email',
'textarea' => 'Textarea',
'checkbox' => 'Checkbox',
'dropdown' => 'Výběr (dropdown)',
'file' => 'Soubor',
'custom_code' => 'Vlastní kód',
'custom_content' => 'Vlastní obsah',
],
'form_field_validation' => [
'select' => '--- Vyberte pravidlo ---',
'required' => 'Vyžadováno',
'email' => 'Email',
'numeric' => 'Číslo',
'custom' => 'Vlastní pravidlo',
],
'email' => [
'address_from' => 'Adresa OD',
'address_from_placeholder' => 'john.doe@domain.com',
'address_from_name' => 'Jméno odesílatele',
'address_from_name_placeholder' => 'John Doe',
'address_replyto' => 'Adresa Odpovědět na',
'address_replyto_comment' => 'Odpověď na mail půjde na tuto adresu (REPLY-TO).',
'subject' => 'Předmět emailu',
'subject_comment' => 'Nastavte pouze pokud chcete přepsat předmět definovaný v šabloně (Nastavení > E-mailové šablony).',
'template' => 'Šablona emailu',
'template_comment' => 'Kód emailové šablony vytvořené v Nastavení > E-mailové šablony. Nechte prázdné pro výchozí šablonu: janvince.smallcontactform::mail.autoreply.',
'allow_email_queue' => 'Řadit do fronty',
'allow_email_queue_comment' => 'Přidat emaily do fronty místo okamžitého odeslání. Musíte ale nejdříve správně nakonfigurovat frontu systému OctoberCMS!',
'allow_notifications' => 'Povolit odesílání upozornění',
'allow_notifications_comment' => 'Odesílat upozornění, pokud někdo odešle formulář.',
'notification_address_to' => 'Upozornění posílat na adresu:',
'notification_address_to_comment' => 'Jedna emailová adresa nebo seznam adres oddělených čárkami',
'notification_address_to_placeholder' => 'notifications@domain.com',
'notification_address_from_form' => 'Nastavit adresu Od na email z formuláře (NEMUSÍ PODPOROVAT váš emailový systém!)',
'notification_address_from_form_comment' => 'Nastaví u odesílaného upozornění adresu Od (From) na tu, která byla zadána ve formuláři (sloupec email musí mít nastavenou vazbu).',
'allow_autoreply' => 'Povolit automatickou odpověď',
'allow_autoreply_comment' => 'Poslat automatickou odpověď odesílateli formuláře',
'autoreply_name_field' => 'Pole formuláře, které obsahuje JMÉNO odesílatele',
'autoreply_name_field_empty_option' => '-- Vyberte --',
'autoreply_name_field_comment' => 'Pole typu Text.',
'autoreply_email_field' => 'Pole formuláře, které obsahuje ADRESU odesílatele',
'autoreply_email_field_empty_option' => '-- Vyberte --',
'autoreply_email_field_comment' => 'Pole typu Email.',
'autoreply_message_field' => 'Pole formuláře, které obsahuje ZPRÁVU',
'autoreply_message_field_empty_option' => '-- vyberte --',
'autoreply_message_field_comment' => 'Pole typu Textarea nebo Text.',
'notification_template' => 'Šablona notifikačního emailu',
'notification_template_comment' => 'Kód emailové šablony vytvořené v Nastavení > E-mailové šablony. Nechte prázdné pro výchozí šablonu: janvince.smallcontactform::mail.notification.',
],
'antispam' => [
'add_antispam' => 'Přidat pasivní ochranu proti spamu',
'add_antispam_comment' => 'Přidá jednoduchou ale efektivní pasivní ochranu proti robotům (více informací v souboru README.md)',
'antispam_delay' => 'Zpoždění formuláře (s)',
'antispam_delay_comment' => 'Test na příliš rychlé odeslání formuláře (většinou roboty)',
'antispam_delay_placeholder' => '3',
'antispam_label' => 'Popisek (label) antispamového pole',
'antispam_label_comment' => 'Popisek bude viditelný pouze na prohlížečích bez podpory JavaScriptu',
'antispam_label_placeholder' => 'Prosím vymažte toto pole',
'antispam_error_msg' => 'Chybová zprávy',
'antispam_error_msg_comment' => 'Zpráva, která se zobrazí, pokud se aktivuje pasivní antispam',
'antispam_error_msg_placeholder' => 'Prosím vymažte obsah tohoto pole!',
'antispam_delay_error_msg' => 'Chybová zprávy při rychlém odeslání',
'antispam_delay_error_msg_comment' => 'Zpráva, která se zobrazí při příliš rychlém odeslání formuláře',
'antispam_delay_error_msg_placeholder' => 'Příliš rychlé odeslání formuláře! Prosím zkuste to za pár vteřin znovu!',
'add_google_recaptcha' => 'Přidat Google reCaptcha',
'add_google_recaptcha_comment' => 'Přidá reCaptcha do kontaktního formuláře (více informací v souboru README.md). <br>API klíče můžete získat na <a href="https://www.google.com/recaptcha/admin#list" target="_blank">stránce Google reCaptcha</a>.',
'google_recaptcha_version' => 'Verze Google reCaptcha',
'google_recaptcha_version_comment' => 'Zvolte verzi reCaptcha widgetu.<br>Více informací naleznete na <a href="https://developers.google.com/recaptcha/docs/versions" target="_blank">webu Google reCaptcha</a>.',
'google_recaptcha_versions' => [
'v2checkbox' => 'reCaptcha V2 zaškrtávací pole',
'v2invisible' => 'reCaptcha V2 neviditelná',
],
'google_recaptcha_site_key' => 'Site key',
'google_recaptcha_site_key_comment' => 'Vložte svůj "site key"',
'google_recaptcha_secret_key' => 'Secret key',
'google_recaptcha_secret_key_comment' => 'Vložte svůj "secret key"',
'google_recaptcha_wrapper_css' => 'CSS třída kontejneru reCaptcha boxu',
'google_recaptcha_wrapper_css_comment' => 'CSS třída kontejneru, ve kterém je vložený box reCaptcha',
'google_recaptcha_wrapper_css_placeholder' => 'form-group',
'google_recaptcha_error_msg' => 'Chybová zpráva',
'google_recaptcha_error_msg_comment' => 'Zpráva, která se zobrazí, pokud dojde chybě při ověření reCAPTCHA.',
'google_recaptcha_error_msg_placeholder' => 'Chyba při ověření pomocí Google reCAPTCHA!',
'google_recaptcha_scripts_allow' => 'Automaticky přidat Google reCAPTCHA sckript',
'google_recaptcha_scripts_allow_comment' => 'Vloží odkaz na JavaScriptový soubor potřebný pro fungování reCAPTCHA.',
'google_recaptcha_locale_allow' => 'Povolit detekci jazyka',
'google_recaptcha_locale_allow_comment' => 'Přidá k reCAPTCHA skriptu kód jazyka stránky, takže ověřovací box bude mluvit jazykem návštěvníka webu.',
'add_ip_protection' => 'Testovat IP adresu odesílatele',
'add_ip_protection_comment' => 'Nepovolí příliš mnoho odeslání formuláře z jedné IP adresy',
'add_ip_protection_count' => 'Maximální počet odeslání během jednoho dne',
'add_ip_protection_count_comment' => 'Počet povolených odeslání formuláře z jedné IP adresy během jednoho dne',
'add_ip_protection_count_placeholder' => '3',
'add_ip_protection_error_get_ip' => 'Nepodařilo se určit vaši IP adresu!',
'add_ip_protection_error_too_many_submits' => 'Chybová zpráva při překročení počtu odeslání',
'add_ip_protection_error_too_many_submits_comment' => 'Zpráva, kterou obdrží uživatel při překročení limitu počtu odeslání formuláře',
'add_ip_protection_error_too_many_submits_placeholder' => 'Byl překročen limit odeslání formuláře během jednoho dne!',
'disabled_extensions' => 'Zakázaná rozšíření',
'disabled_extensions_comment' => 'Nastavení ze záložky Soukromí zkusobila vypnutí těchto rozšíření',
],
'mapping' => [
'hint' => [
'title' => 'Proč vazby na sloupce?',
'content' => '
<p>Můžete vytvořit libovolný formulář s vlastními poli a jejich typy.</p>
<p>Systém zapíše do databáze všechna odeslaná data formuláře, ale pro Přehled zpráv jsou zvlášť ukládána pole Jméno, Email a Zpráva.</p>
<p>Proto je nutné identifikovat pro tyto sloupce odpovídající pole ve vašem formuláři.</p>
<p><em>Vytvořené vazby jsou použité i při odesílání automatických odpovědí, kde je nutné vazba alespoň na pole Email.</em></p>
',
],
'warning' => [
'title' => 'Nevidíte vaše formulářová pole?',
'content' => '
<p>Pokud zde nevidíte svá formulářová pole, klikněte dole na tlačítko Uložit a pak obnovte stránku (F5 nebo Ctr+R / Cmd+R).</p>
',
],
],
'privacy' => [
'disable_messages_saving' => 'Zakázat ukládání zpráv',
'disable_messages_saving_comment' => 'Pokud je zaškrtnuto, odeslané zprávy se nebudou ukládat do databáze.<br><strong>Tato volba zároveň zakáže použití IP ochrany!</strong>',
'disable_messages_saving_comment_section' => '<div class="callout fade in callout-danger no-subheader"><div class="header"><i class="icon-warning"></i><h3>Ujistěte se, že máte povoleny notifikační emaily, jinak nebudete mít žádná data z odeslaných formulářů!</h3></div></div>',
],
'tabs' => [
'form' => 'Formulář',
'buttons' => 'Odesílací tlačítko',
'form_fields' => 'Pole formuláře',
'mapping' => 'Vazby sloupců',
'email' => 'Email',
'antispam' => 'Antispam',
'privacy' => 'Soukromí'
],
],
'components' => [
'groups' => [
'hacks' => 'Hacks',
'override_form' => 'Přepsat nastavení formuláře',
'override_notifications' => 'Přepsat nastavení notifikací',
'override_autoreply' => 'Přepsat nastavení automatických odpovědí',
'override' => 'Přepsat nastavení',
'override_redirect' => 'Přepsat nastavení přesměrování',
'override_ga' => 'Přepsat nastavení Google Analytics',
'override_notes' => 'Přepsat poznámky',
],
'properties' => [
'disable_notifications' => 'Zakázat odesílání notifikačních emailů',
'disable_notifications_comment' => 'Zakáže odeslání notifikáčních emailů (bez ohledu na systémová nastavení formuláře)',
'form_description' => 'Popisek formuláře',
'form_description_comment' => 'Volitelně můžete přidat popisek formuláře, který se uloží společně s odeslanými daty do seznamu zpráv. Můžete použít i {{ :slug }}.',
'disable_fields' => 'Zakázat pole',
'disable_fields_comment' => 'Vložte názvy polí oddělené trubkou (např. name|message|phone)',
'send_btn_label' => 'Popisek odesílacího tlačítka',
'send_btn_label_comment' => 'Přepíše výchozí text odesílacího tlačítka',
'form_success_msg' => 'Zpráva po úspěšném odeslání',
'form_success_msg_comment' => 'Přepíše výchozí zprávu zobrazenou po úspěšném odeslání formuláře',
'form_error_msg' => 'Zpráva po chybě při odeslání',
'form_error_msg_comment' => 'Přepíše výchozí zprávu zobrazenou po neúspěšném odeslání formuláře',
'notification_address_to' => 'Adresa KOMU',
'notification_address_to_comment' => 'Přepíše adresu KOMU v notifikačním emailu',
'notification_address_from' => 'Adresa OD',
'notification_address_from_comment' => 'Přepíše adresu OD v notifikačním emailu',
'notification_address_from_name' => 'Jméno pro adresu OD',
'notification_address_from_name_comment' => 'Přepíše jméno zobrazené spolu s emailem OD',
'notification_template' => 'Šablona notifikace',
'notification_template_comment' => 'Přepíše šablonu notifikačního emailu',
'notification_subject' => 'Předmět notifikace',
'notification_template_comment' => 'Přepíše předmět emailu',
'disable_autoreply' => 'Zakázat notifikace',
'disable_autoreply_comment' => 'Zakáže odesílání notifikací',
'autoreply_address_from' => 'Adresa OD',
'autoreply_address_from_comment' => 'Přepíše adresu od v automatické odpovědi po odeslání formuláře',
'autoreply_address_from_name' => 'Jméno pro adresu OD',
'autoreply_address_from_name_comment' => 'Přepíše jméno zobrazené spolu s emailem OD',
'autoreply_address_replyto' => 'Adresa ODPOVĚDĚT NA',
'autoreply_address_replyto_comment' => 'Přepíše adresu REPLY TO v automatické odpovědi po odeslání formuláře.',
'autoreply_template' => 'Šablona automatické odpovědi',
'autoreply_template_comment' => 'Přepíše šablonu emailu automatické odpovědi',
'autoreply_subject' => 'Předmět automatické odpovědi',
'autoreply_template_comment' => 'Přepíše předmět emailu',
]
],
];

View File

@ -0,0 +1,491 @@
<?php
return [
'plugin' => [
'name' => 'Kontaktformular',
'description' => 'Kontaktformular',
'category' => 'Kontaktformular',
],
'permissions' => [
'access_messages' => 'Auf Nachrichtenliste zugreifen',
'access_settings' => 'Backendeinstellungen bearbeiten',
'delete_messages' => 'gespeicherte Nachrichten löschen',
'export_messages' => 'gespeicherte Nachrichten exportieren',
],
'navigation' => [
'main_label' => 'Kontaktformular',
'messages' => 'Nachrichten',
],
'controller' => [
'contact_form' => [
'name' => 'Kontaktformular',
'description' => 'Kontaktformular in die Seite einfügen',
'no_fields' => 'Bitte fügen Sie zuerst einige Formularfelder in der Backend-Administration hinzu (in Einstellungen > Kontaktformular > Felder)...',
],
'filter' => [
'date' => 'Datumsbereich',
],
'scoreboard' => [
'records_count' => 'Nachrichten',
'latest_record' => 'Letzte von',
'new_count' => 'Neu',
'new_description' => 'Nachrichten',
'read_count' => 'Gelesen',
'all_count' => 'Insgesamt',
'all_description' => 'Nachrichten',
'settings_btn' => 'Formular Einstellungen',
'mark_read' => 'Als Gelesen markieren',
'mark_read_confirm' => 'Möchten Sie wirklich die ausgewählten Nachrichten als gelesen markeiren?',
'mark_read_success' => 'Erfolgreich als gelesen markiert.',
],
'preview' => [
'record_not_found' => 'Nachricht nicht gefunden!',
],
],
'models' => [
'message' => [
'columns' => [
'id' => 'ID',
'datetime' => 'Datum und Zeit',
'form_data' => 'Daten',
'name' => 'Name',
'email' => 'Email',
'message' => 'Nachricht',
'new_message' => 'Status',
'new' => 'Neu',
'read' => 'Gelesen',
'remote_ip' => 'IP des Absenders',
'form_alias' => 'Alias',
'form_description' => 'Beschreibung',
'created_at' => 'Erstellt am',
'updated_at' => 'Geupdated am',
]
],
],
'controllers' => [
'messages' => [
'list_title' => 'Nachrichten',
'preview' => 'Vorschau',
'preview_title' => 'Nachricht',
'preview_date' => 'Datum:',
'preview_content_title' => 'Inhalt:',
'remote_ip' => 'Von IP gesendet:',
'export' => 'Exportieren',
],
'index' => [
'unauthorized' => 'Unerlaubter Zugriff',
],
],
'mail' => [
'templates' => [
'autoreply' => 'Form autoreply message (English)',
'autoreply_cs' => 'Form autoreply message (Czech)',
'notification' => 'Form notification message (English)',
'notification_cs' => 'Form notification message (Czech)',
]
],
'reportwidget' => [
'partials' => [
'messages' => [
'label' => 'Kontaktformular - Nachrichtenstatistik',
'title' => 'Nachrichtenstatistik',
'messages_all' => 'Alle',
'messages_new' => 'Neu',
'messages_read' => 'Gelesen',
],
'new_message' => [
'label' => 'Kontaktformular - Neue Nachrichten',
'title' => 'Neue Nachrichten',
'link_text' => 'Hier klicken, um die Liste aller Nachrichten anzuzeigen',
],
],
],
'settings' => [
'form' => [
'css_class' => 'Formular CSS Klasse',
'use_placeholders' => 'Platzhalter benutzen',
'use_placeholders_comment' => 'Platzhalter werden anstelle von Labels verwendet',
'disable_browser_validation' => 'Browservalidierung deaktivieren',
'disable_browser_validation_comment' => 'Integrierte Validierung und Popups im Browser nicht zulassen.',
'success_msg' => 'Form success message',
'success_msg_placeholder' => 'Wir haben Ihre Nachricht erhalten.',
'error_msg' => 'Form error message',
'error_msg_placeholder' => 'Es gab einen Fehler beim Senden Ihrer Daten!',
'allow_ajax' => 'Enable AJAX',
'allow_ajax_comment' => 'AJAX mit Fallback für Browser ohne JavaScript verwenden',
'allow_confirm_msg' => 'Vor dem Absenden des Formulars um Bestätigung bitten',
'allow_confirm_msg_comment' => 'Bestätigungsdialog vor dem Senden hinzufügen',
'send_confirm_msg' => 'Bestätigungs-Text',
'send_confirm_msg_placeholder' => 'Sind Sie sicher?',
'hide_after_success' => 'Formular nach erfolgreichem Senden ausblenden',
'hide_after_success_comment' => 'Nur Erfolgsmeldung ohne Formular anzeigen',
'add_assets' => 'Assets hinzufügen',
'add_assets_comment' => 'Automatisches Hinzufügen notwendiger CSS- und JS-Assets (mehr über Assets in der Datei README.md)',
'add_css_assets' => 'CSS Assets hinzufügen',
'add_css_assets_comment' => 'Alle benötigten CSS Dateien werden hinzugefügt',
'add_js_assets' => 'JavaScript Assets hinzufügen',
'add_js_assets_comment' => 'Alle benötigten JavaScript Dateien werden hinzugefügt',
],
'buttons' => [
'send_btn_text' => 'Text senden Button',
'send_btn_text_placeholder' => 'Absenden',
'send_btn_css_class' => 'CSS Klasse senden Button',
'send_btn_css_class_placeholder' => 'btn btn-primary',
'send_btn_wrapper_css' => 'CSS Klasse des senden Button wrappers',
'send_btn_wrapper_css_placeholder' => 'form-group',
],
'redirect' => [
'allow_redirect' => 'Nach dem Einreichen umleiten',
'allow_redirect_comment' => 'Nach erfolgreicher Übermittlung auf eine andere Seite umleiten',
'redirect_url' => 'URL der Seite, auf die umgeleitet werden soll',
'redirect_url_comment' => 'Geben Sie die URL Ihrer Seite ein (bspw. /kontact/danke)',
'redirect_url_placeholder' => '/kontakt/danke',
'redirect_url_external' => 'Externe URL',
'redirect_url_external_comment' => 'Dies ist ein externer URL-Pfad (bspw. http://www.domain.com',
],
'form_fields' => [
'prompt' => 'Neues Formularfeld hinzufügen',
'name' => 'FELDNAME',
'name_comment' => 'Kleinbuchstaben ohne Sonderzeichen (bspw. name, email, adresse, ...)',
'type' => 'Feldtyp',
'label' => 'Label',
'label_placeholder' => 'Vollständiger Name',
'field_styling' => 'Eigene CSS Klasse',
'field_styling_comment' => 'Ändern der Standard-Bootstrap-Stile',
'autofocus' => 'Autofokus-Feld',
'autofocus_comment' => 'Autofokus für dieses Formularfeld',
'wrapper_css' => 'Wrapper CSS-Klasse',
'wrapper_css_placeholder' => 'form-group',
'field_css' => 'Feld CSS-Klasse',
'field_css_placeholder' => 'form-control',
'label_css' => 'Label CSS-Klasse',
'label_css_placeholder' => '',
'field_validation' => 'Feldüberprüfung',
'field_validation_comment' => 'Feldüberprüfungsregeln hinzufügen',
'validation' => 'Validierung',
'validation_prompt' => 'Validierung hinzufügen',
'validation_type' => 'Validierungsregel',
'validation_error' => 'Validierungs-Fehlermeldung',
'validation_error_placeholder' => 'Bitte gültige Daten eingeben.',
'validation_error_comment' => 'Fehlermeldung, die zu verwenden ist, wenn die Validierung fehlschlägt',
'validation_custom_type' => 'Name der Validierungsregel',
'validation_custom_type_comment' => 'Validator-Regelnamen eingeben (bspw. regex, boolean, ...).<br>See <a href="https://octobercms.com/docs/services/validation#available-validation-rules" target="_blank">validation rules</a>.',
'validation_custom_type_placeholder' => 'regex',
'validation_custom_pattern' => 'Muster für Validierungsregeln',
'validation_custom_pattern_comment' => 'Left empty or enter custom rule pattern (this is a right part of Validator rule after colon - eg. [abc] for regex).',
'validation_custom_pattern_placeholder' => "/^[0-9]+$/",
'custom' => 'Benutzerdefiniertes Feld',
'custom_description' => 'Benutzerdefiniertes Feld mit Validierungsoption',
'add_values_prompt' => 'Werte hinzufügen',
'field_value_id' => 'Feld ID',
'field_value_content' => 'Feld Inhalt',
],
'form_field_types' => [
'text' => 'Text',
'email' => 'Email',
'textarea' => 'Textbereich',
'checkbox' => 'Checkbox',
'dropdown' => 'Dropdown-Menü',
'file' => 'File',
'custom_code' => 'Custom code',
'custom_content' => 'Custom content',
],
'form_field_validation' => [
'select' => '--- Validierung auswählen ---',
'required' => 'erforderlich',
'email' => 'Email',
'numeric' => 'Numerisch',
'custom' => 'Benutzerdefinierte Regel',
],
'email' => [
'address_from' => 'Absenderaddresse',
'address_from_placeholder' => 'max.mustermann@domain.de',
'address_from_name' => 'Absendername',
'address_from_name_placeholder' => 'Max Mustermann',
'subject' => 'Email subject',
'subject_comment' => 'Nur einstellen, wenn Sie andere als die unter Einstellungen > Mail-Vorlagen definierten Einstellungen wünschen.',
'template' => 'Email template',
'template_comment' => 'Code der E-Mail-Vorlage, die unter Einstellungen > E-Mail-Vorlagen erstellt wurde. Bei Standardvorlage leer lassen: janvince.smallcontactform::mail.autoreply.',
'allow_email_queue' => 'E-Mail in Warteschlange setzen',
'allow_email_queue_comment' => 'Fügen Sie E-Mails in die Warteschlange ein, anstatt sie sofort zu senden. Sie müssen zuerst Ihre OctoberCMS-Warteschlange konfigurieren!',
'allow_notifications' => 'Benachrichtigungen zulassen',
'allow_notifications_comment' => 'Benachrichtigung senden, nachdem das Formular gesendet wurde',
'notification_address_to' => 'Benachrichtigung an E-Mail senden',
'notification_address_to_comment' => 'Eine E-Mail-Adresse oder eine durch Komma getrennte Liste von Adressen',
'notification_address_to_placeholder' => 'kontakt@domain.de',
'notification_address_from_form' => 'Benachrichtigung von der Adresse des Absenders erzwingen (NICHT von allen E-Mail-Systemen UNTERSTÜTZT!)',
'notification_address_from_form_comment' => 'Benachrichtigung von Adresse auf eine im Kontaktformular eingegebene E-Mail setzen (das Feld muss in der Spaltenzuordnung gesetzt werden).',
'allow_autoreply' => 'Autoreply zulassen',
'allow_autoreply_comment' => 'Senden Sie eine Kopie des Formularinhalts an den Autor',
'autoreply_name_field' => 'NAME form field',
'autoreply_name_field_empty_option' => '-- Select --',
'autoreply_name_field_comment' => 'Must be type of Text.<br><em>Save and refresh this page if you can\'t see your fields.</em>',
'autoreply_email_field' => 'EMAIL address form field',
'autoreply_email_field_empty_option' => '-- Select --',
'autoreply_email_field_comment' => 'Must be type of Email.<br><em>Save and refresh this page if you can\'t see your fields.</em>',
'autoreply_message_field' => 'MESSAGE form field',
'autoreply_message_field_empty_option' => '-- Select --',
'autoreply_message_field_comment' => 'Must be type of Textarea or Text.<br><em>Save and refresh this page if you can\'t see your fields.</em>',
'notification_template' => 'Notification email template',
'notification_template_comment' => 'Code of email template created in Settings > Email templates. Left empty for default template: janvince.smallcontactform::mail.autoreply.',
],
'antispam' => [
'add_antispam' => 'Add passive antispam protection',
'add_antispam_comment' => 'Add simple but effective passive antispam control (more info in README.md file)',
'antispam_delay' => 'Antispam delay (s)',
'antispam_delay_comment' => 'Delay protection for too fast form sending (usually by robots)',
'antispam_delay_placeholder' => '3',
'antispam_label' => 'Antispam field label',
'antispam_label_comment' => 'Label will be visible for non JavaScript enabled browsers',
'antispam_label_placeholder' => 'Please clear this field',
'antispam_error_msg' => 'Error message',
'antispam_error_msg_comment' => 'Message to show to user when antispam protection is triggered',
'antispam_error_msg_placeholder' => 'Please empty this field!',
'antispam_delay_error_msg' => 'Delay error message',
'antispam_delay_error_msg_comment' => 'Message to show to user when form was sent too fast',
'antispam_delay_error_msg_placeholder' => 'Form sent too fast! Please wait few seconds and try again!',
'add_google_recaptcha' => 'Add Google reCaptcha',
'add_google_recaptcha_comment' => 'Add reCaptcha to Contact Form (more info in README.md file).<br>You can get API keys on <a href="https://www.google.com/recaptcha/admin#list" target="_blank">Google reCaptcha site</a>.',
'google_recaptcha_version' => 'Google reCaptcha version',
'google_recaptcha_version_comment' => 'Choose a version of reCaptcha widget.<br>More info on <a href="https://developers.google.com/recaptcha/docs/versions" target="_blank">Google reCaptcha site</a>.',
'google_recaptcha_versions' => [
'v2checkbox' => 'reCaptcha V2 checkbox',
'v2invisible' => 'reCaptcha V2 invisible',
],
'google_recaptcha_site_key' => 'Site key',
'google_recaptcha_site_key_comment' => 'Put your site key',
'google_recaptcha_secret_key' => 'Secret key',
'google_recaptcha_secret_key_comment' => 'Put your secret key',
'google_recaptcha_wrapper_css' => 'reCaptcha box wrapper CSS class',
'google_recaptcha_wrapper_css_comment' => 'CSS class of wrapper box around reCaptcha box',
'google_recaptcha_wrapper_css_placeholder' => 'form-group',
'google_recaptcha_error_msg' => 'Error message',
'google_recaptcha_error_msg_comment' => 'Message to show to user when reCAPTCHA is not validated.',
'google_recaptcha_error_msg_placeholder' => 'Google reCAPTCHA validation error!',
'google_recaptcha_scripts_allow' => 'Automatically add necessary JS scripts',
'google_recaptcha_scripts_allow_comment' => 'This will add link to JS scripts to your site.',
'google_recaptcha_locale_allow' => 'Allow locale detection',
'google_recaptcha_locale_allow_comment' => 'This will add curent web page locale to reCAPTCHA script, so it will translated.',
'add_ip_protection' => 'Check sender\'s IP',
'add_ip_protection_comment' => 'Do not allow too many form submits from one IP address',
'add_ip_protection_count' => 'Maximum form submits during a day',
'add_ip_protection_count_comment' => 'Number of allowed submits from one IP address during a single day',
'add_ip_protection_count_placeholder' => '3',
'add_ip_protection_error_get_ip' => 'We wasn\'t able to determine your IP address!',
'add_ip_protection_error_too_many_submits' => 'Too many submits error message',
'add_ip_protection_error_too_many_submits_comment' => 'Error message to show to the user',
'add_ip_protection_error_too_many_submits_placeholder' => 'Too many form submits from one address today!',
'disabled_extensions' => 'Disabled extensions',
'disabled_extensions_comment' => 'Settings set on Privacy tab disabled these extensions',
],
'mapping' => [
'hint' => [
'title' => 'Why fields mapping?',
'content' => '
<p>You can build a custom form with own field names and types.</p>
<p>System writes all form data in database, but for quick overview Name, Email and Message columns are visible separately in Messages list.</p>
<p>So you have to help system to identify these columns by mapping to your form fields.</p>
<p><em>These mappings are also used for autoreply emails where at least Email field mapping is important.</em></p>
',
],
'warning' => [
'title' => 'Can\'t select your form fields?',
'content' => '
<p>If you don\'t see your form fields, click on button Save at the bottom of this page and then reload page (F5 or Ctr+R / Cmd+R).</p>
',
],
],
'privacy' => [
'disable_messages_saving' => 'Disable messages saving',
'disable_messages_saving_comment' => 'When checked, no data will saved in Messages list.<br><strong>This will also disable IP protection!</strong>',
'disable_messages_saving_comment_section' => '<div class="callout fade in callout-danger no-subheader"><div class="header"><i class="icon-warning"></i><h3>Be sure to allow notification emails or you will have no data from sent forms!</h3></div></div>',
],
'tabs' => [
'form' => 'Form',
'buttons' => 'Send button',
'form_fields' => 'Fields',
'mapping' => 'Columns mapping',
'email' => 'Email',
'antispam' => 'Antispam',
'privacy' => 'Privacy'
],
],
'components' => [
'groups' => [
'hacks' => 'Hacks',
'override_form' => 'Override form settings',
'override_notifications' => 'Override notification settings',
'override_autoreply' => 'Override autoreply settings',
'override' => 'Override form settings',
],
'properties' => [
'form_description' => 'Form description',
'form_description_comment' => 'You can add optional form description, that will be saved with other sent data in the messages list. You can also use {{ :slug }} here.',
'disable_fields' => 'Disable fields',
'disable_fields_comment' => 'This will disable listed fields. Add field names separated by pipe (eg. name|message|phone)',
'send_btn_label' => 'Send button label',
'send_btn_label_comment' => 'Override send button label',
'form_success_msg' => 'Success message',
'form_success_msg_comment' => 'Override success message shown after successful sent',
'form_error_msg' => 'Error message',
'form_error_msg_comment' => 'Override error message shown after unsuccessful sent',
'disable_notifications' => 'Disable notification',
'disable_notifications_comment' => 'This will disable notification emails (overrides form settings)',
'notification_address_to' => 'Address TO',
'notification_address_to_comment' => 'This will override email address where notification email will be sent (if enabled in form settings)',
'notification_address_from' => 'Address FROM',
'notification_address_from_comment' => 'This will override email address from where notification email will be sent',
'notification_address_from_name' => 'Address FROM name',
'notification_address_from_name_comment' => 'This will override email address name from where notification email will be sent',
'notification_template' => 'Notification template',
'notification_template_comment' => 'This will override notification email template (eg. janvince.smallcontactform::mail.notification)',
'disable_autoreply' => 'Disable notification',
'disable_autoreply_comment' => 'This will disable notification emails (overrides form settings)',
'autoreply_address_from' => 'Address FROM',
'autoreply_address_from_comment' => 'This will override email address in autoreply email (if enabled in form settings)',
'autoreply_address_from_name' => 'Address (FROM) name',
'autoreply_address_from_name_comment' => 'This will override email address name in autoreply email (if enabled in form settings)',
'autoreply_template' => 'Autoreply template',
'autoreply_template_comment' => 'This will override autoreply email template (eg. janvince.smallcontactform::mail.autoreply)',
]
],
];

View File

@ -0,0 +1,539 @@
<?php
return [
'plugin' => [
'name' => 'Contact form',
'description' => 'Simple contact form builder',
'category' => 'Small plugins',
],
'permissions' => [
'access_messages' => 'Access messages list',
'access_settings' => 'Manage backend preferences',
'delete_messages' => 'Delete stored messages',
'export_messages' => 'Export messages',
],
'navigation' => [
'main_label' => 'Contact form',
'messages' => 'Messages',
],
'controller' => [
'contact_form' => [
'name' => 'Contact form',
'description' => 'Insert contact form to the page',
'no_fields' => 'Please add some form fields in backend administration first (in Settings > Small Contact form > Fields)...',
],
'filter' => [
'date' => 'Date range',
],
'scoreboard' => [
'records_count' => 'Messages',
'latest_record' => 'Latest from',
'new_count' => 'New',
'new_description' => 'Messages',
'read_count' => 'Read',
'all_count' => 'Total',
'all_description' => 'Messages',
'settings_btn' => 'Form settings',
'mark_read' => 'Mark as read',
'mark_read_confirm' => 'Really set selected messages as read?',
'mark_read_success' => 'Successfully marked as read.',
],
'preview' => [
'record_not_found' => 'Message not found!',
],
],
'models' => [
'message' => [
'columns' => [
'id' => 'ID',
'datetime' => 'Date and time',
'form_data' => 'Form data',
'name' => 'Name',
'email' => 'Email',
'message' => 'Message',
'new_message' => 'Status',
'new' => 'New',
'read' => 'Read',
'remote_ip' => 'Sender\'s IP',
'form_alias' => 'Alias',
'form_description' => 'Description',
'created_at' => 'Created at',
'updated_at' => 'Updated at',
'url' => 'URL',
'files' => 'Files',
'form_notes' => 'Notes',
]
],
],
'controllers' => [
'messages' => [
'list_title' => 'Messages',
'preview' => 'Preview',
'preview_title' => 'Contact form message',
'preview_date' => 'From date:',
'preview_content_title' => 'Content:',
'remote_ip' => 'Sent from ip',
'export' => 'Export',
],
'index' => [
'unauthorized' => 'Unauthorized access',
],
],
'mail' => [
'templates' => [
'autoreply' => 'Form autoreply message (English)',
'autoreply_cs' => 'Form autoreply message (Czech)',
'notification' => 'Form notification message (English)',
'notification_cs' => 'Form notification message (Czech)',
]
],
'reportwidget' => [
'partials' => [
'messages' => [
'label' => 'Contact form - Messages stats',
'title' => 'Messages stats',
'messages_all' => 'All',
'messages_new' => 'New',
'messages_read' => 'Read',
],
'new_message' => [
'label' => 'Contact form - New messages',
'title' => 'New messages',
'link_text' => 'Click to show Messages list',
],
],
],
'settings' => [
'form' => [
'css_class' => 'Form CSS class',
'use_placeholders' => 'Use placeholders',
'use_placeholders_comment' => 'Placeholders will be shown instead of field labels',
'disable_browser_validation' => 'Disable browser validation',
'disable_browser_validation_comment' => 'Do not allow browser built-in validation and popups.',
'success_msg' => 'Form success message',
'success_msg_placeholder' => 'Your data was sent.',
'error_msg' => 'Form error message',
'error_msg_placeholder' => 'There was an error sending your data!',
'allow_ajax' => 'Enable AJAX',
'allow_ajax_comment' => 'Allow AJAX with fallback for non JavaScript browsers',
'allow_confirm_msg' => 'Ask confirmation before form send',
'allow_confirm_msg_comment' => 'Add confirm dialog before sending',
'send_confirm_msg' => 'Confirmation text',
'send_confirm_msg_placeholder' => 'Are you sure?',
'hide_after_success' => 'Hide form after successful send',
'hide_after_success_comment' => 'Show only success message without form',
'add_assets' => 'Add assets',
'add_assets_comment' => 'Automatically add necessary CSS and JS assets (more about assets in README.md file)',
'add_css_assets' => 'Add CSS assets',
'add_css_assets_comment' => 'All necesssary styles will be included',
'add_js_assets' => 'Add JavaScript assets',
'add_js_assets_comment' => 'All necesssary JavaScripts will be included',
'form_ga_event_success' => 'GA event after successful sent',
'notes' => 'Notes',
'notes_comment' => 'You can add notes to display in mail messages.',
],
'sections' => [
'ga_events' => 'Events'
],
'ga' => [
'ga_success_event_allow' => 'Send event after successful sent',
'ga_success_event_gtag' => 'Global tag used on website',
'ga_success_event_gtag_empty_option' => 'Choose used tag',
'ga_success_event_gtag_ga' => 'analytics.js (old)',
'ga_success_event_gtag_gtag' => 'gtag.js',
],
'buttons' => [
'send_btn_text' => 'Send button text',
'send_btn_text_placeholder' => 'Send',
'send_btn_css_class' => 'Send button CSS class',
'send_btn_css_class_placeholder' => 'btn btn-primary',
'send_btn_wrapper_css' => 'Send button wrapper CSS class',
'send_btn_wrapper_css_placeholder' => 'form-group',
],
'redirect' => [
'allow_redirect' => 'Redirect after submit',
'allow_redirect_comment' => 'Redirect to another page after successfull submit',
'redirect_url' => 'Page URL to redirect to',
'redirect_url_comment' => 'Enter your page URL (eg. /contact/thank-you)',
'redirect_url_placeholder' => '/contact/thank-you',
'redirect_url_external' => 'External URL',
'redirect_url_external_comment' => 'This is external URL path (eg. http://www.domain.com)',
],
'form_fields' => [
'prompt' => 'Add new form field',
'name' => 'FIELD NAME',
'name_comment' => 'Lower case without special characters (eg. name, email, home_address, ...)',
'type' => 'Field type',
'label' => 'Label',
'label_placeholder' => 'Full name',
'field_styling' => 'Custom CSS class',
'field_styling_comment' => 'Change default Bootstrap styles',
'autofocus' => 'Autofocus field',
'autofocus_comment' => 'Autofocus this form field',
'wrapper_css' => 'Wrapper CSS class',
'wrapper_css_placeholder' => 'form-group',
'field_css' => 'Field CSS class',
'field_css_placeholder' => 'form-control',
'label_css' => 'Label CSS class',
'label_css_placeholder' => '',
'field_validation' => 'Field validation',
'field_validation_comment' => 'Add field validation rules',
'validation' => 'Validation',
'validation_prompt' => 'Add validation',
'validation_type' => 'Validation rule',
'validation_error' => 'Validation error message',
'validation_error_placeholder' => 'Please enter valid data.',
'validation_error_comment' => 'Error message to use when validation fails',
'validation_custom_type' => 'Validation rule name',
'validation_custom_type_comment' => 'Enter Validator rule name (eg. regex, boolean, ...).<br>See <a href="https://octobercms.com/docs/services/validation#available-validation-rules" target="_blank">validation rules</a>.',
'validation_custom_type_placeholder' => 'regex',
'validation_custom_pattern' => 'Validation rule pattern',
'validation_custom_pattern_comment' => 'Left empty or enter custom rule pattern (this is a right part of Validator rule after colon - eg. [abc] for regex).',
'validation_custom_pattern_placeholder' => "/^[0-9]+$/",
'custom' => 'Custom field',
'custom_description' => 'Custom field with validation option',
'add_values_prompt' => 'Add values',
'field_value_id' => 'Field value ID',
'field_value_content' => 'Field value content',
'hit_type' => 'Hit type',
'event_category' => 'Event category',
'event_action' => 'Event action',
'event_label' => 'Event label',
'custom_code' => 'Custom code',
'custom_code_comment' => 'This code will override built in field code. Use carefully!',
'custom_code_twig' => 'Allow Twig',
'custom_code_twig_comment' => 'If checked, Twig markup will be parsed.',
'custom_content' => 'Custom content',
'custom_content_comment' => 'This content will be added to field.',
],
'form_field_types' => [
'text' => 'Text',
'email' => 'Email',
'textarea' => 'Textarea',
'checkbox' => 'Checkbox',
'dropdown' => 'Dropdown',
'file' => 'File',
'custom_code' => 'Custom code',
'custom_content' => 'Custom content',
],
'form_field_validation' => [
'select' => '--- Select validation ---',
'required' => 'Required',
'email' => 'Email',
'numeric' => 'Numeric',
'custom' => 'Custom rule',
],
'email' => [
'address_from' => 'From address',
'address_from_placeholder' => 'john.doe@domain.com',
'address_from_name' => 'From address name',
'address_from_name_placeholder' => 'John Doe',
'address_replyto' => 'Reply To address',
'address_replyto_comment' => 'Reply to mail will be send to this address.',
'subject' => 'Email subject',
'subject_comment' => 'Set only if you want other than defined in Settings > Mail templates.',
'template' => 'Email template',
'template_comment' => 'Code of email template created in Settings > Email templates. Left empty for default template: janvince.smallcontactform::mail.autoreply.',
'allow_email_queue' => 'Queueing mail',
'allow_email_queue_comment' => 'Add email to queue instead of immediately send. You have to configure your OctoberCMS queue first!',
'allow_notifications' => 'Allow notifications',
'allow_notifications_comment' => 'Send notification after form has been sent',
'notification_address_to' => 'Send notification to email',
'notification_address_to_comment' => 'One email address or comma-separated list of addresses',
'notification_address_to_placeholder' => 'notifications@domain.com',
'notification_address_from_form' => 'Force notification From address (NOT SUPPORTED by all email systems!)',
'notification_address_from_form_comment' => 'Set notification From address to an email entered in contact form (the field must be set in column mapping).',
'allow_autoreply' => 'Allow autoreply',
'allow_autoreply_comment' => 'Send a form content copy to author',
'autoreply_name_field' => 'NAME form field',
'autoreply_name_field_empty_option' => '-- Select --',
'autoreply_name_field_comment' => 'Must be type of Text.<br><em>Save and refresh this page if you can\'t see your fields.</em>',
'autoreply_email_field' => 'EMAIL address form field',
'autoreply_email_field_empty_option' => '-- Select --',
'autoreply_email_field_comment' => 'Must be type of Email.<br><em>Save and refresh this page if you can\'t see your fields.</em>',
'autoreply_message_field' => 'MESSAGE form field',
'autoreply_message_field_empty_option' => '-- Select --',
'autoreply_message_field_comment' => 'Must be type of Textarea or Text.<br><em>Save and refresh this page if you can\'t see your fields.</em>',
'notification_template' => 'Notification email template',
'notification_template_comment' => 'Code of email template created in Settings > Email templates. Left empty for default template: janvince.smallcontactform::mail.autoreply.',
],
'antispam' => [
'add_antispam' => 'Add passive antispam protection',
'add_antispam_comment' => 'Add simple but effective passive antispam control (more info in README.md file)',
'antispam_delay' => 'Antispam delay (s)',
'antispam_delay_comment' => 'Delay protection for too fast form sending (usually by robots)',
'antispam_delay_placeholder' => '3',
'antispam_label' => 'Antispam field label',
'antispam_label_comment' => 'Label will be visible for non JavaScript enabled browsers',
'antispam_label_placeholder' => 'Please clear this field',
'antispam_error_msg' => 'Error message',
'antispam_error_msg_comment' => 'Message to show to user when antispam protection is triggered',
'antispam_error_msg_placeholder' => 'Please empty this field!',
'antispam_delay_error_msg' => 'Delay error message',
'antispam_delay_error_msg_comment' => 'Message to show to user when form was sent too fast',
'antispam_delay_error_msg_placeholder' => 'Form sent too fast! Please wait few seconds and try again!',
'add_google_recaptcha' => 'Add Google reCaptcha',
'add_google_recaptcha_comment' => 'Add reCaptcha to Contact Form (more info in README.md file).<br>You can get API keys on <a href="https://www.google.com/recaptcha/admin#list" target="_blank">Google reCaptcha site</a>.',
'google_recaptcha_version' => 'Google reCaptcha version',
'google_recaptcha_version_comment' => 'Choose a version of reCaptcha widget.<br>More info on <a href="https://developers.google.com/recaptcha/docs/versions" target="_blank">Google reCaptcha site</a>.',
'google_recaptcha_versions' => [
'v2checkbox' => 'reCaptcha V2 checkbox',
'v2invisible' => 'reCaptcha V2 invisible',
],
'google_recaptcha_site_key' => 'Site key',
'google_recaptcha_site_key_comment' => 'Put your site key',
'google_recaptcha_secret_key' => 'Secret key',
'google_recaptcha_secret_key_comment' => 'Put your secret key',
'google_recaptcha_wrapper_css' => 'reCaptcha box wrapper CSS class',
'google_recaptcha_wrapper_css_comment' => 'CSS class of wrapper box around reCaptcha box',
'google_recaptcha_wrapper_css_placeholder' => 'form-group',
'google_recaptcha_error_msg' => 'Error message',
'google_recaptcha_error_msg_comment' => 'Message to show to user when reCAPTCHA is not validated.',
'google_recaptcha_error_msg_placeholder' => 'Google reCAPTCHA validation error!',
'google_recaptcha_scripts_allow' => 'Automatically add necessary JS scripts',
'google_recaptcha_scripts_allow_comment' => 'This will add link to JS scripts to your site.',
'google_recaptcha_locale_allow' => 'Allow locale detection',
'google_recaptcha_locale_allow_comment' => 'This will add curent web page locale to reCAPTCHA script, so it will translated.',
'add_ip_protection' => 'Check sender\'s IP',
'add_ip_protection_comment' => 'Do not allow too many form submits from one IP address',
'add_ip_protection_count' => 'Maximum form submits during a day',
'add_ip_protection_count_comment' => 'Number of allowed submits from one IP address during a single day',
'add_ip_protection_count_placeholder' => '3',
'add_ip_protection_error_get_ip' => 'We wasn\'t able to determine your IP address!',
'add_ip_protection_error_too_many_submits' => 'Too many submits error message',
'add_ip_protection_error_too_many_submits_comment' => 'Error message to show to the user',
'add_ip_protection_error_too_many_submits_placeholder' => 'Too many form submits from one address today!',
'disabled_extensions' => 'Disabled extensions',
'disabled_extensions_comment' => 'Settings set on Privacy tab disabled these extensions',
],
'mapping' => [
'hint' => [
'title' => 'Why fields mapping?',
'content' => '
<p>You can build a custom form with own field names and types.</p>
<p>System writes all form data in database, but for quick overview Name, Email and Message columns are visible separately in Messages list.</p>
<p>So you have to help system to identify these columns by mapping to your form fields.</p>
<p><em>These mappings are also used for autoreply emails where at least Email field mapping is important.</em></p>
',
],
'warning' => [
'title' => 'Can\'t select your form fields?',
'content' => '
<p>If you don\'t see your form fields, click on button Save at the bottom of this page and then reload page (F5 or Ctr+R / Cmd+R).</p>
',
],
],
'privacy' => [
'disable_messages_saving' => 'Disable messages saving',
'disable_messages_saving_comment' => 'When checked, no data will saved in Messages list.<br><strong>This will also disable IP protection!</strong>',
'disable_messages_saving_comment_section' => '<div class="callout fade in callout-danger no-subheader"><div class="header"><i class="icon-warning"></i><h3>Be sure to allow notification emails or you will have no data from sent forms!</h3></div></div>',
],
'tabs' => [
'form' => 'Form',
'buttons' => 'Send button',
'form_fields' => 'Fields',
'mapping' => 'Columns mapping',
'email' => 'Email',
'antispam' => 'Antispam',
'privacy' => 'Privacy',
'ga' => 'Google Analytics',
],
],
'components' => [
'groups' => [
'hacks' => 'Hacks',
'override_form' => 'Override form settings',
'override_notifications' => 'Override notification settings',
'override_autoreply' => 'Override autoreply settings',
'override' => 'Override form settings',
'override_redirect' => 'Override redirect settings',
'override_ga' => 'Override Google Analytics settings',
'override_notes' => 'Override notes',
],
'properties' => [
'form_description' => 'Form description',
'form_description_comment' => 'You can add optional form description, that will be saved with other sent data in the messages list. You can also use {{ :slug }} here.',
'disable_fields' => 'Disable fields',
'disable_fields_comment' => 'This will disable listed fields. Add field names separated by pipe (eg. name|message|phone)',
'send_btn_label' => 'Send button label',
'send_btn_label_comment' => 'Override send button label',
'form_success_msg' => 'Success message',
'form_success_msg_comment' => 'Override success message shown after successful sent',
'form_error_msg' => 'Error message',
'form_error_msg_comment' => 'Override error message shown after unsuccessful sent',
'disable_notifications' => 'Disable notification',
'disable_notifications_comment' => 'This will disable notification emails (overrides form settings)',
'notification_address_to' => 'Address TO',
'notification_address_to_comment' => 'This will override email address where notification email will be sent (if enabled in form settings)',
'notification_address_from' => 'Address FROM',
'notification_address_from_comment' => 'This will override email address from where notification email will be sent',
'notification_address_from_name' => 'Address FROM name',
'notification_address_from_name_comment' => 'This will override email address name from where notification email will be sent',
'notification_template' => 'Notification template',
'notification_template_comment' => 'This will override notification email template (eg. janvince.smallcontactform::mail.notification)',
'notification_subject' => 'Notification subject',
'notification_template_comment' => 'Override email subject',
'disable_autoreply' => 'Disable notification',
'disable_autoreply_comment' => 'This will disable notification emails (overrides form settings)',
'autoreply_address_from' => 'Address FROM',
'autoreply_address_from_comment' => 'This will override email address in autoreply email (if enabled in form settings)',
'autoreply_address_from_name' => 'Address (FROM) name',
'autoreply_address_from_name_comment' => 'This will override email address name in autoreply email (if enabled in form settings)',
'autoreply_address_replyto' => 'Address REPLY TO',
'autoreply_address_replyto_comment' => 'This will override REPLY TO email address in autoreply email (if enabled in form settings)',
'autoreply_template' => 'Autoreply template',
'autoreply_template_comment' => 'This will override autoreply email template (eg. janvince.smallcontactform::mail.autoreply)',
'autoreply_subject' => 'Autoreply email subject',
'autoreply_template_comment' => 'Override email subject',
]
],
];

View File

@ -0,0 +1,539 @@
<?php
return [
'plugin' => [
'name' => 'Lomake',
'description' => 'Yksinkertainen lomaketyökalu',
'category' => 'Small plugins',
],
'permissions' => [
'access_messages' => 'Pääsy viestilistaan',
'access_settings' => 'Hallitse ylläpidon asetuksia',
'delete_messages' => 'Poista tallennetut viestit',
'export_messages' => 'Vie viestit',
],
'navigation' => [
'main_label' => 'Lomake',
'messages' => 'Viestit',
],
'controller' => [
'contact_form' => [
'name' => 'Yhteydenottolomake',
'description' => 'Lisää yhteydenottolomake sivulle',
'no_fields' => 'Ole hyvä ja lisää muutama kenttä ylläpidossa. (Asetukset > Yhteydenottolomake > Kentät)...',
],
'filter' => [
'date' => 'Päivämääräväli',
],
'scoreboard' => [
'records_count' => 'Viestit',
'latest_record' => 'Viimeisimmät',
'new_count' => 'Uusi',
'new_description' => 'Viestit',
'read_count' => 'Luetut',
'all_count' => 'Yhteensä',
'all_description' => 'Viestit',
'settings_btn' => 'Lomakeasetukset',
'mark_read' => 'Merkitse luetuksi',
'mark_read_confirm' => 'Haluatko varmasti merkitä viestin luetuksi`?',
'mark_read_success' => 'Viesti merkitty luetuksi.',
],
'preview' => [
'record_not_found' => 'Viestiä ei löytynyt!',
],
],
'models' => [
'message' => [
'columns' => [
'id' => 'ID',
'datetime' => 'PVM ja aika',
'form_data' => 'Lomakedata',
'name' => 'Nimi',
'email' => 'Sähköposti',
'message' => 'Viesti',
'new_message' => 'Tila',
'new' => 'Uusi',
'read' => 'Luettu',
'remote_ip' => 'Lähettjän IP',
'form_alias' => 'Alias',
'form_description' => 'Kuvaus',
'created_at' => 'Luotu',
'updated_at' => 'Päivitetty',
'url' => 'URL',
'files' => 'Tiedostot',
'form_notes' => 'Muistiinpanot',
]
],
],
'controllers' => [
'messages' => [
'list_title' => 'Viestit',
'preview' => 'Esikatselu',
'preview_title' => 'Yhteydenottolomakkeen viesti',
'preview_date' => 'Alkaen pvm:',
'preview_content_title' => 'Sisältö:',
'remote_ip' => 'IP-osoite',
'export' => 'Vie',
],
'index' => [
'unauthorized' => 'Ei pääsyä',
],
],
'mail' => [
'templates' => [
'autoreply' => 'Form autoreply message (English)',
'autoreply_fi' => 'Yhteydenoton automaattisen vastauksen viesti (Finnish)',
'notification' => 'Form notification message (English)',
'notification_fi' => 'Yhteydenoton notifikaatioviesti (Finnish)',
]
],
'reportwidget' => [
'partials' => [
'messages' => [
'label' => 'Lomake - Viestitilastot',
'title' => 'Viestitilastot',
'messages_all' => 'Kaikki',
'messages_new' => 'Uusi',
'messages_read' => 'Luettu',
],
'new_message' => [
'label' => 'Lomake - Uusi viesti',
'title' => 'Uudet viestit',
'link_text' => 'Klikkaa viestilistalle',
],
],
],
'settings' => [
'form' => [
'css_class' => 'Lomakkeen CSS-luokat',
'use_placeholders' => 'Käytä esimerkkitekstiä',
'use_placeholders_comment' => 'Esimerkkiteksti näytetään kenttien otsikoiden sijasta',
'disable_browser_validation' => 'Poista selaimen validointi käytöstä',
'disable_browser_validation_comment' => 'Älä salli selaimen sisäänrakennettua validointia ja ponnahdusikkunoita.',
'success_msg' => 'Onnistuneen lähetyksen viesti',
'success_msg_placeholder' => 'Lomake lähetetty onnistuneesti.',
'error_msg' => 'Viesti lähetyksen epäonnistuessa',
'error_msg_placeholder' => 'Lomaketta ei voitu lähettää!',
'allow_ajax' => 'Salli AJAX',
'allow_ajax_comment' => 'Salli AJAX oletuksena selaimille, joissa JacaSkriptiä ei ole',
'allow_confirm_msg' => 'Kysy vahvistus ennen lomakkeen lähetystä',
'allow_confirm_msg_comment' => 'Lisää vahvistusikkuna ennen lomakkeen lähetystä',
'send_confirm_msg' => 'Vahvistusteksti',
'send_confirm_msg_placeholder' => 'Oletko varma?',
'hide_after_success' => 'Piilota lomake onnistuneen lähetyksen jälkeen',
'hide_after_success_comment' => 'Näytä vain Lähetys onnistui -viesti ja piilota lomake',
'add_assets' => 'Lisää kirjastot',
'add_assets_comment' => 'Lisää automaattisesti tarvittavat CSS- ja JS-kirjastot (lue lisää README.md-tiedostosta)',
'add_css_assets' => 'Lisää CSS-kirjasto',
'add_css_assets_comment' => 'Kaikki tarvittavat tyylit sisällytetään',
'add_js_assets' => 'Lisää JavaScript-kirjasto',
'add_js_assets_comment' => 'Kaikki tarvittavat JavaScripts-kirjastot sisällytetään',
'form_ga_event_success' => 'GA-tapahtuma onnistuneen lähetyksen jälkeen',
'notes' => 'Muistiinpanot',
'notes_comment' => 'Voit lisätä muistiinpanoja, joita näytetään viesteissä.',
],
'sections' => [
'ga_events' => 'Tapahtumat'
],
'ga' => [
'ga_success_event_allow' => 'Lähetystapahtyma onnistuneesta lähetyksestä',
'ga_success_event_gtag' => 'Global tag, jota käytetään sivustolla',
'ga_success_event_gtag_empty_option' => 'Valitse käytettävä tagi',
'ga_success_event_gtag_ga' => 'analytics.js (old)',
'ga_success_event_gtag_gtag' => 'gtag.js',
],
'buttons' => [
'send_btn_text' => 'Lähetä nappulan teksti',
'send_btn_text_placeholder' => 'Lähetä',
'send_btn_css_class' => 'Lähetä nappulan CSS-luokka',
'send_btn_css_class_placeholder' => 'btn btn-primary',
'send_btn_wrapper_css' => 'Lähetä nappulan wrapper CSS-luokka',
'send_btn_wrapper_css_placeholder' => 'form-group',
],
'redirect' => [
'allow_redirect' => 'Edelleenohjaa lähetyksen jälkeen',
'allow_redirect_comment' => 'Edelleenohjaa toiseen sivuun onnistuneen lähetyksen jälkeen',
'redirect_url' => 'Sivun URL, johon ohjataan',
'redirect_url_comment' => 'Lisää sivun URL-osoite (esim. /yhteystiedot/kiitos)',
'redirect_url_placeholder' => '/yhteystiedot/kiitos',
'redirect_url_external' => 'Ulkoinen URL-osoite',
'redirect_url_external_comment' => 'Tämä on ulkoisen sivuston osoite (esim. http://www.domain.com)',
],
'form_fields' => [
'prompt' => 'Lisää uusi lomakekenttä',
'name' => 'KENTÄN NIMI',
'name_comment' => 'pienin kirjaimin, ei erikoismerkkejä (esim. nimi, sahkoposti, osoite_koti, ...)',
'type' => 'Kentän tyyppi',
'label' => 'Label',
'label_placeholder' => 'Koko nimi',
'field_styling' => 'Oma CSS-luokka',
'field_styling_comment' => 'Vaihda oletus Bootstrap-tyyli',
'autofocus' => 'Autofocus-kenttä',
'autofocus_comment' => 'Tee tästä kentästä Autofocus',
'wrapper_css' => 'Wrapper CSS-luokka',
'wrapper_css_placeholder' => 'form-group',
'field_css' => 'Field CSS-luokka',
'field_css_placeholder' => 'form-control',
'label_css' => 'Label CSS-luokka',
'label_css_placeholder' => '',
'field_validation' => 'Kentän validointi',
'field_validation_comment' => 'Lisää kentän validointisäännöt',
'validation' => 'Validointi',
'validation_prompt' => 'Lisää validointi',
'validation_type' => 'Validointisääntö',
'validation_error' => 'Validoinnin virheilmoitus',
'validation_error_placeholder' => 'Ole hyvä ja korjaa kentän tieto.',
'validation_error_comment' => 'Virheviesti, joka näytetään epäonnistuneesta validoinnista',
'validation_custom_type' => 'Validointisäännön nimi',
'validation_custom_type_comment' => 'Anna validointisäännölle nimi (esim. regex, boolean, ...).<br>Katso <a href="https://octobercms.com/docs/services/validation#available-validation-rules" target="_blank">validointi säännöt</a>.',
'validation_custom_type_placeholder' => 'regex',
'validation_custom_pattern' => 'Validointisäännön pattern',
'validation_custom_pattern_comment' => 'Jätä tyhjäksi tai anna oma pattern (tämä on oikean puoleinen osa Validaattorisäännön jälkeen kaksoispisteen perässä - esim. [abc], regex).',
'validation_custom_pattern_placeholder' => "/^[0-9]+$/",
'custom' => 'Oma kenttä',
'custom_description' => 'Oma kenttä validointioptiolla',
'add_values_prompt' => 'Lisää arvot',
'field_value_id' => 'Kentän arvo ID',
'field_value_content' => 'Kentän arvon sisältö',
'hit_type' => 'Hit-tyyppi',
'event_category' => 'Tapahtumakategoria',
'event_action' => 'Tapahtuma toimenpide',
'event_label' => 'Tapahtuma label',
'custom_code' => 'Oma koodi',
'custom_code_comment' => 'Tämä yliajaa kentän oletuskoodin. Käytä varoen!',
'custom_code_twig' => 'Salli Twig',
'custom_code_twig_comment' => 'Mikäli sallittu, Twig-markup parseroidaan.',
'custom_content' => 'Oma sisältö',
'custom_content_comment' => 'Tämä sisältö lisätään kenttään.',
],
'form_field_types' => [
'text' => 'Teksi',
'email' => 'Email',
'textarea' => 'Tekstialue',
'checkbox' => 'Valintaruutu',
'dropdown' => 'Pudotusvalikko',
'file' => 'Tiedosto',
'custom_code' => 'Oma koodi',
'custom_content' => 'Oma sisältö',
],
'form_field_validation' => [
'select' => '--- Valitse ---',
'required' => 'Pakollinen',
'email' => 'Sähköposti',
'numeric' => 'Numeerinen',
'custom' => 'Oma sääntö',
],
'email' => [
'address_from' => 'Lähetysosoite',
'address_from_placeholder' => 'john.doe@domain.com',
'address_from_name' => 'Lähettäjän nimi',
'address_from_name_placeholder' => 'John Doe',
'address_replyto' => 'Vastausosoite',
'address_replyto_comment' => 'Vastausviesti lähetetään tähän osoitteeseen.',
'subject' => 'Viestin aihe',
'subject_comment' => 'Aseta vain, mikäli haluat vaihtaa oletuksen (Asetukset > Sähköpostipohjat.',
'template' => 'Sähköpostipohja',
'template_comment' => 'Koodi, joka on luotu Asetukset > Sähköpostipohjat. Jätä tyhjäksi käyttääksesi oletuspohjaa: janvince.smallcontactform::mail.autoreply.',
'allow_email_queue' => 'Laita lähetykset jonoon',
'allow_email_queue_comment' => 'Lähetä sähköposti jonossa sen sijaan, että se lähetetään heti. OctoberCMS jono pitää konfiguroida ensin!',
'allow_notifications' => 'Salli notifikaatiot',
'allow_notifications_comment' => 'Lähetä notifikaatio onnistuneen lähetyksen jälkeen',
'notification_address_to' => 'Notifikaatioiden sähköpostiosoite',
'notification_address_to_comment' => 'Yksi osoite tai pilkulla erotettuna useampi',
'notification_address_to_placeholder' => 'notifications@domain.com',
'notification_address_from_form' => 'Pakota notifikaatio Lähettäjä-osoite (EI TUETA kaikissa sähköpostijärjestelmissä!)',
'notification_address_from_form_comment' => 'Aseta notifikaatioiden Lähettäjä-osoite, josta Yhteydenottolomake näkyy tulevan (kenttä on asetettava palsta kartoitukseen).',
'allow_autoreply' => 'Salli autoreply',
'allow_autoreply_comment' => 'Lähetä lomakkeen sisältö kopiona lähettäjälle',
'autoreply_name_field' => 'NIMI lomakekenttä',
'autoreply_name_field_empty_option' => '-- Valitse --',
'autoreply_name_field_comment' => 'Tyypin on oltava Teksti.<br><em>Tallenna ja lataa uudelleen tämä sivu, mikäli kentät ei näy.</em>',
'autoreply_email_field' => 'EMAIL-osoite lomakekenttä',
'autoreply_email_field_empty_option' => '-- Valitse --',
'autoreply_email_field_comment' => 'Tyypin on oltava Email.<br><em>Tallenna ja lataa uudelleen tämä sivu, mikäli kentät ei näy.</em>',
'autoreply_message_field' => 'VIESTI lomakekenttä',
'autoreply_message_field_empty_option' => '-- Valitse --',
'autoreply_message_field_comment' => 'Tyypin on oltava Tekstialue tai Teksti.<br><em>Tallenna ja lataa uudelleen tämä sivu, mikäli kentät ei näy.</em>',
'notification_template' => 'Notifikaatioiden lomakepohja',
'notification_template_comment' => 'Sähköpostipohjan koodi on luotu Asetukset > Sähköpostipohjat. Jätä tyhjäksi, jos haluat käyttää oletusta: janvince.smallcontactform::mail.autoreply.',
],
'antispam' => [
'add_antispam' => 'Lisää passiivinen roskapostisuodatin',
'add_antispam_comment' => 'Lisää yksinkertainen mutta tehokas roskapostisuodatin (lisätietoja README.md tiedostossa)',
'antispam_delay' => 'Roskapostisuodattimen viive (s)',
'antispam_delay_comment' => 'Viive, kuinka nopeasti suodattimen kautta voi yrittää uudelleen lähettää (estää usein roskapostirobottien toimintaa)',
'antispam_delay_placeholder' => '3',
'antispam_label' => 'Roskapostisuodattimen kentän nimi',
'antispam_label_comment' => 'Nimi näytetään selaimilla, joissa ei ole JavaScript päällä',
'antispam_label_placeholder' => 'Ole hyvä ja tyhjennä tämä kenttä',
'antispam_error_msg' => 'Virheviesti',
'antispam_error_msg_comment' => 'Viesti, joka näytetään käyttäjälle kun roskapostisuodatin on käynnistynyt',
'antispam_error_msg_placeholder' => 'Ole hyvä ja tyhjennä tämä kenttä!',
'antispam_delay_error_msg' => 'Virheviesti viiveestä',
'antispam_delay_error_msg_comment' => 'Virheviesti, joka näytetään mikäli lomake lähetetään liian nopeasti',
'antispam_delay_error_msg_placeholder' => 'Uusi viesti lähetettiin liian nopeasti! Odota muutama sekunti ja yritä uudelleen!',
'add_google_recaptcha' => 'Lisää Google reCaptcha',
'add_google_recaptcha_comment' => 'Lisää reCaptcha yhteydenottolomakkeelle (Lisätietoja README.md tiedostossa).<br>Saat API-avaimet <a href="https://www.google.com/recaptcha/admin#list" target="_blank">Google reCaptcha -sivustolta</a>.',
'google_recaptcha_version' => 'Google reCaptcha versio',
'google_recaptcha_version_comment' => 'Valitse versio reCaptcha vimpaimesta.<br>Lisätietoja <a href="https://developers.google.com/recaptcha/docs/versions" target="_blank">Google reCaptcha -sivustolta</a>.',
'google_recaptcha_versions' => [
'v2checkbox' => 'reCaptcha V2 checkbox',
'v2invisible' => 'reCaptcha V2 invisible',
],
'google_recaptcha_site_key' => 'Sivustokohtainen avain',
'google_recaptcha_site_key_comment' => 'Lisää sivustoavaimesi',
'google_recaptcha_secret_key' => 'Salainen avain',
'google_recaptcha_secret_key_comment' => 'Lisää salainen avaimesi',
'google_recaptcha_wrapper_css' => 'reCaptcha laatikon wrapper CSS-luokka',
'google_recaptcha_wrapper_css_comment' => 'CSS-luokka wrapper-laatikkoon reCaptcha:n ympärille',
'google_recaptcha_wrapper_css_placeholder' => 'form-group',
'google_recaptcha_error_msg' => 'Virheviesti',
'google_recaptcha_error_msg_comment' => 'Viesti, joka näytetään väärästä reCAPTCHA-validoinnista.',
'google_recaptcha_error_msg_placeholder' => 'Google reCAPTCHA validointivirhe!',
'google_recaptcha_scripts_allow' => 'Lisää tarvittavat JS-skriptit automaattisesti',
'google_recaptcha_scripts_allow_comment' => 'Tämän avulla lisätään tarvittavati JS-skriptit automaattisesti sivustollesi.',
'google_recaptcha_locale_allow' => 'Salli kielialueen tunnistus',
'google_recaptcha_locale_allow_comment' => 'Tämän avulla käännetään reCAPTCHA-skripti käyttäjän selainta vastaavalle kielelle.',
'add_ip_protection' => 'Tarkista lähettäjän IP',
'add_ip_protection_comment' => 'Älä salli liian montaa lähetystä yhdestä IP-osoitteesta',
'add_ip_protection_count' => 'Sallittujen lähetysten maksimimäärä per päivä',
'add_ip_protection_count_comment' => 'Kuinka monta lähetystä sallitaan yhdestä IP-osoitteesta per päivä',
'add_ip_protection_count_placeholder' => '3',
'add_ip_protection_error_get_ip' => 'Emme voineet varmentaa IP-osoitettasi!',
'add_ip_protection_error_too_many_submits' => 'Liian monta lähetystä -viesti',
'add_ip_protection_error_too_many_submits_comment' => 'Viesti, joka näytetään käyttäjälle',
'add_ip_protection_error_too_many_submits_placeholder' => 'Olet lähettänyt liian monta viestiä 24-tunnin aikana!',
'disabled_extensions' => 'Poista laajennukset käytöstä',
'disabled_extensions_comment' => 'Asetukset tehdään Yksityisyys-välilehdellä',
],
'mapping' => [
'hint' => [
'title' => 'Miksi mappaus?',
'content' => '
<p>Voit rakentaa oman lomakkeen omilla kentillä ja kenttätyypeillä.</p>
<p>Järjestelmä kirjoittaa kaiken tiedon tietokantaan, mutta pikaselausta varten Nimi-, Sähköposti- ja Viesti-sarakkeet ovat erikseen näkyvissä viestilistauksessa.</p>
<p>Helpottaaksesi järjestelmää ymmärtämään kenttien riippuvuudet, sinun on mäpättävä ne manuaalisesti.</p>
<p><em>Näitä mäppäyksiä hyödynnetään myös autoreply-viesteissä, missä vähintään sähköpostikenttä on tärkeä.</em></p>
',
],
'warning' => [
'title' => 'Et voi valita lomakekenttiä?',
'content' => '
<p>Mikäli et näe lomakekenttiä, tallenna ja päivitä selaimesi (paina F5 tai Ctr+R / Cmd+R).</p>
',
],
],
'privacy' => [
'disable_messages_saving' => 'Poista viestin tallennus käytöstä',
'disable_messages_saving_comment' => 'Mikäli valittuna, viestejä ei tallenneta muistiin.<br><strong>Tämä poistaa myös IP-suojauksen käytöstä!</strong>',
'disable_messages_saving_comment_section' => '<div class="callout fade in callout-danger no-subheader"><div class="header"><i class="icon-warning"></i><h3>Varmista, että olet sallinut notifikaatioviestit tai muuten et saa ollenkaan tietoa lähetetyistä yhteydenotoista!</h3></div></div>',
],
'tabs' => [
'form' => 'Lomake',
'buttons' => 'Lähetä-nappula',
'form_fields' => 'Kentät',
'mapping' => 'Columns mapping',
'email' => 'Sähköposti',
'antispam' => 'Roskapostisuodatus',
'privacy' => 'Yksityisyys',
'ga' => 'Google Analytics',
],
],
'components' => [
'groups' => [
'hacks' => 'Hacks',
'override_form' => 'Yliaja lomakeasetukset',
'override_notifications' => 'Yliaja notifikaatioasetukset',
'override_autoreply' => 'Yliaja autoreply-asetukset',
'override' => 'Yliaja lomakkeen asetukset',
'override_redirect' => 'Yliaja edelleenohjauksen asetukset',
'override_ga' => 'Yliaja Google Analytics -asetukset',
'override_notes' => 'Yliaja muistiinpanot',
],
'properties' => [
'form_description' => 'Lomakkeen kuvaus',
'form_description_comment' => 'Voit lisätä vaihtoehtoisen lomakkeen kuvauksen, joka tallennetaan yhdessä muun datan kanssa viestilistaan. Voit myös käyttää {{ :slug }} tässä kohdassa.',
'disable_fields' => 'Kentät pois käytöstä',
'disable_fields_comment' => 'Tämä ottaa kentät pois käytöstä. Lisää halutut kentät erotettuna pystyviivalla (esim. name|message|phone)',
'send_btn_label' => 'Lähetä-nappulan teksti',
'send_btn_label_comment' => 'Yliaja Lähetä-nappulan teksti',
'form_success_msg' => 'Lähetys onnistui -viesti',
'form_success_msg_comment' => 'Yliaja Viesti lähetetty onnistuneesti -viesti',
'form_error_msg' => 'Virheviesti',
'form_error_msg_comment' => 'Yliaja virheviesti epäonnistuneesta lähetyksestä',
'disable_notifications' => 'Poista notifikaatiot',
'disable_notifications_comment' => 'Tämä poistaa notifikaatiosähköpostit käytöstä (yliajaa lomakeasetukset)',
'notification_address_to' => 'Viesti TO',
'notification_address_to_comment' => 'Tämän avulla voit yliajaa vastaanottajan sähköpostiosoitteen (mikäli aktiivinen lomakkeen asetuksissa)',
'notification_address_from' => 'Lähettäjä FROM',
'notification_address_from_comment' => 'Tämä yliajaa sähköpostiosoitteen notifikaatioista, mistä osoitteesta viesti tulee',
'notification_address_from_name' => 'Lähettäjän FROM-nimi',
'notification_address_from_name_comment' => 'Tämä yliajaa sähköpostiosoitteen nimen, kuka lähettäjänä on',
'notification_template' => 'Notifikaatio pohja',
'notification_template_comment' => 'Tämä yliajaa oletuspohjan jota notifikaatiot käyttävät (esim. janvince.smallcontactform::mail.notification)',
'notification_subject' => 'Notifikaation aihe',
'notification_template_comment' => 'Yliaja sähköpostin aihe',
'disable_autoreply' => 'Poista notifikaatiot käytöstä',
'disable_autoreply_comment' => 'Tämä poistaa notifikaatiopostit käytöstä (yliajaa lomakkeen asetukset)',
'autoreply_address_from' => 'Viesti FROM',
'autoreply_address_from_comment' => 'Tämä yliajaa sähköpostiosoitteen, jota käytetään autoreply osoitteena (mikäli käytössä lomakkeen asetuksissa)',
'autoreply_address_from_name' => 'Lähettäjän (FROM) nimi',
'autoreply_address_from_name_comment' => 'Tämä yliajaa lähettäjän nimen autoreply-sähköposteista (mikäli käytössä lomakkeen asetuksissa)',
'autoreply_address_replyto' => 'Vastausosoite REPLY TO',
'autoreply_address_replyto_comment' => 'Tämä yliajaa vastausosoitteen autoreply-sähköposteissa (mikäli käytössä lomakkeen asetuksissa)',
'autoreply_template' => 'Autoreply-valmispohja',
'autoreply_template_comment' => 'Tämä yliajaa autoreply-sähköpostipohjan (esim. janvince.smallcontactform::mail.autoreply)',
'autoreply_subject' => 'Autoreply-sähköpostin aihe',
'autoreply_template_comment' => 'Tämä yliajaa autoreply-vastauksen viestin aiheen',
]
],
];

View File

@ -0,0 +1,426 @@
<?php
return [
'plugin' => [
'name' => 'Formulaire de contact',
'description' => 'Générateur simple de formulaire de contact',
'category' => 'Petits plugins',
],
'permissions' => [
'access_messages' => 'Accéder à la liste des messages',
'access_settings' => 'Gérer les préférences d\'administration',
'delete_messages' => 'Supprimer les messages stockés',
'export_messages' => 'Exporter des messages',
],
'navigation' => [
'main_label' => 'Formulaire de contact',
'messages' => 'Messages',
],
'controller' => [
'contact_form' => [
'name' => 'Formulaire de contact',
'description' => 'Insérer un formulaire de contact sur la page',
'no_fields' => 'Veuillez ajouter d\abord des champs de formulaire dans l\administration dorsale (dans Paramètres > Formulaire de contact > Champs) ...',
],
'filter' => [
'date' => 'Plage de dates',
],
'scoreboard' => [
'records_count' => 'Messages',
'latest_record' => 'Dernier message de',
'new_count' => 'Nouveau',
'new_description' => 'Messages',
'read_count' => 'Lus',
'all_count' => 'Total',
'all_description' => 'Messages',
'settings_btn' => 'Paramètres du formulaire',
'mark_read' => 'Marquer comme lu',
'mark_read_confirm' => 'Voulez-vous vraiment définir les messages sélectionnés comme lus?',
'mark_read_success' => 'Les messages ont été marqués comme lu avec succès.',
],
'preview' => [
'record_not_found' => 'Message non trouvé!',
],
],
'models' => [
'message' => [
'columns' => [
'id' => 'ID',
'datetime' => 'Date et heure',
'form_data' => 'Données du formulaire',
'name' => 'Nom',
'email' => 'E-mail',
'message' => 'Message',
'new_message' => 'Statut',
'new' => 'Nouveau',
'read' => 'Lu',
'remote_ip' => 'IP de l\'expéditeur',
'form_alias' => 'Alias',
'form_description' => 'Description',
'created_at' => 'Créé à',
'updated_at' => 'Modifié à',
]
],
],
'controllers' => [
'messages' => [
'list_title' => 'Messages',
'preview' => 'Aperçu',
'preview_title' => 'Message du formulaire de contact',
'preview_date' => 'Date : ',
'preview_content_title' => 'Contenu :',
'remote_ip' => 'Envoyé depuis l\'IP :',
'export' => 'Exporter',
],
'index' => [
'unauthorized' => 'Accès non autorisé',
],
],
'mail' => [
'templates' => [
'autoreply' => 'Réponse automatique du formulaire (français)',
'autoreply_cs' => 'Réponse automatique du formulaire (tchèque)',
'notification' => 'Message de notification du formulaire (français)',
'notification_cs' => 'Message de notification du formulaire (tchèque)',
]
],
'reportwidget' => [
'partials' => [
'messages' => [
'label' => 'Formulaire de contact - Statistiques des messages',
'title' => 'Statistiques des messages',
'messages_all' => 'Tout',
'messages_new' => 'Nouveaux',
'messages_read' => 'Lus',
],
'new_message' => [
'label' => 'Formulaire de contact - Nouveaux messages',
'title' => 'Nouveaux messages',
'link_text' => 'Cliquez pour afficher la liste des messages',
],
],
],
'settings' => [
'form' => [
'css_class' => 'Classe CSS du formulaire',
'use_placeholders' => 'Utiliser des "placeholder"',
'use_placeholders_comment' => 'Des "placeholder" seront affichés à la plage des étiquettes de champs.',
'disable_browser_validation' => 'Désactiver la validation du navigateur',
'disable_browser_validation_comment' => 'Ne pas autoriser la validation intégrée du navigateur et ses fenêtres contextuelles.',
'success_msg' => 'Message de réussite du formulaire',
'success_msg_placeholder' => 'Vos données ont été envoyées.',
'error_msg' => 'Message d\'erreur du formulaire',
'error_msg_placeholder' => 'Une erreur s\'est produite lors de l\'envoi de vos données!',
'allow_ajax' => 'Activer AJAX',
'allow_ajax_comment' => 'Autoriser AJAX avec rechange pour les navigateurs sans JavaScript.',
'allow_confirm_msg' => 'Demander une confirmation avant l\'envoi du formulaire',
'allow_confirm_msg_comment' => 'Ajouter une boîte de dialogue de confirmation avant l\'envoi',
'send_confirm_msg' => 'Texte de confirmation',
'send_confirm_msg_placeholder' => 'Êtes-vous sûr?',
'hide_after_success' => 'Masquer le formulaire après l\'envoi réussi',
'hide_after_success_comment' => 'Afficher uniquement le message de réussite sans formulaire',
'add_assets' => 'Ajouter des assets',
'add_assets_comment' => 'Ajouter automatiquement les assets CSS et JS nécessaires (plus d\'informations sur les assets dans le fichier README.md - en anglais)',
'add_css_assets' => 'Ajouter des assets CSS',
'add_css_assets_comment' => 'Tous les styles nécessaires seront inclus',
'add_js_assets' => 'Ajouter des assets JavaScript',
'add_js_assets_comment' => 'Tous les scripts JavaScript nécessaires seront inclus',
],
'buttons' => [
'send_btn_text' => 'Texte du bouton envoyer',
'send_btn_text_placeholder' => 'Envoyer',
'send_btn_css_class' => 'Classe(s) CSS du bouton envoyer',
'send_btn_css_class_placeholder' => 'btn btn-primary',
'send_btn_wrapper_css' => 'Classe(s) CSS du wrapper du bouton envoyer',
'send_btn_wrapper_css_placeholder' => 'form-group',
],
'redirect' => [
'allow_redirect' => 'Rediriger après soumission',
'allow_redirect_comment' => 'Rediriger vers une autre page après un envoie réussie',
'redirect_url' => 'URL de la page vers laquelle rediriger',
'redirect_url_comment' => 'Entrez l\'URL de votre page (par exemple, /contact/thank-you)',
'redirect_url_placeholder' => '/contact/thank-you',
'redirect_url_external' => 'URL externe',
'redirect_url_external_comment' => 'Ceci est un chemin d\'URL externe (ex. http://www.domain.com)',
],
'form_fields' => [
'prompt' => 'Ajouter un nouveau champ de formulaire',
'name' => 'Nom du champ',
'name_comment' => 'Minuscules sans caractères spéciaux (ex. nom, email, adresse_personnelle, ...)',
'type' => 'Type de champ',
'label' => 'Étiquette',
'label_placeholder' => 'Nom complet',
'field_styling' => 'Classe CSS personnalisée',
'field_styling_comment' => 'Changer les styles de Bootstrap par défaut',
'autofocus' => 'Champ autofocus',
'autofocus_comment' => 'Autofocus ce champ du formulaire',
'wrapper_css' => 'Classe CSS du wrapper',
'wrapper_css_placeholder' => 'form-group',
'field_css' => 'Classe CSS du champ',
'field_css_placeholder' => 'form-control',
'label_css' => 'Classe CSS de l\'étiquette',
'label_css_placeholder' => '',
'field_validation' => 'Validation du champ',
'field_validation_comment' => 'Ajouter des règles de validation du champ',
'validation' => 'Validation',
'validation_prompt' => 'Ajouter une validation',
'validation_type' => 'Règle de validation',
'validation_error' => 'Message d\'erreur de validation',
'validation_error_placeholder' => 'S\'il vous plaît entrer des données valides.',
'validation_error_comment' => 'Message d\'erreur à utiliser lorsque la validation échoue',
'custom' => 'Champ personnalisé',
'custom_description' => 'Champ personnalisé avec option de validation',
],
'form_field_types' => [
'text' => 'Texte',
'email' => 'Email',
'textarea' => 'Aire de texte',
'checkbox' => 'Case à cocher',
'dropdown' => 'Dropdown',
'file' => 'File',
'custom_code' => 'Custom code',
'custom_content' => 'Custom content',
],
'form_field_validation' => [
'select' => '--- Sélectionnez la validation ---',
'required' => 'Requis',
'email' => 'Email',
'numeric' => 'Numérique',
],
'email' => [
'address_from' => 'Adresse de l\'expéditeur',
'address_from_placeholder' => 'john.doe@domain.com',
'address_from_name' => 'Nom de l\'expéditeur',
'address_from_name_placeholder' => 'John Doe',
'subject' => 'Sujet de l\'e-mail',
'subject_comment' => 'Définissez uniquement si vous souhaitez une définition autre que celle définie dans Paramètres > Modèles des e-mails.',
'template' => 'Modèle e-mail',
'template_comment' => 'Code du modèle e-mail créé dans Paramètres > Modèles des e-mails. Laissez vide pour le modèle par défaut: janvince.smallcontactform::mail.autoreply.',
'allow_email_queue' => 'E-mail en fille d\'attente',
'allow_email_queue_comment' => 'Ajouter un email à la file d\'attente au lieu de l\'envoyer immédiatement. Vous devez d\'abord configurer votre file d\'attente OctoberCMS!',
'allow_notifications' => 'Autoriser les notifications',
'allow_notifications_comment' => 'Envoyer une notification après l\'envoi du formulaire',
'notification_address_to' => 'Envoyer une notification à l\'e-mail',
'notification_address_to_comment' => 'Une adresse électronique ou une liste d\'adresses séparées par des virgules',
'notification_address_to_placeholder' => 'notifications@domain.com',
'notification_address_from_form' => 'Forcer l\'adresse e-mail de la notification (NON PRIS EN CHARGE par tous les systèmes de messagerie!)',
'notification_address_from_form_comment' => 'Définir l\'adresse e-mail entré dans le formulaire de contact comme adresse de l\'expéditeur (le champ doit être défini dans le mappage de colonnes).',
'allow_autoreply' => 'Autoriser une copie à l\'auteur',
'allow_autoreply_comment' => 'Envoyer une copie du contenu du formulaire à l\'auteur',
'autoreply_name_field' => 'Champ du formulaire avec le NOM',
'autoreply_name_field_empty_option' => '-- Sélectionnez --',
'autoreply_name_field_comment' => 'Doit être du type Texte.<br><em>Enregistrez et actualisez cette page si vous ne pouvez pas voir vos champs.</em>',
'autoreply_email_field' => 'Champ du formulaire avec l\'adresse E-MAIL',
'autoreply_email_field_empty_option' => '-- Sélectionnez --',
'autoreply_email_field_comment' => 'Doit être du type email.<br><em>Enregistrez et actualisez cette page si vous ne pouvez pas voir vos champs.</em>',
'autoreply_message_field' => 'Champ du formulaire avec le contenu du MESSAGE',
'autoreply_message_field_empty_option' => '-- Sélectionnez --',
'autoreply_message_field_comment' => 'Doit être du type Aire de texte ou Texte.<br><em>Enregistrez et actualisez cette page si vous ne pouvez pas voir vos champs.</em>',
'notification_template' => 'Modèle e-mail de la notification',
'notification_template_comment' => 'Code du modèle de courrier électronique créé dans Paramètres > Modèless des e-mails. Laisser vide pour le modèle par défaut : janvince.smallcontactform::mail.autoreply.',
],
'antispam' => [
'add_antispam' => 'Ajouter une protection antispam passive',
'add_antispam_comment' => 'Ajouter un contrôle antispam passif simple mais efficace (plus dinformations dans le fichier README.md - en anglais)',
'antispam_delay' => 'Délai Antispam (en secondes)',
'antispam_delay_comment' => 'Protection différée pour l\'envoi de formulaires trop rapide (généralement par des robots)',
'antispam_delay_placeholder' => '3',
'antispam_label' => 'Étiquette de champ antispam',
'antispam_label_comment' => 'L\'étiquette sera visible pour les navigateurs non activés par JavaScript',
'antispam_label_placeholder' => 'Veuillez effacer ce champ',
'antispam_error_msg' => 'Message d\'erreur',
'antispam_error_msg_comment' => 'Message à afficher à l\'utilisateur lorsque la protection antispam est déclenchée',
'antispam_error_msg_placeholder' => 'Veuillez vider ce champ!',
'antispam_delay_error_msg' => 'Message d\'erreur de délai',
'antispam_delay_error_msg_comment' => 'Message à montrer à l\'utilisateur lorsque le formulaire a été envoyé trop rapidement',
'antispam_delay_error_msg_placeholder' => 'Formulaire envoyé trop vite! S\'il vous plaît attendre quelques secondes et essayez à nouveau!',
'add_google_recaptcha' => 'Ajouter Google reCaptcha',
'add_google_recaptcha_comment' => 'Ajoutez reCaptcha au formulaire de contact (plus d\informations dans le fichier README.md - en anglais). <br> Vous pouvez obtenir les clés dAPI sur le <a href="https://www.google.com/recaptcha/admin#list" target="_blank">Google reCaptcha</a>.',
'google_recaptcha_site_key' => 'Clé du site',
'google_recaptcha_site_key_comment' => 'Mettez votre clé du site',
'google_recaptcha_secret_key' => 'Clé secrète',
'google_recaptcha_secret_key_comment' => 'Mettez votre clé secrète',
'google_recaptcha_error_msg' => 'Message d\'erreur',
'google_recaptcha_error_msg_comment' => 'Message à afficher à l\'utilisateur lorsque le reCAPTCHA n\'est pas validé.',
'google_recaptcha_error_msg_placeholder' => 'Erreur de validation du reCAPTCHA de Google!',
'google_recaptcha_scripts_allow' => 'Ajouter automatiquement les scripts JS nécessaires',
'google_recaptcha_scripts_allow_comment' => 'Cela ajoutera un lien vers les scripts JS sur votre site.',
'google_recaptcha_locale_allow' => 'Autoriser la détection des paramètres de langues',
'google_recaptcha_locale_allow_comment' => 'Cela ajoutera les paramètres de langues actuels de la page Web au script reCAPTCHA, de sorte qu\'il sera traduit.',
'add_ip_protection' => 'Vérifier l\'adresse IP de l\'expéditeur',
'add_ip_protection_comment' => 'Ne pas autoriser trop de formulaires soumis à partir d\'une même adresse IP',
'add_ip_protection_count' => 'Formulaire maximum soumis au cours d\'une journée',
'add_ip_protection_count_comment' => 'Nombre de soumissions autorisées à partir d\'une même adresse IP au cours d\'une seule journée',
'add_ip_protection_count_placeholder' => '3',
'add_ip_protection_error_get_ip' => 'Nous n\'avons pas pu déterminer votre adresse IP!',
'add_ip_protection_error_too_many_submits' => 'Message d\'erreur lorsque trop de messages sont envoyés',
'add_ip_protection_error_too_many_submits_comment' => 'Message d\'erreur à montrer à l\'utilisateur',
'add_ip_protection_error_too_many_submits_placeholder' => 'Trop de messages ont été envoyés par votre adresse aujourd\'hui!',
'disabled_extensions' => 'Extensions désactivées',
'disabled_extensions_comment' => 'Les paramètres définis dans l\'onglet Confidentialité ont désactivé ces extensions.',
],
'mapping' => [
'hint' => [
'title' => 'Pourquoi le mappage des champs?',
'content' => '
<p>Vous pouvez créer un formulaire personnalisé avec vos propres noms et types de champs.</p>
<p>Le système écrit toutes les données de formulaire dans la base de données, mais pour une présentation rapide, les colonnes Nom, E-mail et Message sont visibles séparément dans la listedes messages.</p>
<p>Vous devez donc aider le système à identifier ces colonnes en les associant à vos champs de formulaire.</p>
<p><em>Ces mappages sont également utilisés pour les e-mails à réponse automatique dans lesquels au moins le mappage du champ e-mail est important.</em></p>
',
],
'warning' => [
'title' => 'Vous ne pouvez pas sélectionner vos champs de formulaire?',
'content' => '
<p>Si vous ne voyez pas vos champs de formulaire, cliquez sur le bouton Enregistrer en bas de cette page, puis rechargez la page (F5 ou Ctrl+R / Cmd+R).</p>
',
],
],
'privacy' => [
'disable_messages_saving' => 'Désactiver l\'enregistrement des messages',
'disable_messages_saving_comment' => 'Lorsque cette case est cochée, aucune donnée ne sera enregistrée dans la liste de messages.<br><strong>La protection IP sera également désactivée!</strong>',
'disable_messages_saving_comment_section' => '<div class="callout fade in callout-danger no-subheader"><div class="header"><i class="icon-warning"></i><h3>Assurez-vous d\'autoriser les courriels de notification, sinon vous ne recevrez aucune donnée des formulaires envoyés!</h3></div></div>',
],
'tabs' => [
'form' => 'Formulaire',
'buttons' => 'Bouton envoyer',
'form_fields' => 'Champs',
'mapping' => 'Mappage des colonnes',
'email' => 'E-mail',
'antispam' => 'Antispam',
'privacy' => 'Confidentialité'
],
],
'components' => [
'groups' => [
'hacks' => 'Hacks',
],
'properties' => [
'disable_notifications' => 'Désactiver les e-mails de notification',
'disable_notifications_comment' => 'Ceci désactivera les courriels de notification (remplace les paramètres du formulaire)',
'form_description' => 'Description du formulaire',
'form_description_comment' => 'Vous pouvez ajouter une description de formulaire facultative, qui sera enregistrée avec les autres données envoyées dans la liste de messages. Vous pouvez également utiliser {{:slug}} ici.',
]
],
];

View File

@ -0,0 +1,146 @@
<?php
return [
'plugin' => [
'name' => 'Kapcsolat űrlap',
'description' => 'Űrlap generálása kapcsolat felvételhez.',
'category' => 'Small plugins',
],
'permissions' => [
'access_messages' => 'Üzenetek megtekintése',
'access_settings' => 'Beállítások módosítása',
'delete_messages' => 'Üzenetek törlése',
'export_messages' => 'Üzenetek exportálása',
],
'navigation' => [
'main_label' => 'Kapcsolat űrlap',
'messages' => 'Üzenetek',
],
'controller' => [
'contact_form' => [
'name' => 'Kapcsolat űrlap',
'description' => 'Űrlap generálása kapcsolat felvételhez.',
'no_fields' => 'Elsőként hozzon létre legalább egy mezőt itt: Beállítások > Small plugins > Kapcsolat űrlap > Fields',
],
'filter' => [
'date' => 'Időintervallum',
],
'scoreboard' => [
'records_count' => 'Üzenetek',
'latest_record' => 'Legutóbbi',
'new_count' => 'Új levél',
'new_description' => 'üzenet',
'read_count' => 'Olvasott',
'all_count' => 'Összes',
'all_description' => 'üzenet',
'settings_btn' => 'Testreszabás',
'mark_read' => 'Olvasottnak jelöl',
'mark_read_confirm' => 'Valóban olvasottnak szeretné jelölni az üzeneteket?',
'mark_read_success' => 'Az üzenetek sikeresen olvasottnak lettek jelölve.',
],
'preview' => [
'record_not_found' => 'Üzenet nem található!',
],
],
'models' => [
'message' => [
'columns' => [
'id' => 'ID',
'datetime' => 'Elküldve',
'form_data' => 'Adatok',
'name' => 'Név',
'email' => 'Email',
'message' => 'Üzenet',
'new_message' => 'Státusz',
'new' => 'Új levél',
'read' => 'Olvasott',
'remote_ip' => 'IP cím',
'form_alias' => 'Űrlap',
'form_description' => 'Leírás',
'created_at' => 'Létrehozva',
'updated_at' => 'Módosítva',
],
],
],
'controllers' => [
'messages' => [
'list_title' => 'Üzenetek',
'preview' => 'Előnézet',
'preview_title' => 'Üzenet',
'preview_date' => 'Elküldve:',
'preview_content_title' => 'Tartalom:',
'remote_ip' => 'IP cím',
'export' => 'Exportálás',
],
'index' => [
'unauthorized' => 'Illetéktelen hozzáférés',
],
],
'mail' => [
'templates' => [
'autoreply' => 'Automatikus üzenet (angol)',
'autoreply_cs' => 'Automatikus üzenet (cseh)',
'notification' => 'Értesítő üzenet (angol)',
'notification_cs' => 'Értesítő üzenet (cseh)',
]
],
'reportwidget' => [
'partials' => [
'messages' => [
'label' => 'Kapcsolat űrlap - Statisztika',
'title' => 'Üzenet statisztika',
'messages_all' => 'Összes',
'messages_new' => 'Új levél',
'messages_read' => 'Olvasott',
],
'new_message' => [
'label' => 'Kapcsolat űrlap - Új üzenetek',
'title' => 'Új üzenetek',
'link_text' => 'Összes üzenet megtekintése',
],
],
],
'components' => [
'groups' => [
'hacks' => 'Hackelés',
],
'properties' => [
'disable_notifications' => 'Értesítő e-mailek letiltása',
'disable_notifications_comment' => 'Felül fogja írni az űrlap központi beállítását erre vonatkozóan.',
'form_description' => 'Űrlap leírás',
'form_description_comment' => 'Amennyiben megad adatot, azok mentésre kerülnek az űrlap beküldésekor. Például az aktuális oldal címének megjegyzéséhez használhatja a {{ :slug }} kódot.',
],
],
];

View File

@ -0,0 +1,436 @@
<?php
return [
'plugin' => [
'name' => 'Formularz kontaktowy',
'description' => 'Kreator prostego formularza kontaktowego',
'category' => 'Small plugins',
],
'permissions' => [
'access_messages' => 'Przeglądaj wiadomości',
'access_settings' => 'Zarządzaj ustawieniami',
'delete_messages' => 'Usuwaj zapisane wiadomości',
'export_messages' => 'Eksportuj wiadomości',
],
'navigation' => [
'main_label' => 'Formularz kontaktowy',
'messages' => 'Wiadomości',
],
'controller' => [
'contact_form' => [
'name' => 'Formularz kontaktowy',
'description' => 'Dodaj formularz kontaktowy do strony',
'no_fields' => 'Najpierw dodaj pola formularza w panelu administracyjnym (Ustawienia -> Small plugins -> Formularz kontktowy)...',
],
'filter' => [
'date' => 'Zakres dat',
],
'scoreboard' => [
'records_count' => 'Wiadomości',
'latest_record' => 'Ostatnia wiadomość od',
'new_count' => 'Nowe',
'new_description' => 'Wiadomości',
'read_count' => 'Przeczytane',
'all_count' => 'Wszystkie',
'all_description' => 'Wiadomości',
'settings_btn' => 'Ustawienia formularza',
'mark_read' => 'Oznacz jako przeczytane',
'mark_read_confirm' => 'Czy na pewno oznaczyć wybrane wiadomości jako przeczytane?',
'mark_read_success' => 'Oznaczono jako przeczytane.',
],
'preview' => [
'record_not_found' => 'Nie znaleziono wiadomości!',
],
],
'models' => [
'message' => [
'columns' => [
'id' => 'ID',
'datetime' => 'Data i godzina',
'form_data' => 'Dane formularza',
'name' => 'Imię i nazwisko',
'email' => 'Email',
'message' => 'Wiadomość',
'new_message' => 'Status',
'new' => 'Nowa',
'read' => 'Przeczytana',
'remote_ip' => 'Adres IP wysyłającego',
'form_alias' => 'Alias',
'form_description' => 'Opis',
'created_at' => 'Utworzono',
'updated_at' => 'Zaktualizowano',
]
],
],
'controllers' => [
'messages' => [
'list_title' => 'Wiadomości',
'preview' => 'Podgląd',
'preview_title' => 'Wiadomość z formularza kontaktowego',
'preview_date' => 'Data otrzymania:',
'preview_content_title' => 'Zawartość:',
'remote_ip' => 'Wysłano z adresu IP',
'export' => 'Eksportuj',
],
'index' => [
'unauthorized' => 'Nie masz uprawnień aby wyświetlić tą stroną',
],
],
'mail' => [
'templates' => [
'autoreply' => 'Wiadomość automatycznej odpowiedzi (Angielski)',
'autoreply_cs' => 'Wiadomość automatycznej odpowiedzi (Czeski)',
'notification' => 'Wiadomość powiadamiająca (Angielski)',
'notification_cs' => 'Wiadomość powiadamiająca (Czeski)',
]
],
'reportwidget' => [
'partials' => [
'messages' => [
'label' => 'Formularz kontaktowy - Statystyki wiadomości',
'title' => 'Statystyki wiadomości',
'messages_all' => 'Wszystkie',
'messages_new' => 'Nowe',
'messages_read' => 'Przeczytane',
],
'new_message' => [
'label' => 'Formularz Kontaktowy - Nowe wiadomości',
'title' => 'Nowe wiadomości',
'link_text' => 'Kliknij, aby pokazać listę wiadomości',
],
],
],
'settings' => [
'form' => [
'css_class' => 'Klasa CSS formularza',
'use_placeholders' => 'Użyj tekstów zastępczych (Placeholder)',
'use_placeholders_comment' => 'Teksty zastępcze będą wyświetlane zamiast etykiet pól. (Etykiety otrzymają styl display: none)',
'disable_browser_validation' => 'Wyłącz domyślną walidację przeglądarki',
'disable_browser_validation_comment' => 'Nie zezwalaj na wbudowane w przeglądarkę sprawdzanie poprawności i wyskakujące okienka.',
'success_msg' => 'Wiadomość o poprawnym wysłaniu formularza',
'success_msg_placeholder' => 'Twoja wiadomość została wysłana.',
'error_msg' => 'Wiadomość o niepoprawnym wysłaniu formularza',
'error_msg_placeholder' => 'Wystąpił błąd podczas wysyłania Twojej wiadomości!',
'allow_ajax' => 'Włącz AJAX',
'allow_ajax_comment' => 'Zezwól na asynchroniczny formularz AJAX razem ze wsparciem dla przeglądarek nieobsługujących JavaScript.',
'allow_confirm_msg' => 'Zapytaj o potwierdzenie przed wysłaniem formularza',
'allow_confirm_msg_comment' => 'Dodaje okno dialogowe potwierdzenia przed wysłaniem',
'send_confirm_msg' => 'Tekst potwierdzenia',
'send_confirm_msg_placeholder' => 'Czy jesteś pewny?',
'hide_after_success' => 'Ukryj formularz po pomyślnym wysłaniu',
'hide_after_success_comment' => 'Pokaż tylko wiadomość o pomyślnym wysłaniu wiadomości bez formularza',
'add_assets' => 'Dodaj pliki',
'add_assets_comment' => 'Automatycznie dodaje niezbędne pliki CSS i JS (więcej na ten temat w pliku README.md)',
'add_css_assets' => 'Dodaj pliki CSS',
'add_css_assets_comment' => 'Dodaje wszystkie niezbędne pliki CSS',
'add_js_assets' => 'Dodaj pliki JS',
'add_js_assets_comment' => 'Dodaje wszystkie niezbędne pliki JS',
],
'buttons' => [
'send_btn_text' => 'Tekst przycisku wyślij',
'send_btn_text_placeholder' => 'Wyślij',
'send_btn_css_class' => 'Klasa CSS przycisku wyślij',
'send_btn_css_class_placeholder' => 'btn btn-primary',
'send_btn_wrapper_css' => 'Klasa CSS kontenera przycisku wyślij',
'send_btn_wrapper_css_placeholder' => 'form-group',
],
'redirect' => [
'allow_redirect' => 'Przekieruj po wysłaniu',
'allow_redirect_comment' => 'Przekierowuje na inną stronę po wysłaniu formularza',
'redirect_url' => 'Adres URL strony przekierowania',
'redirect_url_comment' => 'Wprowadź adres URL strony (np. /contact/thank-you)',
'redirect_url_placeholder' => '/contact/thank-you',
'redirect_url_external' => 'Zewnętrzny adres URL',
'redirect_url_external_comment' => 'Ten adres URL wskazuje na zewnętrzną domenę (np. http://www.domain.com)',
],
'form_fields' => [
'prompt' => 'Dodaj nowe pole formularza',
'name' => 'NAZWA POLA',
'name_comment' => 'Małe litery bez znaków specjalnych (np. name, email, home_address, ...)',
'type' => 'Rodzaj pola',
'label' => 'Etykieta',
'label_placeholder' => 'Imię i nazwisko',
'field_styling' => 'Niestandardowa klasa CSS',
'field_styling_comment' => 'Zmień domyślne style (Bootstrap)',
'autofocus' => 'Automatyczny fokus',
'autofocus_comment' => 'Automatycznie ustaw fokus na to pole',
'wrapper_css' => 'Klasa CSS kontenera',
'wrapper_css_placeholder' => 'form-group',
'field_css' => 'Klasa CSS pola',
'field_css_placeholder' => 'form-control',
'label_css' => 'Klasa CSS etykiety',
'label_css_placeholder' => 'control-label',
'field_validation' => 'Walidacja',
'field_validation_comment' => 'Dodaj reguły walidacji',
'validation' => 'Walidacja',
'validation_prompt' => 'Dodaj regułę walidacji',
'validation_type' => 'Reguła walidacji',
'validation_error' => 'Komunikat błędu walidacji',
'validation_error_placeholder' => 'Wprowadź poprawne dane.',
'validation_error_comment' => 'Komunikat wyświetlany, gdy pole nie przejdzie walidacji',
'validation_custom_type' => 'Validation rule name',
'validation_custom_type_comment' => 'Wprowadź nazwę reguły walidatora (eg. regex, boolean, ...).<br>See <a href="https://octobercms.com/docs/services/validation#available-validation-rules" target="_blank">reguły walidacji</a>.',
'validation_custom_type_placeholder' => 'regex',
'validation_custom_pattern' => 'Wzorzec reguły walidacji',
'validation_custom_pattern_comment' => 'Pozostaw puste lub wprowadź niestandardowy wzorzec reguły (prawa część reguły znajdująca się po dwukropku - np. [abc] dla reguły regex)',
'validation_custom_pattern_placeholder' => "/^[0-9]+$/",
'custom' => 'Pole niestandardowe',
'custom_description' => 'Niestandardowe pole z opcją walidacji',
'add_values_prompt' => 'Dodaj opcje',
'field_value_id' => 'Identyfikator opcji',
'field_value_content' => 'Tekst opcji',
],
'form_field_types' => [
'text' => 'Tekst',
'email' => 'Email',
'textarea' => 'Pole tekstowy',
'checkbox' => 'Pole wyboru',
'dropdown' => 'Lista rozwijalna',
'file' => 'File',
'custom_code' => 'Custom code',
'custom_content' => 'Custom content',
],
'form_field_validation' => [
'select' => '--- Wybierz regułę walidacji ---',
'required' => 'Wymagane',
'email' => 'Email',
'numeric' => 'Numeryczne',
'custom' => 'Reguła niestandardowa',
],
'email' => [
'address_from' => 'Z adresu',
'address_from_placeholder' => 'example@domain.com',
'address_from_name' => 'Nazwa wyświetlana w polu "Od"',
'address_from_name_placeholder' => 'Jan Nowak',
'subject' => 'Temat wiadomości',
'subject_comment' => 'Ustaw tylko wtedy, gdy chcesz aby był inny niż zdefiniowano w Ustawienia > Mail > Szablony wiadomości email',
'template' => 'Szablon wiadomości',
'template_comment' => 'Kod szablonu wiadomości email utworzony w Ustawienia > Mail > Szablony wiadomości email. Pozostaw puste dla domyślnego szablonu: janvince.smallcontactform::mail.autoreply.',
'allow_email_queue' => 'Kolejkowanie wiadomości',
'allow_email_queue_comment' => 'Dodawaj wiadomości do kolejki zamiast wysyłać je natychmiastowo. Pamiętaj, najpierw musisz skonfigurować kolejkę OctoberCMS!',
'allow_notifications' => 'Wysyłaj powiadomienia',
'allow_notifications_comment' => 'Wyślij powiadomienie zaraz po wysłaniu formularza',
'notification_address_to' => 'Wyślij powiadomienie na adres/adresy',
'notification_address_to_comment' => 'Jeden adres email, lub lista oddzielona przecinkami',
'notification_address_to_placeholder' => 'notifications@domain.com',
'notification_address_from_form' => 'Wymuś zawartość pola "Od" powiadomienia (NIE WSPIERANE przez wszystkie systemy email)',
'notification_address_from_form_comment' => 'Ustaw adres, z którego wysyłane jest powiadomienie na adres email podany w formularzu kontaktowym (pole musi być ustawione w odwzorowaniu pól).',
'allow_autoreply' => 'Automatyczna odpowiedź',
'allow_autoreply_comment' => 'Wyślij kopię wiadomości do autora',
'autoreply_name_field' => 'Pole NAZWA',
'autoreply_name_field_empty_option' => '-- Wybierz --',
'autoreply_name_field_comment' => 'Musi być typu Tekst.<br><em>Zapisz i odśwież tą stronę jeśli nie widzisz pól.</em>',
'autoreply_email_field' => 'Pole EMAIL',
'autoreply_email_field_empty_option' => '-- Wybierz --',
'autoreply_email_field_comment' => 'Musi być typu Email.<br><em>Zapisz i odśwież tą stronę jeśli nie widzisz pól.</em>',
'autoreply_message_field' => 'Pole WIADOMOŚĆ',
'autoreply_message_field_empty_option' => '-- Wybierz --',
'autoreply_message_field_comment' => 'Musi być typu Pole tekstowe lub Tekst.<br><em>Zapisz i odśwież tą stronę jeśli nie widzisz pól.</em>',
'notification_template' => 'Szablon wiadomości powiadomienia',
'notification_template_comment' => 'Kod szablonu wiadomości email utworzony w Ustawienia > Mail > Szablony wiadomości email. Pozostaw puste dla domyślnego szablonu: janvince.smallcontactform::mail.notification.',
],
'antispam' => [
'add_antispam' => 'Dodaj pasywną ochronę antyspamową',
'add_antispam_comment' => 'Dodaj prostą, ale skuteczną pasywną kontrolę antyspamową (więcej informacji w pliku README.md)',
'antispam_delay' => 'Opóźnienie ochrony antyspamowej (s)',
'antispam_delay_comment' => 'Zabezpieczenia w postaci opóźnienia podczas wysyłania dużej ilości wiadomości (zwykle przez roboty)',
'antispam_delay_placeholder' => '3',
'antispam_label' => 'Etykieta pola ochrony antyspamowej',
'antispam_label_comment' => 'Etykieta będzie widoczna tylko dla przeglądarek, które nie obsługują JavaScript',
'antispam_label_placeholder' => 'Wyczyść to pole w celu wysłania wiadomości',
'antispam_error_msg' => 'Komunikat o błędzie - ochrona antyspamowa',
'antispam_error_msg_comment' => 'Komunikat, który zostanie wyświetlony, gdy uruchomi się ochrona antyspamowa',
'antispam_error_msg_placeholder' => 'Musisz wyczyścić to pole, aby wysłać wiadomość!',
'antispam_delay_error_msg' => 'Komunikat o błędzie - opóźnienie',
'antispam_delay_error_msg_comment' => 'Komunikat, który zostanie wyświetlony, gdy użytkownik wyśle wiadomość zbyt szybko',
'antispam_delay_error_msg_placeholder' => 'Wiadomość wysłana zbyt szybko! Poczekaj chwilę, a następnie spróbuj ponownie.',
'add_google_recaptcha' => 'Dodaj Google reCaptcha',
'add_google_recaptcha_comment' => 'Dodaj reCaptcha do formularza kontaktowego (więcej informacji w pliku README.md).<br>Możesz uzyskać klucze API na <a href="https://www.google.com/recaptcha/admin#list" target="_blank">stronie Google reCaptcha</a>.',
'google_recaptcha_site_key' => 'Klucz strony',
'google_recaptcha_site_key_comment' => 'Wpisz swój kod strony',
'google_recaptcha_secret_key' => 'Sekretny klucz',
'google_recaptcha_secret_key_comment' => 'Wpisz swój sekretny klucz',
'google_recaptcha_wrapper_css' => 'Klasa CSS kontenera reCaptcha',
'google_recaptcha_wrapper_css_comment' => 'Klasa CSS kontenera wokół pola reCaptcha',
'google_recaptcha_wrapper_css_placeholder' => 'form-group',
'google_recaptcha_error_msg' => 'Komunikat błędu',
'google_recaptcha_error_msg_comment' => 'Komunikat, który pokaże się, gdy reCAPTCHA zwróci błąd.',
'google_recaptcha_error_msg_placeholder' => 'Google reCAPTCHA validation error!',
'google_recaptcha_scripts_allow' => 'Automatycznie dodaj niezbędne skrypt JS',
'google_recaptcha_scripts_allow_comment' => 'Dodaj skrypty JS do twojej strony',
'google_recaptcha_locale_allow' => 'Zezwól na wykrywanie ustawień regionalnych',
'google_recaptcha_locale_allow_comment' => 'Spowoduje to dodanie bieżących ustawień regionalnych do skryptu reCAPTCHA, tak że będzie ona przetłumaczona.',
'add_ip_protection' => 'Sprawdzaj adres IP wysyłającego',
'add_ip_protection_comment' => 'Nie zezwalaj na zbyt dużo wiadomości z jednego adresu IP',
'add_ip_protection_count' => 'Maksymalna liczba wiadomości na dzień',
'add_ip_protection_count_comment' => 'Maksymalna liczba wiadomości możliwa do wysłania z jednego adresu IP na dzień',
'add_ip_protection_count_placeholder' => '3',
'add_ip_protection_error_get_ip' => 'Nie udało się ustalić Twojego adresu IP',
'add_ip_protection_error_too_many_submits' => 'Komunikat błędu - za dużo wiadomości',
'add_ip_protection_error_too_many_submits_comment' => 'Komunikat, który zostanie pokazany użytkownikowi',
'add_ip_protection_error_too_many_submits_placeholder' => 'Otrzymaliśmy dzisiaj zbyt wiele wiadomości z jednego adresu IP. Spróbuj ponownie jutro.',
'disabled_extensions' => 'Wyłączone rozszerzenia',
'disabled_extensions_comment' => 'Ustawienia na zakładce Prywatność wyłączyły te rozszerzenia',
],
'mapping' => [
'hint' => [
'title' => 'Dlaczego odwzorowywanie pól?',
'content' => '
<p>Możesz zbudować niestandardowy formularz z własnymi nazwami i typami pól.</p>
<p>System zapisuje wszystkie dane formularze w bazie danych. W celu szybkiego podglądu kolumny NAZWA, EMAIL i WIADOMOŚĆ widoczne osobno na liście wiadomości.</p>
<p>Musisz więc pomóc systemowi w identyfikacji tych kolumn poprzez odwzorowanie pól formularza.</p>
<p><em>Odwzorowania również używane przez system automatycznej odpowiedzi na wiadomości, w których ważne jest przynajmniej pole EMAIL.</em></p>
',
],
'warning' => [
'title' => 'Nie możesz wybrać pól?',
'content' => '<p>Jeśli nie widzisz pól formularza wciśnij przycisk zapisz na dole strony a następnie odśwież stronę (F5 lub Ctrl + R / Cmd + R)</p>',
],
],
'privacy' => [
'disable_messages_saving' => 'Wyłącz zapisywanie wiadomości',
'disable_messages_saving_comment' => 'Żadne dane nie zostaną zapisane w liście wiadomości. <strong>To ustawienie wyłączy również ochronę na podstawie adresu IP!</strong>',
'disable_messages_saving_comment_section' => '<div class="callout fade in callout-danger no-subheader"><div class="header"><i class="icon-warning"></i><h3>Pamiętaj, aby włączyć powiadomienia email! W przeciwnym wypadku nie otrzymasz żadnych danych z formularza.</h3></div></div>',
],
'tabs' => [
'form' => 'Formularz',
'buttons' => 'Przycisk wyślij',
'form_fields' => 'Pola',
'mapping' => 'Odwzorowanie pól',
'email' => 'Email',
'antispam' => 'Ochrona antyspamowa',
'privacy' => 'Prywatność'
],
],
'components' => [
'groups' => [
'hacks' => 'Hacki',
],
'properties' => [
'disable_notifications' => 'Wyłącz powiadomienia e-mail',
'disable_notifications_comment' => 'Spowoduje wyłączenie powiadomień e-mail (nadpisuje ustawienia globalne)',
'form_description' => 'Opis formularza',
'form_description_comment' => 'Możesz dodać opcjonalny opis formularza, który zostanie zapisany wraz z danymi wysłanymi przez formularz. Może także użyć {{ :slug }}.',
]
],
];

View File

@ -0,0 +1,322 @@
<?php
return [
'plugin' => [
'name' => 'Контактная форма',
'description' => 'Простой конструктор контактной формы',
],
'permissions' => [
'access_messages' => 'Доступ к списку сообщений',
'access_settings' => 'Управление настройками бэкенд',
'delete_messages' => 'Удалить сохраненные сообщения',
],
'navigation' => [
'main_label' => 'Контакт форма',
'messages' => 'Сообщения',
],
'controller' => [
'contact_form' => [
'name' => 'Контактная форма',
'description' => 'Вставьте контактную форму на страницу',
'no_fields' => 'Для работы плагина следует добавить поля формы в бэкенд (Настройки > Контактная форма > Поля)...',
],
'filter' => [
'date' => 'Диапазон дат',
],
'scoreboard' => [
'records_count' => 'Сообщения',
'latest_record' => 'Последнее от',
'new_count' => 'Новые',
'new_description' => 'Сообщения',
'read_count' => 'Прочитанные',
'all_count' => 'Всего',
'all_description' => 'Сообщения',
'settings_btn' => 'Настройки формы',
'mark_read' => 'Отметить как прочитанное',
'mark_read_confirm' => 'Вы действительно хотите отметить выбранные сообщения как прочитанные?',
'mark_read_success' => 'Успешно отмечено как прочитанное',
],
'preview' => [
'record_not_found' => 'Сообщение не найдено!',
],
],
'models' => [
'message' => [
'columns' => [
'datetime' => 'Дата и время',
'form_data' => 'Данные формы',
'name' => 'Имя',
'message' => 'Сообщение',
'new_message' => 'Статус',
'new' => 'Новое',
'read' => 'Прочитанное',
'remote_ip' => 'IP отправителя',
'form_alias' => 'Псевдоним',
'form_description' => 'Описание',
]
],
],
'controllers' => [
'messages' => [
'list_title' => 'Сообщения',
'preview' => 'Предварительный просмотр',
'preview_title' => 'Сообщение контактной формы',
'preview_date' => 'От даты:',
'preview_content_title' => 'Содержание:',
'remote_ip' => 'Отправлено с IP',
],
'index' => [
'unauthorized' => 'Несанкционированный доступ',
],
],
'reportwidget' => [
'partials' => [
'messages' => [
'label' => 'Контактная форма - Статистика сообщений',
'title' => 'Статистика сообщений',
'messages_all' => 'Все',
'messages_new' => 'Новые',
'messages_read' => 'Прочитанные',
],
'new_message' => [
'label' => 'Контактная форма - Новое сообщение',
'title' => 'Новое сообщение',
'link_text' => 'Нажмите, чтобы показать список сообщений',
],
],
],
'settings' => [
'form' => [
'css_class' => 'CSS классы формы',
'use_placeholders' => 'Использовать заполнители формы',
'use_placeholders_comment' => 'Будет скрыт <label>, а текст метки будет показан внутри поля.',
'disable_browser_validation' => 'Отключить валидацию браузера',
'disable_browser_validation_comment' => 'Запретить встроенные проверки и всплывающие окна браузера.',
'success_msg' => 'Текст сообщения об успешной отправке',
'success_msg_placeholder' => 'Ваше сообщение доставлено',
'error_msg' => 'Текст сообщения о ошибке',
'error_msg_placeholder' => 'При отправке сообщения произошла ошибка',
'allow_ajax' => 'Включить AJAX',
'allow_ajax_comment' => 'Разрешить AJAX с откатом для браузеров без JavaScript.',
'allow_confirm_msg' => 'Запрашивать подтверждение перед отправкой формы',
'allow_confirm_msg_comment' => 'Добавить текст диалога перед отправкой.',
'send_confirm_msg' => 'Текст подтверждения',
'send_confirm_msg_placeholder' => 'Отправить сообщение?',
'hide_after_success' => 'Скрыть форму после успешной отправки',
'hide_after_success_comment' => 'Показать только сообщение об успешной отправке.',
],
'buttons' => [
'send_btn_text' => 'Текст на кнопке',
'send_btn_text_placeholder' => 'Отправить',
'send_btn_css_class' => 'CSS классы кнопки',
'send_btn_wrapper_css' => 'CSS классы обертки (wrapper) кнопки',
],
'redirect' => [
'allow_redirect' => 'Редирект после отправки',
'allow_redirect_comment' => 'Перенаправить пользователя на другую страницу после успешного отправки формы.',
'redirect_url' => 'URL страницы для перенаправления',
'redirect_url_comment' => 'Введите URL-адрес страницы (например: /contact/thank-you)',
'redirect_url_external' => 'Внешний URL',
'redirect_url_external_comment' => 'Отметьте, если это внешний адрес (например: http://www.domain.com).',
],
'form_fields' => [
'prompt' => 'Добавить новое поле формы',
'name' => 'ИМЯ ПОЛЯ',
'name_comment' => 'Нижний регистр без специальных символов (например: name, email, home_address, ...).',
'type' => 'Тип поля',
'label' => 'Метка поля',
'label_placeholder' => 'Ваше имя',
'field_styling' => 'Пользовательские CSS классы',
'field_styling_comment' => 'Изменение стандартных Bootstrap стилей.',
'autofocus' => 'Автофокус',
'autofocus_comment' => 'Автофокусировка на этом поле формы.',
'wrapper_css' => 'CSS классы обертки (wrapper)',
'field_css' => 'CSS классы полей <input>',
'label_css' => 'CSS классы метки <label>',
'label_css_placeholder' => '',
'field_validation' => 'Валидация поля',
'field_validation_comment' => 'Добавить правила для проверки поля.',
'validation' => 'Валидация',
'validation_prompt' => 'Добавить валидацию',
'validation_error' => 'Сообщение при ошибке валидации',
'validation_error_placeholder' => 'Данные введены не верно',
'validation_error_comment' => 'Сообщение об ошибке, если валидация не пройдена.',
],
'email' => [
'address_from' => 'От адреса',
'address_from_name' => 'От имени',
'subject' => 'Тема письма',
'subject_comment' => 'Установите если хотите использовать отличное от шаблона, Настройки > Шаблоны почты.',
'template' => 'Шаблон почты',
'template_comment' => 'Код шаблона почты, созданный в Настройки > Шаблоны почты. Если оставить пустым будет использован по умолчанию: janvince.smallcontactform::mail.autoreply.',
'allow_notifications' => 'Разрешить уведомления',
'allow_notifications_comment' => 'Отправлять уведомление на email после отправки формы.',
'notification_address_to' => 'Отправить уведомление на email',
'allow_autoreply' => 'Автоматический ответ',
'allow_autoreply_comment' => 'Отправлять копию содержимого формы автору.',
'autoreply_name_field' => 'Поле формы NAME',
'autoreply_name_field_comment' => 'Должен быть тип поля: Text.<br><em>Сохраните и обновите эту страницу, если вы не видите свои поля.</em>',
'autoreply_email_field' => 'Поле формы EMAIL',
'autoreply_email_field_comment' => 'Должен быть тип поля: Email.<br><em>Сохраните и обновите эту страницу, если вы не видите свои поля.</em>',
'autoreply_message_field' => 'Поле формы MESSAGE',
'autoreply_message_field_comment' => 'Должен быть тип поля: Textarea или Text.<br><em>Сохраните и обновите эту страницу, если вы не видите свои поля.</em>',
'notification_template' => 'Шаблон почты для уведомления',
'notification_template_comment' => 'Код шаблона почты, созданный в Настройки > Шаблоны почты. Если оставить пустым будет использован по умолчанию: janvince.smallcontactform::mail.autoreply.',
],
'antispam' => [
'add_antispam' => 'Добавить пассивную антиспам защиту',
'add_antispam_comment' => 'Простая, но эффективная антиспам защита (подробнее в README.md файле).',
'antispam_delay' => 'Антиспам задержка в секундах',
'antispam_delay_comment' => 'Защищает от слишком быстрой отправки формы (против роботов).',
'antispam_delay_placeholder' => '3',
'antispam_label' => 'Метка поля антиспама',
'antispam_label_comment' => 'Будет отображаться в браузерах с выключенным JavaScript.',
'antispam_label_placeholder' => 'Пожалуйста очистите это поле',
'antispam_error_msg' => 'Текст сообщения при ошибке',
'antispam_error_msg_comment' => 'Сообщение будет показано пользователю, при срабатывании защиты от спама',
'antispam_error_msg_placeholder' => 'Антиспам - Пожалуйста очистите это поле!',
'antispam_delay_error_msg' => 'Текст сообщения при ошибке',
'antispam_delay_error_msg_comment' => 'Сообщение для пользователя, чтобы показать, что форма была отправлена слишком быстро.',
'antispam_delay_error_msg_placeholder' => 'Форма отправлена слишком быстро, пожалуйста подождите 5 секунд.',
'add_google_recaptcha' => 'Добавить Google reCaptcha',
'add_google_recaptcha_comment' => 'Добавить reCaptcha в контактную форму (подробнее в README.md файле).<br>Вы можете получить API ключ на <a href="https://www.google.com/recaptcha/admin#list" target="_blank">Google reCaptcha site</a>.',
'google_recaptcha_site_key_comment' => 'Введите ключ своего сайта',
'google_recaptcha_secret_key_comment' => 'Введите секретный ключ',
'google_recaptcha_error_msg' => 'Текст сообщения при ошибке',
'google_recaptcha_error_msg_comment' => 'Сообщение для пользователя, когда он не прошел проверку reCAPTCHA.',
'google_recaptcha_error_msg_placeholder' => 'Google reCAPTCHA ошибка валидации!',
'google_recaptcha_scripts_allow' => 'Автоматический добавить JavaScript',
'google_recaptcha_scripts_allow_comment' => 'Добавить загрузку необходимых JavaScript на ваш сайт.',
'google_recaptcha_locale_allow' => 'Разрешить локализацию',
'google_recaptcha_locale_allow_comment' => 'Переведет reCAPTCHA, в соответствии с языком веб-страницы.',
'add_ip_protection' => 'Проверять IP-адрес отправителя',
'add_ip_protection_comment' => 'Ограничивает число отправки форм с одного IP-адреса.',
'add_ip_protection_count' => 'Максимальное число отправки форм за день',
'add_ip_protection_count_comment' => 'Количество разрешенных отправлений формы с одного IP-адреса в течение одного дня.',
'add_ip_protection_count_placeholder' => '3',
'add_ip_protection_error_too_many_submits' => 'Сообщение об ошибке',
'add_ip_protection_error_too_many_submits_comment' => 'Текст ошибки при привышении максимального числа отправок, для показа пользователю.',
'add_ip_protection_error_too_many_submits_placeholder' => 'С вашего IP отправлено слишком много форм!',
],
'mapping' => [
'hint' => [
'title' => 'Почему отображение полей?',
'content' => '
<p>Вы можете создать пользовательскую форму с собственными именами и типами полей.</p>
<p>Система записывает все данные формы в базу данных. Для быстрого обзора в бэкенд Контакт форма > Сообщения, нужно привязать поля: Имя, Email, Сообщения.</p>
<p>Поэтому вам необходимо помочь системе идентифицировать эти столбцы, сопоставляя их с полями формы.</p>
<p><em>Эти сопоставления также используются для атоматической отправки писем, где важно, по крайней мере, сопоставление поля Email.</em></p>
',
],
'warning' => [
'title' => 'Не можете выбрать поля формы?',
'content' => '
<p>Если вы не видите свои поля, нажмите кнопку «Сохранить» в нижней части этой страницы, а затем перезагрузите страницу (F5 или Ctr+R / Cmd+R).</p>
',
],
],
'tabs' => [
'form' => 'Форма',
'buttons' => 'Кнопка отправки',
'form_fields' => 'Редактор полей',
'mapping' => 'Отображение',
'email' => 'Email',
'antispam' => 'АнтиСпам',
],
],
];

View File

@ -0,0 +1,305 @@
<?php
return [
'plugin' => [
'name' => 'Kontaktný formulár',
'description' => 'Jednoduchý kontaktný formulár',
'category' => 'Small plugins',
],
'permissions' => [
'access_messages' => 'Prístup k zoznamu správ',
'access_settings' => 'Prístup k nastaveniam',
'delete_messages' => 'Zmazať vybrané správy',
'export_messages' => 'Exportovať správy',
],
'navigation' => [
'main_label' => 'Kontaktný formulár',
'messages' => 'Správy',
],
'controller' => [
'contact_form' => [
'name' => 'Kontaktný formulár',
'description' => 'Pridá na stránku kontaktný formulár',
'no_fields' => 'Pridajte prosím nejaké formulárové polia v administrácií systému (Nastavenia > Kontaktný formulár > Polia)...',
],
'filter' => [
'date' => 'Rozmedzie dátumu',
],
'scoreboard' => [
'records_count' => 'Správy',
'latest_record' => 'najnovšie od',
'new_count' => 'Nové',
'new_description' => 'Správ',
'read_count' => 'Prečítané',
'all_count' => 'Celkom',
'all_description' => 'Správ',
'settings_btn' => 'Nastavenie formulára',
'mark_read' => 'Označiť ako prečítané',
'mark_read_confirm' => 'Naozaj chcete vybrané správy označiť ako prečítané?',
'mark_read_success' => 'Správy boli označené ako prečítané.',
],
'preview' => [
'record_not_found' => 'Správa nebola nájdená!',
],
],
'models' => [
'message' => [
'columns' => [
'id' => 'ID',
'datetime' => 'Dátum a čas',
'form_data' => 'Dáta formulára',
'name' => 'Meno',
'email' => 'Email',
'message' => 'Správa',
'new_message' => 'Stav',
'new' => 'Nová',
'read' => 'Prečítaná',
'remote_ip' => 'IP odosielateľa',
'created_at' => 'Dátum vytvorenia',
'updated_at' => 'Dátum aktualizácie',
]
],
],
'controllers' => [
'messages' => [
'list_title' => 'Správy',
'preview' => 'Náhľad',
'preview_title' => 'Správa z kontaktného formulára',
'preview_date' => 'Z dňa:',
'preview_content_title' => 'Obsah:',
'remote_ip' => 'odoslané z ip',
'form_alias' => 'Alias',
'form_description' => 'Popis',
'export' => 'Export',
],
'index' => [
'unauthorized' => 'Neoprávnený prístup!',
],
],
'mail' => [
'templates' => [
'autoreply' => 'Správa automatickej odpovede z kontaktného formulára (Anglicky)',
'notification' => 'Notifikácia z kontaktného formulára (Anglicky)',
'autoreply_cs' => 'Správa automatickej odpovede z kontaktného formulára (Česky)',
'notification_cs' => 'Notifikácia z kontaktného formulára (Česky)',
]
],
'reportwidget' => [
'partials' => [
'messages' => [
'label' => 'Kontaktný formulár - Prehľad správ',
'title' => 'Prehľad správ',
'messages_all' => 'Všetky',
'messages_new' => 'Nové',
'messages_read' => 'Prečítané',
],
'new_message' => [
'label' => 'Kontaktný formulár - Nové správy',
'title' => 'Nové správy',
'link_text' => 'Kliknite pre zobrazenie prehľadu správ',
],
],
],
'settings' => [
'form' => [
'css_class' => 'CSS trieda formulára',
'use_placeholders' => 'Používať zástupný text (placeholder)',
'use_placeholders_comment' => 'Miesto popiskov nad formulárovými poliami bude použitý zástupný text',
'disable_browser_validation' => 'Zakázať validáciu prehliadačom',
'disable_browser_validation_comment' => 'Nepovoliť prehliadaču použiť vlastnú validáciu a zobrazovať výstrahy.',
'success_msg' => 'Správa po úspešnom odoslaní',
'success_msg_placeholder' => 'Formulár bol v poriadku odoslaný.',
'error_msg' => 'Chybová správa',
'error_msg_placeholder' => 'Pri odosielaní formulára došlo k chybe!',
'allow_ajax' => 'Povoliť AJAX',
'allow_ajax_comment' => 'Povolí AJAX, ale umožní fungovanie formulára aj na prehliadačoch s vypnutým JavaScriptom',
'allow_confirm_msg' => 'Požadovať potvrdenie pred odoslaním',
'allow_confirm_msg_comment' => 'Zobrazí potvrdzovacie okno pred odoslaním formulára',
'send_confirm_msg' => 'Text potvrdenia',
'send_confirm_msg_placeholder' => 'Naozaj chcete odoslať formulár?',
'hide_after_success' => 'Skryť formulár po úspešnom odoslaní',
'hide_after_success_comment' => 'Po odoslaní zobrazí iba správu s potvrdením bez formulára',
'add_assets' => 'Pridať doplnky',
'add_assets_comment' => 'Automaticky vloží potrebné CSS štýly a JS skripty (Viac informácií je v súbore README.md)',
'add_css_assets' => 'Pridať CSS štýly',
'add_css_assets_comment' => 'Vloží všetky potrebné štýly',
'add_js_assets' => 'Pridať JS skripty',
'add_js_assets_comment' => 'Vloží všetky potrebné skripty',
],
'buttons' => [
'send_btn_text' => 'Text odosielacieho tlačidla',
'send_btn_text_placeholder' => 'Odoslať',
'send_btn_css_class' => 'CSS trieda odosielacieho tlačidla',
'send_btn_css_class_placeholder' => 'btn btn-primary',
'send_btn_wrapper_css' => 'CSS trieda kontajneru',
'send_btn_wrapper_css_placeholder' => 'form-group',
],
'redirect' => [
'allow_redirect' => 'Presmerovať po úspěšnom odoslaní',
'allow_redirect_comment' => 'Presmerovať na inú stránku po úspešnom odoslaní formulára',
'redirect_url' => 'URL stránky pre presmerovanie',
'redirect_url_comment' => 'Vložte URL adresu stránky, kam bude presmerované (např. /kontakt/dakujeme)',
'redirect_url_placeholder' => '/kontakt/dakujeme',
'redirect_url_external' => 'Externá URL',
'redirect_url_external_comment' => 'Toto je adresa externej stránky (napr. http://www.domain.com)',
],
'form_fields' => [
'prempt' => 'Pridať nové pole formulára',
'name' => 'NÁZOV POĽA',
'name_comment' => 'Malými písmenami bez diakritiky (napr. meno, email, vasa_poznamka, ...)',
'type' => 'Typ poľa',
'label' => 'Popisok (label)',
'label_placeholder' => 'Pole formulára',
'field_styling' => 'Vlastné CSS triedy',
'field_styling_comment' => 'Môžete pridať vlastné štýly',
'autofocus' => 'Automaticky zvýrazniť (autofocus)',
'autofocus_comment' => 'Po zobrazení nastaviť na pole kurzor',
'wrapper_css' => 'CSS trieda kontajneru',
'wrapper_css_placeholder' => 'form-group',
'field_css' => 'CSS trieda poľa',
'field_css_placeholder' => 'form-control',
'label_css' => 'CSS trieda popisku (label)',
'label_css_placeholder' => '',
'field_validation' => 'Validačné pravidlá poľa',
'field_validation_comment' => 'Povolí nastavenie vlastných validačných pravidiel',
'validation' => 'Pravidlo',
'validation_prempt' => 'Pridať pravidlo',
'validation_type' => 'Typ',
'validation_error' => 'Chybová správa',
'validation_error_placeholder' => 'prosím vložte správne dáta.',
'validation_error_comment' => 'Chybová hláška, ktorá sa zobrazí pri poli',
'custom' => 'vlastné pole',
'custom_description' => 'vlastné pole s validačnými pravidlami',
],
'form_field_types' => [
'text' => 'Text',
'email' => 'Email',
'textarea' => 'Textarea',
'checkbox' => 'Checkbox',
'dropdown' => 'Dropdown',
'file' => 'File',
'custom_code' => 'Custom code',
'custom_content' => 'Custom content',
],
'form_field_validation' => [
'select' => '--- Vyberte pravidlo ---',
'required' => 'Vyžadované',
'email' => 'Email',
'numeric' => 'Číslo',
],
'email' => [
'address_from' => 'Adresa OD',
'address_from_placeholder' => 'john.doe@domain.com',
'address_from_name' => 'Meno odesielateľa',
'address_from_name_placeholder' => 'John Doe',
'subject' => 'Peedmet emailu',
'subject_comment' => 'Nastavte iba pokiaľ chcete prepísať predmet definovaný v šablóne (Nastavenia > E-mailové šablóny).',
'template' => 'Šablóna emailu',
'template_comment' => 'Kód emailovej šablóny vytvorenej v Nastavenia > E-mailové šablóny. Nechajte prázdne pre predvolenú šablónu: janvince.smallcontactform::mail.autoreply.',
'allow_email_queue' => 'Řadit do fronty',
'allow_email_queue_comment' => 'Pridať emaily do fronty místo okamžitého odoslaní. Musíte ale nejdříve správně nakonfigurovat frontu systému OctoberCMS!',
'allow_notifications' => 'Povoliť odosielanie upozornění',
'allow_notifications_comment' => 'Odesílat upozornení, pokiaľ niekto odošle formulár.',
'notification_address_to' => 'Upozornenia posielať na adresu:',
'notification_address_to_comment' => 'Jedna emailová adresa alebo zoznam adries oddelených čiarkami',
'notification_address_to_placeholder' => 'notifications@domain.com',
'notification_address_from_form' => 'nastaviť adresu Od na email z formulára (NEMUSÍ PODPOROVAŤ váš emailový systém!)',
'notification_address_from_form_comment' => 'Nastaví u odosielaného upozornenia adresu Od (From) na tú, ktorá bola zadaná vo formulári (stĺpec email musí mať nastavenú väzbu).',
'allow_autoreply' => 'Povoliť automatickú odpoveď',
'allow_autoreply_comment' => 'Poslať automatickú odpoveď odosielateľovi formulára',
'autoreply_name_field' => 'Pole formulára, ktoré obsahuje MENO odosielateľa',
'autoreply_name_field_empty_option' => '-- Vyberte --',
'autoreply_name_field_comment' => 'Pole typu Text.',
'autoreply_email_field' => 'Pole formulára, ktoré obsahuje EMAIL odosielateľa',
'autoreply_email_field_empty_option' => '-- Vyberte --',
'autoreply_email_field_comment' => 'Pole typu Email.',
'autoreply_message_field' => 'Pole formulára, ktoré obsahuje SPRÁVU',
'autoreply_message_field_empty_option' => '-- vyberte --',
'autoreply_message_field_comment' => 'Pole typu Textarea alebo Text.',
'notification_template' => 'Šablóna notifikačného emailu',
'notification_template_comment' => 'Kód emailovej šablóny vytvorenej v Nastavenia > E-mailové šablóny. Nechajte prázdne pre predvolenú šablónu: janvince.smallcontactform::mail.notification.',
],
'antispam' => [
'add_antispam' => 'Pridať pasívnu ochranu proti spamu',
'add_antispam_comment' => 'Pridá jednoduchú ale efektívnu pasívnu ochranu proti robotom (viac informácií v súbore README.md)',
'antispam_delay' => 'Meškanie formulára (s)',
'antispam_delay_comment' => 'Test na príliš rýchle odoslanie formulára (väčšinou robotmi)',
'antispam_delay_placeholder' => '3',
'antispam_label' => 'Popisok (label) antispamového poľa',
'antispam_label_comment' => 'Popisok bude viditeľný iba na prehliadačoch bez podpory JavaScriptu',
'antispam_label_placeholder' => 'prosím vymažte toto pole',
'antispam_error_msg' => 'Chybová správa',
'antispam_error_msg_comment' => 'Správa, ktorá se zobrazí, pokiaľ sa aktivuje pasívny antispam',
'antispam_error_msg_placeholder' => 'prosím vymažte obsah tohoto poľa!',
'antispam_delay_error_msg' => 'Chybová správa pri rýchlom odoslaní',
'antispam_delay_error_msg_comment' => 'Správa, ktorá se zobrazí pri príliš rýchlom odoslaní formulára',
'antispam_delay_error_msg_placeholder' => 'Príliš rýchle odoslanie formulára! prosím skúste to za pár sékúnd znovu!',
'add_google_recaptcha' => 'Pridať Google reCaptcha',
'add_google_recaptcha_comment' => 'Pridá reCaptcha do kontaktného formulára (viac informácií v súbore README.md). <br>API kľúče môžete získať na <a href="https://www.google.com/recaptcha/admin#list" target="_blank">stránke Google reCaptcha</a>.',
'google_recaptcha_site_key' => 'Site key',
'google_recaptcha_site_key_comment' => 'Vložte svoj "site key"',
'google_recaptcha_secret_key' => 'Secret key',
'google_recaptcha_secret_key_comment' => 'Vložte svoj "secret key"',
'google_recaptcha_error_msg' => 'Chybová správa',
'google_recaptcha_error_msg_comment' => 'Správa, ktorá sa zobrazí, pokiaľ dôjde k chybe pri overení reCAPTCHA.',
'google_recaptcha_error_msg_placeholder' => 'Chyba pri overení pomocou Google reCAPTCHA!',
'google_recaptcha_scripts_allow' => 'Automaticky pridať Google reCAPTCHA skript',
'google_recaptcha_scripts_allow_comment' => 'Vloží odkaz na JavaScriptový súbor potrebný pre fungovanie reCAPTCHA.',
'google_recaptcha_locale_allow' => 'Povoliť detekciu jazyka',
'google_recaptcha_locale_allow_comment' => 'Pridá k reCAPTCHA skriptu kód jazyka stránky, takže overovací box bude preložený do jazyka návštevníka webu.',
'add_ip_pretection' => 'Testovať IP adresu odosielateľa',
'add_ip_pretection_comment' => 'Nepovolí príliš mnoho odoslaní formulára z jednej IP adresy',
'add_ip_pretection_count' => 'Maximálny počet odoslaní behom jedného dňa',
'add_ip_pretection_count_comment' => 'Počet povolených odoslaní formulára z jednej IP adresy behom jedného dňa',
'add_ip_pretection_count_placeholder' => '3',
'add_ip_pretection_error_get_ip' => 'Nepodarilo sa určiť vašu IP adresu!',
'add_ip_pretection_error_too_many_submits' => 'Chybová správa pri prekročení počtu odoslaní',
'add_ip_pretection_error_too_many_submits_comment' => 'Správa, ktorú obdrží uživateľ pri prekročení limitu počtu odoslaní formulára',
'add_ip_pretection_error_too_many_submits_placeholder' => 'Bol prekročný limit odoslaní formulára behom jedného dňa!',
'disabled_extensions' => 'Zakázané rozšírenia',
'disabled_extensions_comment' => 'Nastavenia zo záložky Súkromie spôsibili vypnutie týchto rozšírení',
],
'mapping' => [
'hint' => [
'title' => 'zrušiť vazby na stĺpce?',
'content' => '
<p>Môžete vytvoriť ľubovolný formulár s vlastnými poliami a ich typmi.</p>
<p>Systém zapíše do databázy všetky odoslané dáta formulára, ale pre Prehľad správ zvlášť ukladané polia Meno, Email a Správa.</p>
<p>preto je nutné identifikovať pre tieot stĺpce odpovedajúce polia vo vašom formulári.</p>
<p><em>Vytvorené väzby použité aj pri odosielaní automatických odpovedí, kde je nutná väzba aspoň na pole Email.</em></p>
',
],
'warning' => [
'title' => 'Nevidíte vaše formulárové polia?',
'content' => '
<p>Pokiaľ tu nevidíte svoje formulárové polia, kliknite dole na tlačidlo Uložiť a potom obnovte stránku (F5 alebo Ctrl+R / Cmd+R).</p>
',
],
],
'privacy' => [
'disable_messages_saving' => 'Zakázať ukladanie správ',
'disable_messages_saving_comment' => 'Pokiaľ je zaškrtnuté, odoslané správy sa nebudú ukladať do databázy.<br><strong>Táto voľba zárovaň zakáže použitie IP ochrany!</strong>',
'disable_messages_saving_comment_section' => '<div class="callout fade in callout-danger no-subheader"><div class="header"><i class="icon-warning"></i><h3>Uistite sa, že máte povolené notifikačné emaily, inak nebudete mať žiadne dáta z odoslaných formulárov!</h3></div></div>',
],
'tabs' => [
'form' => 'Formulár',
'buttons' => 'Odosielacie tlačidlo',
'form_fields' => 'Pole formulára',
'mapping' => 'Väzby stĺpcov',
'email' => 'Email',
'antispam' => 'Antispam',
'privacy' => 'Súkromie'
],
],
'components' => [
'groups' => [
'hacks' => 'Hacks',
],
'preperties' => [
'disable_notifications' => 'Zakázať odosielanie notifikačných emailov',
'disable_notifications_comment' => 'Zakáže odoslanie notifikačných emailov (bez ohľadu na systémové nastavenia formulára)',
'form_description' => 'Popisok formulára',
'form_description_comment' => 'Volitelne môžete pridať popisok formulára, ktorý sa uloží spoločne s odoslanými dátami zoznamu správ. Môžete použiť aj {{ :slug }}.',
]
],
];

View File

@ -0,0 +1,541 @@
<?php namespace JanVince\SmallContactForm\Models;
use Str;
use Model;
use URL;
use October\Rain\Router\Helper as RouterHelper;
use Cms\Classes\Page as CmsPage;
use Cms\Classes\Theme;
use JanVince\SmallContactForm\Models\Settings;
use Log;
use Validator;
use Mail;
use Request;
use Carbon\Carbon;
use View;
use App;
use System\Models\MailTemplate;
use System\Classes\MailManager;
use Twig;
use Input;
use System\Models\File;
class Message extends Model
{
use \October\Rain\Database\Traits\Validation;
public $table = 'janvince_smallcontactform_messages';
public $implement = ['@RainLab.Translate.Behaviors.TranslatableModel'];
public $timestamps = true;
public $rules = [];
public $translatable = [];
protected $guarded = [];
protected $jsonable = ['form_data'];
public $attachMany = [
'uploads' => 'System\Models\File',
];
/**
* Scope new messages only
*/
public function scopeIsNew($query)
{
return $query->where('new_message', '=', 1);
}
/**
* Scope read messages only
*/
public function scopeIsRead($query)
{
return $query->where('new_message', '=', 0);
}
public function storeFormData($data, $formAlias, $formDescription, $formNotes){
if(Settings::getTranslated('privacy_disable_messages_saving')) {
return;
}
$output = [];
$name_field_value = NULL;
$email_field_value = NULL;
$message_field_value = NULL;
$formFields = Settings::getTranslated('form_fields');
$uploads = [];
foreach($data as $key => $value) {
// skip helpers
if(substr($key, 0, 1) == '_'){
continue;
}
// skip reCaptcha
if($key == 'g-recaptcha-response'){
continue;
}
// skip non-defined fields
// store uploaded file -- currently only one file is supported
$fieldDefined = null;
$fieldUpload = null;
foreach( $formFields as $field) {
if( $field['name'] == $key) {
$fieldDefined = true;
if($field['type'] == 'file') {
$fieldUpload = true;
if(!empty(Input::file($key))) {
$file = new File;
$file->data = (Input::file($key));
$file->is_public = true;
$file->save();
$uploads[] = $file;
}
}
}
}
// skip uploads
if($fieldUpload){
continue;
}
if( !$fieldDefined ) {
Log::warning('SMALL CONTACT FORM WARNING: Found a non-defined field in sent data! Field name: ' . e($key) . ' and value: ' . e($value['value']) );
continue;
}
$output[$key] = e($value['value']);
// if email field is assigned in autoreply, save it separatelly
if(empty($email_field_value) and $key == Settings::getTranslated('autoreply_email_field')){
$email_field_value = e($value['value']);
}
// if name field is assigned in autoreply, save it separatelly
if(empty($name_field_value) and $key == Settings::getTranslated('autoreply_name_field')){
$name_field_value = e($value['value']);
}
// if message is assigned in autoreply, save it separatelly
if(empty($message_field_value) and $key == Settings::getTranslated('autoreply_message_field')){
$message_field_value = e($value['value']);
}
}
$this->form_data = $output;
$this->name = $name_field_value;
$this->email = $email_field_value;
$this->message = $message_field_value;
$this->remote_ip = Request::ip();
$this->form_alias = $formAlias;
$this->form_description = $formDescription;
$this->url = url()->full();
$this->form_notes = $formNotes;
$this->save();
// Add files
if($uploads) {
foreach($uploads as $upload) {
$this->uploads()->add($upload);
}
}
return $this;
}
/**
* Build and send autoreply message
*/
public function sendAutoreplyEmail($postData, $componentProperties, $formAlias, $formDescription, $messageObject, $formNotes){
if(!Settings::getTranslated('allow_autoreply')) {
return;
}
if (!empty($componentProperties['disable_autoreply'])) {
return;
}
if(!Settings::getTranslated('autoreply_email_field')) {
Log::error('SMALL CONTACT FORM ERROR: Contact form data have no email to send autoreply message!');
return;
}
/**
* Extract and test email field value
*/
$sendTo = '';
foreach($postData as $key => $field) {
if($key == Settings::getTranslated('autoreply_email_field')){
$sendTo = $field['value'];
}
}
$validator = Validator::make(['email' => $sendTo], ['email' => 'required|email']);
if($validator->fails()){
Log::error('SMALL CONTACT FORM ERROR: Email to send autoreply is not valid!' . PHP_EOL . ' Data: '. json_encode($postData) );
return;
}
if( Settings::getTranslated('allow_email_queue') ){
$method = 'queue';
} else {
$method = 'send';
}
$output = [];
$outputFull = [];
$formFields = Settings::getTranslated('form_fields');
foreach($formFields as $field) {
if(!empty($field['type'] and $field['type'] == 'file')) {
continue;
}
$fieldValue = null;
if( !empty( $postData[ $field['name'] ]['value'] ) ) {
$fieldValue = e( html_entity_decode( $postData[ $field['name'] ]['value'] ) );
} else {
$fieldValue = null;
}
if( !empty( $field['name'] ) ) {
$outputFull[ $field['name'] ] = array_merge( $field, [ 'value' => $fieldValue ] );
}
$output[ $field['name'] ] = $fieldValue;
}
$output['form_description'] = $formDescription;
$output['form_alias'] = $formAlias;
$template = Settings::getTranslatedTemplates('en', App::getLocale(), 'autoreply');
if( Settings::getTranslated('email_template') ){
if(View::exists(Settings::getTranslated('email_template')) OR !empty( MailTemplate::listAllTemplates()[Settings::getTranslated('email_template')] ) ) {
$template = Settings::getTranslated('email_template');
} else {
Log::error('SMALL CONTACT FORM: Missing defined email template: ' . Settings::getTranslated('email_template') . '. Default template will be used!');
}
}
/**
* Override email template by component property
* Language specific template has priority (override non language specific)
*/
if ( !empty($componentProperties['autoreply_template']) and !empty( MailTemplate::listAllTemplates()[ $componentProperties['autoreply_template'] ] ) ) {
$template = $componentProperties['autoreply_template'];
} elseif ( !empty($componentProperties['autoreply_template']) and empty( MailTemplate::listAllTemplates()[ $componentProperties['autoreply_template'] ] ) ) {
Log::error('SMALL CONTACT FORM: Missing defined email template: ' . $componentProperties['autoreply_template'] . '. ' . $template . ' template will be used!');
}
if ( !empty($componentProperties[ ('autoreply_template_'.App::getLocale())]) and !empty( MailTemplate::listAllTemplates()[ $componentProperties[ ('autoreply_template_'.App::getLocale())] ] ) ) {
$template = $componentProperties[('autoreply_template_'.App::getLocale())];
} elseif ( !empty($componentProperties[ ('autoreply_template_'.App::getLocale())]) and empty( MailTemplate::listAllTemplates()[ $componentProperties[ ('autoreply_template_'.App::getLocale())] ] ) ) {
Log::error('SMALL CONTACT FORM: Missing defined email template: ' . $componentProperties[ ('autoreply_template_'.App::getLocale())] . '. ' . $template . ' template will be used!');
}
if(!empty($messageObject->uploads))
{
$uploads = $messageObject->uploads;
}
else
{
$uploads = [];
}
Mail::{$method}($template, ['messageObject' => $messageObject, 'uploads' => $uploads, 'fields' => $output, 'fieldsDetails' => $outputFull, 'url' => url()->full(), 'form_notes' => $formNotes], function($message) use($sendTo, $componentProperties, $output){
$message->to($sendTo);
if (!empty($componentProperties['autoreply_subject'])) {
$message->subject(Twig::parse($componentProperties['autoreply_subject'],['fields' => $output]));
\App::forgetInstance('parse.twig');
\App::forgetInstance('twig.environment');
} elseif (Settings::getTranslated('email_subject')) {
$message->subject(Twig::parse(Settings::getTranslated('email_subject'), ['fields' => $output]));
\App::forgetInstance('parse.twig');
\App::forgetInstance('twig.environment');
}
/**
* From address
* Component's property can override this
*/
$fromAddress = null;
$fromAddressName = null;
if( Settings::getTranslated('email_address_from') ) {
$fromAddress = Settings::getTranslated('email_address_from');
$fromAddressName = Settings::getTranslated('email_address_from_name');
}
if( !empty($componentProperties['autoreply_address_from']) ) {
$fromAddress = $componentProperties['autoreply_address_from'];
}
if( !empty($componentProperties['autoreply_address_from_name']) ) {
$fromAddressName = $componentProperties['autoreply_address_from_name'];
}
if( !empty($componentProperties[ ('autoreply_address_from_name_'.App::getLocale()) ]) ) {
$fromAddressName = $componentProperties[ ('autoreply_address_from_name_'.App::getLocale()) ];
}
$validator = Validator::make(['email' => $fromAddress], ['email' => 'required|email']);
if($validator->fails()){
Log::error('SMALL CONTACT FORM ERROR: Autoreply email address is invalid (' .$fromAddress. ')! System email address and name will be used.');
} else {
$message->from($fromAddress, $fromAddressName);
}
/**
* Reply To address
* Component's property can override this
*/
$replyToAddress = null;
if( Settings::getTranslated('email_address_replyto') ) {
$replyToAddress = Settings::getTranslated('email_address_replyto');
}
if( !empty($componentProperties['autoreply_address_replyto']) ) {
$replyToAddress = $componentProperties['autoreply_address_replyto'];
}
if( $replyToAddress ) {
$validator = Validator::make(['email' => $replyToAddress], ['email' => 'required|email']);
if($validator->fails()){
Log::error('SMALL CONTACT FORM ERROR: Autoreply Reply To email address is invalid (' .$replyToAddress. ')! No Reply To header will be added.');
} else {
$message->replyTo($replyToAddress);
}
}
});
}
/**
* Build and send notification message
*/
public function sendNotificationEmail($postData, $componentProperties, $formAlias, $formDescription, $messageObject, $formNotes){
if(!Settings::getTranslated('allow_notifications')) {
return;
}
if(!empty($componentProperties['disable_notifications'])) {
return;
}
$sendTo = (!empty($componentProperties['notification_address_to']) ? $componentProperties['notification_address_to'] : Settings::getTranslated('notification_address_to') );
$sendToAddresses = explode(',', $sendTo);
$sendToAddressesValidated = [];
foreach($sendToAddresses as $sendToAddress) {
$validator = Validator::make(['email' => trim($sendToAddress)], ['email' => 'required|email']);
if($validator->fails()){
Log::error('SMALL CONTACT FORM ERROR: Notification email address (' .trim($sendToAddress). ') is invalid! No notification will be delivered!');
} else {
$sendToAddressesValidated[] = trim($sendToAddress);
}
}
if( !count($sendToAddressesValidated) ) {
return;
}
if( Settings::getTranslated('allow_email_queue') ){
$method = 'queue';
} else {
$method = 'send';
}
$output = [];
$outputFull = [];
$formFields = Settings::getTranslated('form_fields');
$replyToAddress = null;
$replyToName = null;
foreach($formFields as $field) {
if(!empty($field['type'] and $field['type'] == 'file')) {
continue;
}
$fieldValue = null;
if( !empty( $postData[ $field['name'] ]['value'] ) ) {
$fieldValue = e( html_entity_decode( $postData[ $field['name'] ]['value'] ) );
} else {
$fieldValue = null;
}
if( !empty( $field['name'] ) ) {
$outputFull[ $field['name'] ] = array_merge( $field, [ 'value' => $fieldValue ] );
}
// If email field is assigned, prepare for replyTo
if(empty($replyToAddress) and $field['name'] == Settings::getTranslated('autoreply_email_field') and isset($postData[$field['name']]['value'])){
$replyToAddress = e( $postData[$field['name']]['value'] );
}
// If name field is assigned, prepare for fromAddress
if(empty($replyToName) and $field['name'] == Settings::getTranslated('autoreply_name_field') and isset($postData[$field['name']]['value'])){
$replyToName = e( $postData[$field['name']]['value'] );
}
$output[ $field['name'] ] = $fieldValue;
}
$output['form_description'] = $formDescription;
$output['form_alias'] = $formAlias;
$template = Settings::getTranslatedTemplates('en', App::getLocale(), 'notification');
if( Settings::getTranslated('notification_template') ){
if(View::exists(Settings::getTranslated('notification_template')) OR !empty( MailTemplate::listAllTemplates()[Settings::getTranslated('notification_template')] ) ) {
$template = Settings::getTranslated('notification_template');
} else {
Log::error('SMALL CONTACT FORM: Missing defined email template: ' . Settings::getTranslated('notification_template') . '. Default template will be used!');
}
}
/**
* Override email template by component property
* Language specific template has priority (override non language specific)
*/
if ( !empty($componentProperties['notification_template']) and !empty( MailTemplate::listAllTemplates()[ $componentProperties['notification_template'] ] ) ) {
$template = $componentProperties['notification_template'];
} elseif ( !empty($componentProperties['notification_template']) and empty( MailTemplate::listAllTemplates()[ $componentProperties['notification_template'] ] ) ) {
Log::error('SMALL CONTACT FORM: Missing defined email template: ' . $componentProperties['notification_template'] . '. ' . $template . ' template will be used!');
}
if ( !empty($componentProperties[ ('notification_template_'.App::getLocale())]) and !empty( MailTemplate::listAllTemplates()[ $componentProperties[ ('notification_template_'.App::getLocale())] ] ) ) {
$template = $componentProperties[('notification_template_'.App::getLocale())];
} elseif ( !empty($componentProperties[ ('notification_template_'.App::getLocale())]) and empty( MailTemplate::listAllTemplates()[ $componentProperties[ ('notification_template_'.App::getLocale())] ] ) ) {
Log::error('SMALL CONTACT FORM: Missing defined email template: ' . $componentProperties[ ('notification_template_'.App::getLocale())] . '. ' . $template . ' template will be used!');
}
if(!empty($messageObject->uploads))
{
$uploads = $messageObject->uploads;
}
else
{
$uploads = [];
}
Mail::{$method}($template, ['messageObject' => $messageObject, 'uploads' => $uploads, 'fields' => $output, 'fieldsDetails' => $outputFull, 'url' => url()->full(), 'form_notes' => $formNotes], function($message) use($sendToAddressesValidated, $replyToAddress, $replyToName, $componentProperties, $output){
if( count($sendToAddressesValidated)>1 ) {
foreach($sendToAddressesValidated as $address) {
$message->bcc($address);
}
} elseif( !empty($sendToAddressesValidated[0]) ) {
$message->to($sendToAddressesValidated[0]);
} else {
return;
}
if (!empty($componentProperties['notification_subject'])) {
$message->subject(Twig::parse($componentProperties['notification_subject'], ['fields' => $output]));
\App::forgetInstance('parse.twig');
\App::forgetInstance('twig.environment');
}
/**
* Set Reply to address and also set From address if requested
*/
if ( !empty($replyToAddress) ) {
$validator = Validator::make(['email' => $replyToAddress], ['email' => 'required|email']);
if($validator->fails()){
Log::error('SMALL CONTACT FORM ERROR: Notification replyTo address is not valid (' .$replyToAddress. ')! Reply to address will not be used.');
return;
}
$message->replyTo($replyToAddress, $replyToName);
// Force From field if requested
if ( Settings::getTranslated('notification_address_from_form') ) {
$message->from($replyToAddress, $replyToName);
}
}
/**
* Set From address if defined in component property
*/
if ( !empty($componentProperties['notification_address_from'])) {
if (!empty($componentProperties['notification_address_from_name'])) {
$fromAddressName = $componentProperties['notification_address_from_name'];
} else {
$fromAddressName = null;
}
$message->from($componentProperties['notification_address_from'], $fromAddressName);
}
});
}
/**
* Test how many times was given IP address used this day
* @return int
*/
public function testIPAddress($ip){
$today = Carbon::today();
$count = Message::whereDate('created_at', '=', $today->toDateString())
->where('remote_ip', '=', $ip)
->count();
return $count;
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace JanVince\SmallContactForm\Models;
use Db;
use \Backend\Models\ExportModel;
use \October\Rain\Support\Collection;
use \JanVince\SmallContactForm\Models\Message;
class MessageExport extends ExportModel {
/**
* @var array Fillable fields
*/
// protected $fillable = [];
public function exportData($columns, $sessionKey = null)
{
$records = Message::all();
$records->each(function($record) use ($columns) {
$record->addVisible($columns);
});
return $records->toArray();
}
}

View File

@ -0,0 +1,439 @@
<?php
namespace JanVince\SmallContactForm\Models;
use Model;
use App;
use System\Classes\PluginManager;
class Settings extends Model
{
public $implement = [
'System.Behaviors.SettingsModel',
'@RainLab.Translate.Behaviors.TranslatableModel',
];
public $translatable = [
'form_success_msg',
'form_error_msg',
'form_send_confirm_msg',
'send_btn_text',
'form_fields',
'antispam_delay_error_msg',
'antispam_label',
'antispam_error_msg',
'add_ip_protection_error_too_many_submits',
'email_address_from_name',
'email_subject',
'email_template',
'notification_template',
'google_recaptcha_error_msg',
'ga_success_event_category',
'ga_success_event_action',
'ga_success_event_label',
'form_notes',
];
public $requiredPermissions = ['janvince.smallcontactform.access_settings'];
public $settingsCode = 'janvince_smallcontactform_settings';
public $settingsFields = 'fields.yaml';
protected $jsonable = ['form_fields'];
/**
* Try to use Rainlab Tranlaste plugin to get translated content or falls back to default settings value
*/
public static function getTranslated($value, $defaultValue = false){
// Check for Rainlab.Translate plugin
$pluginManager = PluginManager::instance()->findByIdentifier('Rainlab.Translate');
if ($pluginManager && !$pluginManager->disabled) {
$settings = Settings::instance();
$valueTranslated = $settings->getAttributeTranslated($value);
if(!empty($valueTranslated)){
return $valueTranslated;
} else {
return $defaultValue;
}
} else {
return Settings::get($value, $defaultValue);
}
}
/**
* Try to use Rainlab Tranlaste plugin to get translated content for given key
*/
public static function getDictionaryTranslated($value){
// Check for Rainlab.Translate plugin
$translatePlugin = PluginManager::instance()->findByIdentifier('Rainlab.Translate');
if ($translatePlugin && !$translatePlugin->disabled) {
$params = [];
$message = \RainLab\Translate\Models\Message::trans($value, $params);
return $message;
} else {
return $value;
}
}
/**
* Generate form fields types list
* @return array
*/
public function getTypeOptions($value, $formData)
{
$fieldTypes = $this->getFieldTypes();
$types = [];
if(!$fieldTypes) {
return [];
}
foreach ($fieldTypes as $key => $value) {
$types[$key] = 'janvince.smallcontactform::lang.settings.form_field_types.'.$key;
}
return $types;
}
/**
* Generate form fields types list
* @return array
*/
public function getValidationTypeOptions($value, $formData)
{
return [
'required' => 'janvince.smallcontactform::lang.settings.form_field_validation.required',
'email' => 'janvince.smallcontactform::lang.settings.form_field_validation.email',
'numeric' => 'janvince.smallcontactform::lang.settings.form_field_validation.numeric',
'custom' => 'janvince.smallcontactform::lang.settings.form_field_validation.custom',
];
}
/**
* Generate list of existing fields for email name
* @return array
*/
public function getAutoreplyNameFieldOptions($value, $formData)
{
return $this->getFieldsList('text');
}
/**
* Generate list of existing fields for email name
* @return array
*/
public function getAutoreplyEmailFieldOptions($value, $formData)
{
return $this->getFieldsList('email');
}
/**
* Generate list of existing message fields
* @return array
*/
public function getAutoreplyMessageFieldOptions($value, $formData)
{
return $this->getFieldsList('textarea');
}
/**
* Generate fields list
* @return arry
*/
private function getFieldsList($type = false, $forceType = false){
$output = [];
$outputAll = [];
foreach (Settings::getTranslated('form_fields', []) as $field) {
$fieldName = $field['name'] . ' ['. $field ['type'] . ']';
$outputAll[$field['name']] = $fieldName;
if($type && !empty($field['type']) && $field['type'] <> $type) {
continue;
} else {
$output[$field['name']] = $fieldName;
}
}
if($forceType) {
return $output;
} else {
return $outputAll;
}
}
/**
* HTML field types mapping array
* @return array
*/
public static function getFieldTypes($type = false) {
$types = [
'text' => [
'html_open' => 'input',
'label' => true,
'wrapper_class' => 'form-group',
'field_class' => 'form-control',
'use_name_attribute' => true,
'attributes' => [
'type' => 'text',
],
'html_close' => null,
],
'email' => [
'html_open' => 'input',
'label' => true,
'wrapper_class' => 'form-group',
'field_class' => 'form-control',
'use_name_attribute' => true,
'attributes' => [
'type' => 'email',
],
'html_close' => null,
],
'textarea' => [
'html_open' => 'textarea',
'label' => true,
'wrapper_class' => 'form-group',
'field_class' => 'form-control',
'use_name_attribute' => true,
'attributes' => [
'rows' => 5,
],
'html_close' => 'textarea',
],
'checkbox' => [
'html_open' => 'input',
'label' => false,
'wrapper_class' => null,
'field_class' => null,
'inner_label' => true,
'use_name_attribute' => true,
'attributes' => [
'type' => 'checkbox',
],
'html_close' => null,
],
'dropdown' => [
'html_open' => 'select',
'label' => true,
'wrapper_class' => 'form-group',
'field_class' => 'form-control',
'inner_label' => false,
'use_name_attribute' => true,
'attributes' => [
],
'html_close' => 'select',
],
'file' => [
'html_open' => 'input',
'label' => true,
'wrapper_class' => 'form-group',
'field_class' => 'form-control',
'inner_label' => false,
'use_name_attribute' => true,
'attributes' => [
'type' => 'file',
],
'html_close' => null,
],
'custom_code' => [
'html_open' => "div",
'label' => true,
'wrapper_class' => null,
'field_class' => null,
'inner_label' => false,
'use_name_attribute' => false,
'attributes' => [
],
'html_close' => "div",
],
'custom_content' => [
'html_open' => "div",
'label' => true,
'wrapper_class' => null,
'field_class' => null,
'inner_label' => false,
'use_name_attribute' => false,
'attributes' => [
],
'html_close' => "div",
],
];
if($type){
if(!empty($types[$type])){
return $types[$type];
}
}
return $types;
}
/**
* Get non English locales from Translate plugin
* @return array
*/
public static function getEnabledLocales() {
// Check for Rainlab.Translate plugin
$pluginManager = PluginManager::instance()->findByIdentifier('Rainlab.Translate');
if ($pluginManager && !$pluginManager->disabled) {
$locales = \RainLab\Translate\Models\Locale::listEnabled();
return $locales;
} elseif( App::getLocale() ) {
// Backend locale
return [
'en' => 'English',
App::getLocale() => App::getLocale(),
];
}
// English fallback
return [
'en' => 'English',
];
}
/**
* Get non English locales from Translate plugin
* @return array
*/
public static function getTranslatedTemplates($defaultLocale = 'en', $locale = NULL, $templateType = NULL) {
$enabledLocales = Settings::getEnabledLocales();
/**
* Templates map
* [locale] => [templateType] => [template]
*/
$translatedTemplates = [
'en' => [
'autoreply' => [
'janvince.smallcontactform::mail.autoreply' => 'janvince.smallcontactform::lang.mail.templates.autoreply',
],
'notification' => [
'janvince.smallcontactform::mail.notification' => 'janvince.smallcontactform::lang.mail.templates.notification',
],
],
'cs' => [
'autoreply' => [
'janvince.smallcontactform::mail.autoreply_cs' => 'janvince.smallcontactform::lang.mail.templates.autoreply_cs',
],
'notification' => [
'janvince.smallcontactform::mail.notification_cs' => 'janvince.smallcontactform::lang.mail.templates.notification_cs',
],
],
'es' => [
'autoreply' => [
'janvince.smallcontactform::mail.autoreply_es' => 'janvince.smallcontactform::lang.mail.templates.autoreply_es',
],
'notification' => [
'janvince.smallcontactform::mail.notification_es' => 'janvince.smallcontactform::lang.mail.templates.notification_es',
],
],
];
if( $locale and $templateType ) {
if( !empty($translatedTemplates[$locale]) and !empty($translatedTemplates[$locale][$templateType]) ) {
return key($translatedTemplates[$locale][$templateType]);
} elseif ( $defaultLocale and !empty($translatedTemplates[$defaultLocale]) and !empty($translatedTemplates[$defaultLocale][$templateType]) ) {
return key($translatedTemplates[$defaultLocale][$templateType]);
} else {
return NULL;
}
} else {
$allEnabledTemplates = [];
foreach( $enabledLocales as $enabledLocaleKey => $enabledLocaleName ) {
if( !empty($translatedTemplates[$enabledLocaleKey]) ) {
foreach( $translatedTemplates[$enabledLocaleKey] as $type ) {
foreach( $type as $key => $value ) {
$allEnabledTemplates[$key] = e(trans($value));
}
}
}
}
return $allEnabledTemplates;
}
return [];
}
}

View File

@ -0,0 +1,73 @@
# ===================================
# Column Definitions
# ===================================
columns:
# id:
# label: janvince.smallgallery::lang.categories.columns.id
# searchable: true
new_message:
label: janvince.smallcontactform::lang.models.message.columns.new_message
type: switch_icon_star
created_at:
label: janvince.smallcontactform::lang.models.message.columns.datetime
type: datetime
searchable: true
name:
label: janvince.smallcontactform::lang.models.message.columns.name
searchable: true
email:
label: janvince.smallcontactform::lang.models.message.columns.email
searchable: true
message:
label: janvince.smallcontactform::lang.models.message.columns.message
searchable: true
type: text_preview
width: 50%
remote_ip:
label: janvince.smallcontactform::lang.models.message.columns.remote_ip
searchable: true
type: text
invisible: true
form_alias:
label: janvince.smallcontactform::lang.models.message.columns.form_alias
searchable: true
type: text
invisible: true
form_description:
label: janvince.smallcontactform::lang.models.message.columns.form_description
searchable: true
type: text_preview
invisible: true
form_data:
label: janvince.smallcontactform::lang.models.message.columns.form_data
searchable: true
type: text
invisible: true
url:
label: janvince.smallcontactform::lang.models.message.columns.url
searchable: true
type: text
invisible: true
uploads:
label: janvince.smallcontactform::lang.models.message.columns.files
type: scf_files_link
invisible: true
form_notes:
label: janvince.smallcontactform::lang.models.message.columns.form_notes
searchable: true
type: text
invisible: true

View File

@ -0,0 +1,49 @@
# ===================================
# Column Definitions
# ===================================
columns:
id:
label: janvince.smallcontactform::lang.models.message.columns.id
type: number
new_message:
label: janvince.smallcontactform::lang.models.message.columns.new
type: number
created_at:
label: janvince.smallcontactform::lang.models.message.columns.created_at
type: datetime
updated_at:
label: janvince.smallcontactform::lang.models.message.columns.updated_at
type: datetime
name:
label: janvince.smallcontactform::lang.models.message.columns.name
type: text
email:
label: janvince.smallcontactform::lang.models.message.columns.email
type: text
message:
label: janvince.smallcontactform::lang.models.message.columns.message
type: text
remote_ip:
label: janvince.smallcontactform::lang.models.message.columns.remote_ip
type: text
form_alias:
label: janvince.smallcontactform::lang.models.message.columns.form_alias
type: text
form_description:
label: janvince.smallcontactform::lang.models.message.columns.form_description
type: text
form_description:
label: janvince.smallcontactform::lang.models.message.columns.url
type: text

View File

@ -0,0 +1,9 @@
<div class="callout fade in callout-info no-subheader">
<div class="header">
<i class="icon-warning"></i>
<h3><?= e(trans('janvince.smallcontactform::lang.settings.mapping.hint.title')); ?></h3>
</div>
<div class="content">
<p><?= trans('janvince.smallcontactform::lang.settings.mapping.hint.content'); ?></p>
</div>
</div>

View File

@ -0,0 +1,9 @@
<div class="callout fade in callout-warning no-subheader">
<div class="header">
<i class="icon-warning"></i>
<h3><?= e(trans('janvince.smallcontactform::lang.settings.mapping.warning.title')); ?></h3>
</div>
<div class="content">
<p><?= trans('janvince.smallcontactform::lang.settings.mapping.warning.content'); ?></p>
</div>
</div>

View File

@ -0,0 +1,894 @@
fields: { }
tabs:
fields:
## FORM
form_css_class:
label: 'janvince.smallcontactform::lang.settings.form.css_class'
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
form_success_msg:
label: 'janvince.smallcontactform::lang.settings.form.success_msg'
placeholder: 'janvince.smallcontactform::lang.settings.form.success_msg_placeholder'
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
form_error_msg:
label: 'janvince.smallcontactform::lang.settings.form.error_msg'
placeholder: 'janvince.smallcontactform::lang.settings.form.error_msg_placeholder'
span: right
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
form_hide_after_success:
label: 'janvince.smallcontactform::lang.settings.form.hide_after_success'
comment: 'janvince.smallcontactform::lang.settings.form.hide_after_success_comment'
span: left
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
form_use_placeholders:
label: 'janvince.smallcontactform::lang.settings.form.use_placeholders'
comment: 'janvince.smallcontactform::lang.settings.form.use_placeholders_comment'
span: left
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
form_disable_browser_validation:
label: 'janvince.smallcontactform::lang.settings.form.disable_browser_validation'
comment: 'janvince.smallcontactform::lang.settings.form.disable_browser_validation_comment'
span: left
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
section_ajax:
type: section
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
form_allow_ajax:
label: 'janvince.smallcontactform::lang.settings.form.allow_ajax'
comment: 'janvince.smallcontactform::lang.settings.form.allow_ajax_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
form_allow_confirm_msg:
label: 'janvince.smallcontactform::lang.settings.form.allow_confirm_msg'
comment: 'janvince.smallcontactform::lang.settings.form.allow_confirm_msg_comment'
span: left
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
cssClass: field-indent
trigger:
action: show
field: form_allow_ajax
condition: checked
form_send_confirm_msg:
label: 'janvince.smallcontactform::lang.settings.form.send_confirm_msg'
placeholder: 'janvince.smallcontactform::lang.settings.form.send_confirm_msg_placeholder'
span: right
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
cssClass: field-indent
trigger:
action: show
field: form_allow_ajax
condition: checked
section_assets:
type: section
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
trigger:
action: show
field: add_assets
condition: checked
add_assets:
label: 'janvince.smallcontactform::lang.settings.form.add_assets'
comment: 'janvince.smallcontactform::lang.settings.form.add_assets_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
add_css_assets:
label: 'janvince.smallcontactform::lang.settings.form.add_css_assets'
comment: 'janvince.smallcontactform::lang.settings.form.add_css_assets_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
cssClass: field-indent
trigger:
action: show
field: add_assets
condition: checked
add_js_assets:
label: 'janvince.smallcontactform::lang.settings.form.add_js_assets'
comment: 'janvince.smallcontactform::lang.settings.form.add_js_assets_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
cssClass: field-indent
trigger:
action: show
field: add_assets
condition: checked
section_notes:
type: section
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
form_notes:
label: 'janvince.smallcontactform::lang.settings.form.notes'
comment: 'janvince.smallcontactform::lang.settings.form.notes_comment'
span: left
type: textarea
tab: 'janvince.smallcontactform::lang.settings.tabs.form'
## BUTTONS
send_btn_wrapper_css:
span: left
label: 'janvince.smallcontactform::lang.settings.buttons.send_btn_wrapper_css'
placeholder: 'janvince.smallcontactform::lang.settings.buttons.send_btn_wrapper_css_placeholder'
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.buttons'
send_btn_css_class:
label: 'janvince.smallcontactform::lang.settings.buttons.send_btn_css_class'
placeholder: 'janvince.smallcontactform::lang.settings.buttons.send_btn_css_class_placeholder'
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.buttons'
send_btn_text:
label: 'janvince.smallcontactform::lang.settings.buttons.send_btn_text'
placeholder: 'janvince.smallcontactform::lang.settings.buttons.send_btn_text_placeholder'
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.buttons'
section_redirect:
type: section
tab: 'janvince.smallcontactform::lang.settings.tabs.buttons'
allow_redirect:
label: 'janvince.smallcontactform::lang.settings.redirect.allow_redirect'
comment: 'janvince.smallcontactform::lang.settings.redirect.allow_redirect_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.buttons'
redirect_url:
label: 'janvince.smallcontactform::lang.settings.redirect.redirect_url'
comment: 'janvince.smallcontactform::lang.settings.redirect.redirect_url_comment'
placeholder: 'janvince.smallcontactform::lang.settings.redirect.redirect_url_placeholder'
span: full
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.buttons'
cssClass: field-indent
trigger:
action: show
field: allow_redirect
condition: checked
redirect_url_external:
label: 'janvince.smallcontactform::lang.settings.redirect.redirect_url_external'
comment: 'janvince.smallcontactform::lang.settings.redirect.redirect_url_external_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.buttons'
cssClass: field-indent
trigger:
action: show
field: allow_redirect
condition: checked
## FORM FIELDS
form_fields:
prompt: 'janvince.smallcontactform::lang.settings.form_fields.prompt'
span: full
type: repeater
style: collapsed
tab: 'janvince.smallcontactform::lang.settings.tabs.form_fields'
form:
fields:
name:
span: full
label: 'janvince.smallcontactform::lang.settings.form_fields.name'
comment: 'janvince.smallcontactform::lang.settings.form_fields.name_comment'
type: text
required: true
# cssClass: 'bg-info'
type:
span: left
label: 'janvince.smallcontactform::lang.settings.form_fields.type'
type: dropdown
required: true
cssClass: field-indent
label:
span: right
label: 'janvince.smallcontactform::lang.settings.form_fields.label'
placeholder: 'janvince.smallcontactform::lang.settings.form_fields.label_placeholder'
type: text
cssClass: field-indent
field_values:
# label: 'janvince.smallcontactform::lang.settings.form_fields.validation'
prompt: 'janvince.smallcontactform::lang.settings.form_fields.add_values_prompt'
span: full
type: repeater
style: collapsed
cssClass: field-indent
trigger:
action: show
field: type
condition: value[dropdown]
form:
fields:
field_value_id:
span: left
label: 'janvince.smallcontactform::lang.settings.form_fields.field_value_id'
type: text
field_value_content:
span: right
label: 'janvince.smallcontactform::lang.settings.form_fields.field_value_content'
type: text
field_custom_code:
span: full
label: 'janvince.smallcontactform::lang.settings.form_fields.custom_code'
comment: 'janvince.smallcontactform::lang.settings.form_fields.custom_code_comment'
type: codeeditor
size: large
cssClass: field-indent
trigger:
action: show
field: type
condition: value[custom_code]
field_custom_code_twig:
span: left
label: 'janvince.smallcontactform::lang.settings.form_fields.custom_code_twig'
comment: 'janvince.smallcontactform::lang.settings.form_fields.custom_code_twig_comment'
type: checkbox
cssClass: field-indent
trigger:
action: show
field: type
condition: value[custom_code]
field_custom_code_line:
span: full
type: section
cssClass: field-indent
trigger:
action: show
field: type
condition: value[custom_code]
field_custom_content:
span: full
label: 'janvince.smallcontactform::lang.settings.form_fields.custom_content'
comment: 'janvince.smallcontactform::lang.settings.form_fields.custom_content_comment'
type: richeditor
size: large
cssClass: field-indent
trigger:
action: show
field: type
condition: value[custom_content]
field_custom_content_section:
span: full
type: section
cssClass: field-indent
trigger:
action: show
field: type
condition: value[custom_content]
field_styling:
label: 'janvince.smallcontactform::lang.settings.form_fields.field_styling'
comment: 'janvince.smallcontactform::lang.settings.form_fields.field_styling_comment'
span: left
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form_fields'
cssClass: field-indent
autofocus:
label: 'janvince.smallcontactform::lang.settings.form_fields.autofocus'
comment: 'janvince.smallcontactform::lang.settings.form_fields.autofocus_comment'
span: right
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.form_fields'
cssClass: field-indent
wrapper_css:
span: left
label: 'janvince.smallcontactform::lang.settings.form_fields.wrapper_css'
placeholder: 'janvince.smallcontactform::lang.settings.form_fields.wrapper_css_placeholder'
type: text
cssClass: field-indent
trigger:
action: show
field: field_styling
condition: checked
label_css:
span: left
label: 'janvince.smallcontactform::lang.settings.form_fields.label_css'
placeholder: 'janvince.smallcontactform::lang.settings.form_fields.label_css_placeholder'
type: text
cssClass: field-indent
trigger:
action: show
field: field_styling
condition: checked
field_css:
span: right
label: 'janvince.smallcontactform::lang.settings.form_fields.field_css'
placeholder: 'janvince.smallcontactform::lang.settings.form_fields.field_css_placeholder'
type: text
trigger:
action: show
field: field_styling
condition: checked
section_validation:
type: section
cssClass: field-indent
trigger:
action: show
field: field_styling
condition: checked
field_validation:
label: 'janvince.smallcontactform::lang.settings.form_fields.field_validation'
comment: 'janvince.smallcontactform::lang.settings.form_fields.field_validation_comment'
span: full
type: checkbox
cssClass: field-indent
validation:
# label: 'janvince.smallcontactform::lang.settings.form_fields.validation'
prompt: 'janvince.smallcontactform::lang.settings.form_fields.validation_prompt'
span: full
type: repeater
style: collapsed
cssClass: field-indent
trigger:
action: show
field: field_validation
condition: checked
form:
fields:
validation_type:
span: left
label: 'janvince.smallcontactform::lang.settings.form_fields.validation'
type: dropdown
emptyOption: 'janvince.smallcontactform::lang.settings.form_field_validation.select'
validation_error:
span: right
label: 'janvince.smallcontactform::lang.settings.form_fields.validation_error'
placeholder: 'janvince.smallcontactform::lang.settings.form_fields.validation_error_placeholder'
type: text
validation_custom_type:
span: left
label: 'janvince.smallcontactform::lang.settings.form_fields.validation_custom_type'
placeholder: 'janvince.smallcontactform::lang.settings.form_fields.validation_custom_type_placeholder'
comment: 'janvince.smallcontactform::lang.settings.form_fields.validation_custom_type_comment'
commentHtml: true
type: text
trigger:
action: show
field: validation_type
condition: value[custom]
validation_custom_pattern:
span: right
label: 'janvince.smallcontactform::lang.settings.form_fields.validation_custom_pattern'
placeholder: 'janvince.smallcontactform::lang.settings.form_fields.validation_custom_pattern_placeholder'
comment: 'janvince.smallcontactform::lang.settings.form_fields.validation_custom_pattern_comment'
type: text
trigger:
action: show
field: validation_type
condition: value[custom]
## MAPPING
autoreply_email_field:
label: 'janvince.smallcontactform::lang.settings.email.autoreply_email_field'
commentHtml: true
comment: 'janvince.smallcontactform::lang.settings.email.autoreply_email_field_comment'
span: left
type: dropdown
tab: 'janvince.smallcontactform::lang.settings.tabs.mapping'
emptyOption: 'janvince.smallcontactform::lang.settings.email.autoreply_email_field_empty_option'
partial_mapping:
type: partial
path: $/janvince/smallcontactform/models/settings/_mapping_help.htm
span: right
tab: 'janvince.smallcontactform::lang.settings.tabs.mapping'
autoreply_name_field:
label: 'janvince.smallcontactform::lang.settings.email.autoreply_name_field'
commentHtml: true
comment: 'janvince.smallcontactform::lang.settings.email.autoreply_name_field_comment'
span: left
type: dropdown
tab: 'janvince.smallcontactform::lang.settings.tabs.mapping'
emptyOption: 'janvince.smallcontactform::lang.settings.email.autoreply_name_field_empty_option'
autoreply_message_field:
label: 'janvince.smallcontactform::lang.settings.email.autoreply_message_field'
commentHtml: true
comment: 'janvince.smallcontactform::lang.settings.email.autoreply_message_field_comment'
span: left
type: dropdown
tab: 'janvince.smallcontactform::lang.settings.tabs.mapping'
emptyOption: 'janvince.smallcontactform::lang.settings.email.autoreply_message_field_empty_option'
partial_mapping_warning:
type: partial
path: $/janvince/smallcontactform/models/settings/_mapping_warning.htm
span: right
tab: 'janvince.smallcontactform::lang.settings.tabs.mapping'
## ANTISPAM
add_google_recaptcha:
label: 'janvince.smallcontactform::lang.settings.antispam.add_google_recaptcha'
comment: 'janvince.smallcontactform::lang.settings.antispam.add_google_recaptcha_comment'
commentHtml: true
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
google_recaptcha_version:
label: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_version'
comment: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_version_comment'
commentHtml: true
span: left
type: dropdown
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
options:
v2checkbox: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_versions.v2checkbox'
v2invisible: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_versions.v2invisible'
trigger:
action: show
field: add_google_recaptcha
condition: checked
google_recaptcha_site_key:
label: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_site_key'
comment: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_site_key_comment'
commentHtml: true
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_google_recaptcha
condition: checked
google_recaptcha_secret_key:
label: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_secret_key'
comment: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_secret_key_comment'
span: right
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_google_recaptcha
condition: checked
google_recaptcha_error_msg:
label: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_error_msg'
comment: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_error_msg_comment'
placeholder: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_error_msg_placeholder'
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_google_recaptcha
condition: checked
google_recaptcha_wrapper_css:
label: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_wrapper_css'
comment: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_wrapper_css_comment'
placeholder: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_wrapper_css_placeholder'
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_google_recaptcha
condition: checked
google_recaptcha_scripts_allow:
label: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_scripts_allow'
comment: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_scripts_allow_comment'
span: left
type: checkbox
default: false
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_google_recaptcha
condition: checked
google_recaptcha_locale_allow:
label: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_locale_allow'
comment: 'janvince.smallcontactform::lang.settings.antispam.google_recaptcha_locale_allow_comment'
span: left
type: checkbox
default: false
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_google_recaptcha
condition: checked
section_google_recaptcha:
type: section
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
trigger:
action: show
field: add_google_recaptcha
condition: checked
section_disabled_extensions:
type: section
label: 'janvince.smallcontactform::lang.settings.antispam.disabled_extensions'
comment: 'janvince.smallcontactform::lang.settings.antispam.disabled_extensions_comment'
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
trigger:
action: show
field: privacy_disable_messages_saving
condition: checked
add_antispam:
label: 'janvince.smallcontactform::lang.settings.antispam.add_antispam'
comment: 'janvince.smallcontactform::lang.settings.antispam.add_antispam_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
antispam_delay:
label: 'janvince.smallcontactform::lang.settings.antispam.antispam_delay'
comment: 'janvince.smallcontactform::lang.settings.antispam.antispam_delay_comment'
placeholder: 'janvince.smallcontactform::lang.settings.antispam.antispam_delay_placeholder'
span: left
type: number
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_antispam
condition: checked
antispam_delay_error_msg:
label: 'janvince.smallcontactform::lang.settings.antispam.antispam_delay_error_msg'
comment: 'janvince.smallcontactform::lang.settings.antispam.antispam_delay_error_msg_comment'
placeholder: 'janvince.smallcontactform::lang.settings.antispam.antispam_delay_error_msg_placeholder'
span: right
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_antispam
condition: checked
antispam_label:
label: 'janvince.smallcontactform::lang.settings.antispam.antispam_label'
comment: 'janvince.smallcontactform::lang.settings.antispam.antispam_label_comment'
placeholder: 'janvince.smallcontactform::lang.settings.antispam.antispam_label_placeholder'
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_antispam
condition: checked
antispam_error_msg:
label: 'janvince.smallcontactform::lang.settings.antispam.antispam_error_msg'
comment: 'janvince.smallcontactform::lang.settings.antispam.antispam_error_msg_comment'
placeholder: 'janvince.smallcontactform::lang.settings.antispam.antispam_error_msg_placeholder'
span: right
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_antispam
condition: checked
section_ip_protection:
type: section
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
trigger:
action: show
field: add_antispam
condition: checked
add_ip_protection:
label: 'janvince.smallcontactform::lang.settings.antispam.add_ip_protection'
comment: 'janvince.smallcontactform::lang.settings.antispam.add_ip_protection_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
trigger:
action: disable
field: privacy_disable_messages_saving
condition: checked
add_ip_protection_count:
label: 'janvince.smallcontactform::lang.settings.antispam.add_ip_protection_count'
comment: 'janvince.smallcontactform::lang.settings.antispam.add_ip_protection_count_comment'
placeholder: 'janvince.smallcontactform::lang.settings.antispam.add_ip_protection_count_placeholder'
span: left
type: number
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_ip_protection
condition: checked
add_ip_protection_error_too_many_submits:
label: 'janvince.smallcontactform::lang.settings.antispam.add_ip_protection_error_too_many_submits'
comment: 'janvince.smallcontactform::lang.settings.antispam.add_ip_protection_error_too_many_submits_comment'
placeholder: 'janvince.smallcontactform::lang.settings.antispam.add_ip_protection_error_too_many_submits_placeholder'
span: right
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.antispam'
cssClass: field-indent
trigger:
action: show
field: add_ip_protection
condition: checked
## EMAILS
allow_email_queue:
label: 'janvince.smallcontactform::lang.settings.email.allow_email_queue'
comment: 'janvince.smallcontactform::lang.settings.email.allow_email_queue_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
section_autoreply:
type: section
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
trigger:
action: show
field: allow_autoreply
condition: checked
allow_autoreply:
label: 'janvince.smallcontactform::lang.settings.email.allow_autoreply'
comment: 'janvince.smallcontactform::lang.settings.email.allow_autoreply_comment'
span: left
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
email_address_from:
label: 'janvince.smallcontactform::lang.settings.email.address_from'
span: left
type: text
placeholder: 'janvince.smallcontactform::lang.settings.email.address_from_placeholder'
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
cssClass: field-indent
trigger:
action: show
field: allow_autoreply
condition: checked
email_address_from_name:
label: 'janvince.smallcontactform::lang.settings.email.address_from_name'
span: right
type: text
placeholder: 'janvince.smallcontactform::lang.settings.email.address_from_name_placeholder'
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
cssClass: field-indent
trigger:
action: show
field: allow_autoreply
condition: checked
email_address_replyto:
label: 'janvince.smallcontactform::lang.settings.email.address_replyto'
span: left
type: text
placeholder: 'janvince.smallcontactform::lang.settings.email.address_from_placeholder'
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
cssClass: field-indent
trigger:
action: show
field: allow_autoreply
condition: checked
email_subject:
label: 'janvince.smallcontactform::lang.settings.email.subject'
comment: 'janvince.smallcontactform::lang.settings.email.subject_comment'
span: full
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
cssClass: field-indent
trigger:
action: show
field: allow_autoreply
condition: checked
email_template:
label: 'janvince.smallcontactform::lang.settings.email.template'
comment: 'janvince.smallcontactform::lang.settings.email.template_comment'
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
cssClass: field-indent
trigger:
action: show
field: allow_autoreply
condition: checked
section_notify:
type: section
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
trigger:
action: show
field: allow_notifications
condition: checked
allow_notifications:
label: 'janvince.smallcontactform::lang.settings.email.allow_notifications'
comment: 'janvince.smallcontactform::lang.settings.email.allow_notifications_comment'
span: left
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
notification_address_from_form:
label: 'janvince.smallcontactform::lang.settings.email.notification_address_from_form'
comment: 'janvince.smallcontactform::lang.settings.email.notification_address_from_form_comment'
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
cssClass: field-indent
trigger:
action: show
field: allow_notifications
condition: checked
notification_address_to:
label: 'janvince.smallcontactform::lang.settings.email.notification_address_to'
comment: 'janvince.smallcontactform::lang.settings.email.notification_address_to_comment'
span: left
type: text
placeholder: 'janvince.smallcontactform::lang.settings.email.notification_address_to_placeholder'
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
cssClass: field-indent
trigger:
action: show
field: allow_notifications
condition: checked
notification_template:
label: 'janvince.smallcontactform::lang.settings.email.notification_template'
comment: 'janvince.smallcontactform::lang.settings.email.notification_template_comment'
span: left
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.email'
cssClass: field-indent
trigger:
action: show
field: allow_notifications
condition: checked
## Google Analytics
section_ga_events:
type: section
label: 'janvince.smallcontactform::lang.settings.sections.ga_events'
tab: 'janvince.smallcontactform::lang.settings.tabs.ga'
ga_success_event_allow:
label: 'janvince.smallcontactform::lang.settings.ga.ga_success_event_allow'
span: left
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.ga'
ga_success_event_gtag:
label: 'janvince.smallcontactform::lang.settings.ga.ga_success_event_gtag'
span: left
type: dropdown
defaut: 'gtag'
cssClass: field-indent
emptyOption: 'janvince.smallcontactform::lang.settings.ga.ga_success_event_gtag_empty_option'
options:
gtag: 'janvince.smallcontactform::lang.settings.ga.ga_success_event_gtag_gtag'
ga: 'janvince.smallcontactform::lang.settings.ga.ga_success_event_gtag_ga'
tab: 'janvince.smallcontactform::lang.settings.tabs.ga'
ga_success_event_category:
label: 'janvince.smallcontactform::lang.settings.form_fields.event_category'
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.ga'
cssClass: field-indent
trigger:
action: show
field: ga_success_event_allow
condition: checked
ga_success_event_action:
label: 'janvince.smallcontactform::lang.settings.form_fields.event_action'
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.ga'
cssClass: field-indent
trigger:
action: show
field: ga_success_event_allow
condition: checked
ga_success_event_label:
label: 'janvince.smallcontactform::lang.settings.form_fields.event_label'
type: text
tab: 'janvince.smallcontactform::lang.settings.tabs.ga'
cssClass: field-indent
trigger:
action: show
field: ga_success_event_allow
condition: checked
## PRIVACY
privacy_disable_messages_saving:
label: 'janvince.smallcontactform::lang.settings.privacy.disable_messages_saving'
comment: 'janvince.smallcontactform::lang.settings.privacy.disable_messages_saving_comment'
commentHtml: true
span: full
type: checkbox
tab: 'janvince.smallcontactform::lang.settings.tabs.privacy'
privacy_disable_messages_saving_section:
comment: 'janvince.smallcontactform::lang.settings.privacy.disable_messages_saving_comment_section'
commentHtml: true
span: full
type: section
cssClass: field-indent
tab: 'janvince.smallcontactform::lang.settings.tabs.privacy'
trigger:
action: show
field: privacy_disable_messages_saving
condition: checked

View File

@ -0,0 +1,27 @@
<?php
namespace JanVince\SmallContactForm\ReportWidgets;
use Backend\Classes\ReportWidgetBase;
use JanVince\SmallContactForm\Controllers\Messages as MessagesController;
/**
* Contact form sent messages report widget
*/
class Messages extends ReportWidgetBase
{
public function render()
{
return $this->makePartial('messages');
}
public function getRecordsStats($value){
$controller = new MessagesController;
return $controller->getRecordsStats($value);
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace JanVince\SmallContactForm\ReportWidgets;
use Backend\Classes\ReportWidgetBase;
use JanVince\SmallContactForm\Controllers\Messages as MessagesController;
/**
* Contact form sent messages report widget
*/
class NewMessage extends ReportWidgetBase
{
public function render()
{
return $this->makePartial('newmessage');
}
public function getRecordsStats($value){
$controller = new MessagesController;
return $controller->getRecordsStats($value);
}
}

View File

@ -0,0 +1,17 @@
<div class="report-widget">
<h3><?= e(trans('janvince.smallcontactform::lang.reportwidget.partials.messages.title')) ?></h3>
<a href="<?= Backend::url('janvince/smallcontactform/messages');?>">
<div
class="control-chart"
data-control="chart-bar"
data-size="200"
data-center-text="180">
<ul>
<li data-color="orange"><?= e(trans('janvince.smallcontactform::lang.reportwidget.partials.messages.messages_all')) ?> <span><?php echo($this->getRecordsStats('all_count')); ?></span></li>
<li data-color="#95b753"><?= e(trans('janvince.smallcontactform::lang.reportwidget.partials.messages.messages_new')) ?> <span><?php echo($this->getRecordsStats('new_count')); ?></span></li>
<li data-color="#d1d1d1"><?= e(trans('janvince.smallcontactform::lang.reportwidget.partials.messages.messages_read')) ?> <span><?php echo($this->getRecordsStats('read_count')); ?></span></li>
</ul>
</div>
</a>
</div>

View File

@ -0,0 +1,13 @@
<div class="report-widget">
<h3><?= e(trans('janvince.smallcontactform::lang.reportwidget.partials.new_message.title')) ?></h3>
<a href="<?= Backend::url('janvince/smallcontactform/messages');?>">
<div class="scoreboard-item title-value">
<p <?= ($this->getRecordsStats('new_count') > 0 ? 'class="positive"' : 'style="color: #d1d1d1;"'); ?>">
<span class="oc-icon-inbox oc-icon-2x"></span><strong><?= $this->getRecordsStats('new_count'); ?></strong>
</p>
<p class="description"><?= e(trans('janvince.smallcontactform::lang.reportwidget.partials.new_message.link_text')) ?></p>
</div>
</a>
</div>

View File

@ -0,0 +1,31 @@
<?php
namespace JanVince\SmallContactForm\Updates;
use Schema;
use October\Rain\Database\Updates\Migration;
class SmallContactFormTables_01 extends Migration
{
public function up()
{
Schema::create('janvince_smallcontactform_messages', function($table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->text('name')->nullable();
$table->text('email')->nullable();
$table->text('message')->nullable();
$table->text('form_data')->nullable();
$table->boolean('new_message')->default(1);
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('janvince_smallcontactform_messages');
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace JanVince\SmallContactForm\Updates;
use Schema;
use October\Rain\Database\Updates\Migration;
class SmallContactFormTables_02 extends Migration
{
public function up()
{
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->string('remote_ip')->nullable();
$table->index('remote_ip');
});
}
public function down()
{
if (Schema::hasColumn('janvince_smallcontactform_messages', 'remote_ip')) {
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->dropColumn('remote_ip');
});
}
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace JanVince\SmallContactForm\Updates;
use Schema;
use October\Rain\Database\Updates\Migration;
class SmallContactFormTables_03 extends Migration
{
public function up()
{
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->text('form_description')->nullable();
$table->string('form_alias')->nullable();
});
}
public function down()
{
if (Schema::hasColumn('janvince_smallcontactform_messages', 'form_description')) {
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->dropColumn('form_description');
});
}
if (Schema::hasColumn('janvince_smallcontactform_messages', 'form_alias')) {
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->dropColumn('form_alias');
});
}
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace JanVince\SmallContactForm\Updates;
use Schema;
use October\Rain\Database\Updates\Migration;
class SmallContactFormTables_04 extends Migration
{
public function up()
{
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->text('url')->nullable();
});
}
public function down()
{
if (Schema::hasColumn('janvince_smallcontactform_messages', 'form_description')) {
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->dropColumn('url');
});
}
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace JanVince\SmallContactForm\Updates;
use Schema;
use October\Rain\Database\Updates\Migration;
class SmallContactFormTables_05 extends Migration
{
public function up()
{
if (Schema::hasColumn('janvince_smallcontactform_messages', 'form_description'))
{
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->text('url', 2000)->nullable()->change();
});
}
}
public function down()
{
if (Schema::hasColumn('janvince_smallcontactform_messages', 'form_description'))
{
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->text('url')->nullable()->change();
});
}
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace JanVince\SmallContactForm\Updates;
use Schema;
use October\Rain\Database\Updates\Migration;
class SmallContactFormTables_06 extends Migration
{
public function up()
{
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->text('form_notes', 2000)->nullable();
});
}
public function down()
{
if (Schema::hasColumn('janvince_smallcontactform_messages', 'form_notes'))
{
Schema::table('janvince_smallcontactform_messages', function($table)
{
$table->dropColumn('form_notes');
});
}
}
}

View File

@ -0,0 +1,270 @@
1.0.0:
- "First version of Small Contact Form plugin"
- scf_tables.php
1.0.1:
- Fix form hiding after successful send
- Fix in README.md
1.0.2:
- Fix some typos and add LICENCE file (thanks Szabó Gergő)
1.1.0:
- Added function to delete records in Messages list
- Added permission to delete records
1.2.0:
- Added dashboard report widgets (Stats and New messages)
1.2.1:
- Mail templates now render values with {{ values|raw }}
1.2.2:
- Mail templates convert new lines to <br> with {{ values|raw|nl2br }}
1.2.3:
- Fields mapping moved to separate tab *Columns mapping*
1.2.4:
- Updated README.md with assets usage example
1.2.5:
- Added IP protection function (limit too many submits from one IP address)
- And Messages list column to show senders IP address (invisible by default)
- scf_tables_02.php
1.2.6:
- Fixed IP protection error message
1.2.7:
- Changed remote_ip column type to string
1.2.8:
- Added option to use placeholders instead of labels
1.3.0:
- Added translation support for Rainlab Translate plugin
- Fixed some typos
1.3.1:
- Added default value for getTranslated() method
1.3.2:
- Added custom send button wrapper class
1.4.0:
- Added redirect option after successful submit (internal and external URL)
1.4.1:
- Minor UI fix (thanks Szabó Gergő)
1.4.2:
- Added support for default translated mail templates (Czech and English for now)
1.4.3:
- Fixed translation of mail templates description in Settings > Mail templates
1.4.4:
- Fixed array of enabledLocales
1.4.5:
- Fixed email template check
- Added default EN locale to enabled locales array
1.4.6:
- Removed field type restriction for Fields mapping
1.4.7:
- Removed hardcoded date format for created_at column in messages list, updated README and added hungarian language (thanks Szabó Gergő for all this)
1.4.8:
- Changes to allow multiple use of contact form (form and message blocks has now unique IDs)
- Added checkbox field type
- Scoreboard last message time format (thanks Szabó Gergő)
1.4.9:
- Added scoreboard button to quickly open form settings
1.4.10:
- Fixed typo in lang filename
1.4.11:
- Added "fieldsDetails" array to all email templates to have access to field labels, types and more
- Updated default autoreply mail templates to include fieldsDetail array
- Added function to detect non-defined fields in sent data
- Updated README.md file
1.5.0:
- Added some component hacking options (override autoreply and notification emails and template, disable fields)
- Fixed some typos
- Updated README.md file
1.5.1:
- Fixed flash message visibility when where are some errors
1.5.2:
- Fixed flash error for IP protection visibility
1.5.3:
- Added option for notification emails to have FROM address set from contact form email field
1.5.4:
- Added option to mark selected messages as read
1.5.5:
- Changed JSON type for repeater DB column
1.5.6:
- Removed value attribute in textarea field
1.5.7:
- Added component alias to id attributes for multi-form usage
1.5.8:
- Fixed typo in lang files
1.5.9:
- Added direct link to messages list from dashboard widget
1.6.0:
- Added Google reCAPTCHA validation
1.6.1:
- Changed All messages large indicator to New messages in scoreboard
1.6.2:
- Removed reCAPTCHA hard coded locale string (thx kuzyk). Added settings option to allow locale detection.
1.7.0:
- Added option to specify <label> custom CSS class
1.7.1:
- Fixed 'text_preview' list field type truncate function (thx kuzyk)
1.7.2:
- Changed count() to mb_strlen() function in custom list type definition
1.8.0:
- Added option to disable built-in browser form validation. Added class 'is-invalid' for fields with error (as used Bootstrap 4).
1.9.0:
- Form registered as Page snippet to be used in Rainlab.Page content (thx BtzLeon)
1.9.1:
- REPLY TO address is now used for notification email by default. You can still force FROM address to be used (but this is not supported by all email systems!).
1.9.2:
- Fix problem when ReCaptcha field was logged as an undefined field to system log (thx LukeTowers)
1.9.3:
- Fixed label 'for' attribute to point to input ID (as required by specification)
1.10.0:
- Added form component hacks group (now only for disabling notification emails, more will come)
1.11.0:
- Added form fields alias and description (can be used to distinquish between more forms or to save extra data). More info in README file.
- scf_tables_03.php
1.11.1:
- Added form description field to message preview
1.12.0:
- Added Russian translation (thank Dinver)
1.12.1:
- Chanded input custom list column type for switch to prevent interaction with toolbar JS
1.13.1:
- Added form_alias and form_description variables to email (notification and autoreply) templates
1.13.2:
- Disabled placeholder attribute for checkbox
1.14.0:
- Added option to export messages list
1.14.1:
- Added permissions to export messages list
1.15.0:
- Added Privacy tab and new option to disable sent messages saving
1.15.1:
- Fixed settings fields trigger
1.15.2:
- Fixed default values for recaptcha settings to false
1.15.3:
- Allowed combination of disabled messages saving and allowed passive antispam
1.16.0:
- Added option to have more than one notification email address
1.16.1:
- Fixed missing form data in autoreply templates. Updated default autoreply messages.
1.16.2:
- Updated hungarian translation (thx gergo85)
1.16.3:
- Fixed checkbox validation and validation state
1.17.0:
- Added Slovak translation (thx vosco88)
1.18.0:
- Added French translations (thx FelixINX)
1.19.0:
- Added custom validation fields (thanks petr-vytlacil for help)
1.20.0:
- Added dropdown field type
1.21.0:
- Form fields repeater is now translatable
1.22.0:
- Fixed multiple flash messages shown
1.23.0:
- When placeholders are used, labels are now still present and only hidden by style attribute
1.24.0:
- Added option to set custom reCaptcha wrapper CSS class
1.25.0:
- Added polish (thanks Magiczne) and spanish (thanks codibit) translations
1.30.0:
- Added invisible reCaptcha
1.30.1:
- Fixed reCaptcha scripts load
1.31.2:
- Fixed AJAX redirect when validation error (thanks zlobec)
1.31.3:
- Fixed reCaptcha checkbox version not showing up on older installations
1.31.4:
- Fixed unnecessary refresh after Ajax send (thanks cregx)
1.32.0:
- Added all settings overrides as regular component properties (can be used to override some form settings in multi-form setup)
- Updated documentation
1.32.1:
- Fixed test on empty values if some fields are disabled
1.40.0:
- Added validation rule custom_not_regex (inverse of default regex validation rule)
- Added form container with ID and action attribute with this hash URL (to automatically jump to form after nonAJAX send or refresh)
1.40.1:
- Fixed notification From name to be correctly set from component properties (thanks @pavsid)
1.41.0:
- Added component redirect properties and allow dynamic redirect URL as a component markup parameter. More info in README file.
- Removed hard coded form hash URL (#scf-[form-alias]) as this can be now easily added with redirect options.
1.41.1:
- Set redirect URL property default value to null.
1.42.0:
- Added Google Analytics events after form is successfully sent
- Do not populate redirection field code when redirection is not allowed
1.43.0:
- Rewritten component partials. No action is needed if you use plugin as is. But if you override component partials test them before update!
1.44.0:
- Added component properties to override notification and autoreply email subject (with support for Twig variables)
1.45.0:
- Added German translation (thanks NiklasDah)
1.46.0:
- Fixed backend validation for reCaptcha invisible
1.47.0:
- Added Custom code and Custom content field types
- Updated README
1.47.1:
- Fixed typo in README (wrong component redirection parameter name)
1.47.2:
- Fixed checkbox validation (thanks Chocofede)
1.47.3:
- Removed unnecessarry name attribute from custom_content field
1.47.4:
- Fixed typo in field attributes
1.48.0:
- Added option to set ReplyTo email address for autoreply emails
1.48.1:
- Fixed autoreply email addresses checks
1.48.2:
- Fixed empty ReplyTo field error
1.48.3:
- Fixed getFieldHtmlCode method (thanks sdlb)
1.49.0:
- Fixed missing description and redirect url after AJAX calls
- Fields forms in backend are now collapsed by default for better visibility
1.50.0:
- Auto store form request URL in DB (is available also in Mail templates)
- scf_tables_04.php
1.50.1:
- Removed unnecessarry debug log
1.51.0:
- Added support for (one or many) file uploads
- Fixed AJAX validation
- Updated README
1.51.1:
- Removed uploads array from default fields sent to autoreply template
1.51.2:
- Fixed uploads field in email messages
1.51.3:
- Changed size of database column url (thanks zlobec)
- scf_tables_05.php
1.51.4:
- Fixed passive antispam delay validation
1.52.0:
- Changed reCaptcha validation to work with allow_url_fopen disabled
1.52.1:
- Fixed project git files
1.53.0:
- Added option to choose tag for Analytics event (analytics.js (oridinal) or gtag.js)
1.54.0:
- Added option to add notes for form
1.55.0:
- Form notes will be saved to database with message
- scf_tables_06.php
1.55.1:
- Fixed migrations
1.55.2:
- Added reCaptcha check (thanks @kavishdahekar)
1.55.3:
- Fixed PHP8 compatibility (thanks @kavishdahekar)
1.55.4:
- Removed unnecessary side panel (thanks @TimFoerster)
1.55.5:
- Fixed gtag event code after form sent
1.55.6:
- Fixed yaml for OC3 installation
1.55.7:
- Removed optional parametr in sendAutoreplyEmail (thanks @TimFoerster)
1.56.0:
- Added Finnish language (thanks @mediaclinic)
1.56.1:
- Fixed XSS vulnerability (thanks lex0r)

View File

@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit27d394c7526e9a74451bd4dc314fca57::getLoader();

View File

@ -0,0 +1,445 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

View File

@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,9 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@ -0,0 +1,11 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'ReCaptcha\\' => array($vendorDir . '/google/recaptcha/src/ReCaptcha'),
'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'),
);

View File

@ -0,0 +1,55 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit27d394c7526e9a74451bd4dc314fca57
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit27d394c7526e9a74451bd4dc314fca57', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit27d394c7526e9a74451bd4dc314fca57', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit27d394c7526e9a74451bd4dc314fca57::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}

View File

@ -0,0 +1,39 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit27d394c7526e9a74451bd4dc314fca57
{
public static $prefixLengthsPsr4 = array (
'R' =>
array (
'ReCaptcha\\' => 10,
),
'C' =>
array (
'Composer\\Installers\\' => 20,
),
);
public static $prefixDirsPsr4 = array (
'ReCaptcha\\' =>
array (
0 => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha',
),
'Composer\\Installers\\' =>
array (
0 => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers',
),
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit27d394c7526e9a74451bd4dc314fca57::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit27d394c7526e9a74451bd4dc314fca57::$prefixDirsPsr4;
}, null, ClassLoader::class);
}
}

View File

@ -0,0 +1,198 @@
[
{
"name": "composer/installers",
"version": "dev-main",
"version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/composer/installers.git",
"reference": "1b94b414035400a8be5c694048a0e711a86b1080"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/installers/zipball/1b94b414035400a8be5c694048a0e711a86b1080",
"reference": "1b94b414035400a8be5c694048a0e711a86b1080",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0"
},
"replace": {
"roundcube/plugin-installer": "*",
"shama/baton": "*"
},
"require-dev": {
"composer/composer": "1.6.* || ^2.0",
"composer/semver": "^1 || ^3",
"phpstan/phpstan": "^0.12.55",
"phpstan/phpstan-phpunit": "^0.12.16",
"symfony/phpunit-bridge": "^4.2 || ^5",
"symfony/process": "^2.3"
},
"time": "2021-03-08T12:02:54+00:00",
"type": "composer-plugin",
"extra": {
"class": "Composer\\Installers\\Plugin",
"branch-alias": {
"dev-main": "1.x-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-4": {
"Composer\\Installers\\": "src/Composer/Installers"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kyle Robinson Young",
"email": "kyle@dontkry.com",
"homepage": "https://github.com/shama"
}
],
"description": "A multi-framework Composer library installer",
"homepage": "https://composer.github.io/installers/",
"keywords": [
"Craft",
"Dolibarr",
"Eliasis",
"Hurad",
"ImageCMS",
"Kanboard",
"Lan Management System",
"MODX Evo",
"MantisBT",
"Mautic",
"Maya",
"OXID",
"Plentymarkets",
"Porto",
"RadPHP",
"SMF",
"Starbug",
"Thelia",
"Whmcs",
"WolfCMS",
"agl",
"aimeos",
"annotatecms",
"attogram",
"bitrix",
"cakephp",
"chef",
"cockpit",
"codeigniter",
"concrete5",
"croogo",
"dokuwiki",
"drupal",
"eZ Platform",
"elgg",
"expressionengine",
"fuelphp",
"grav",
"installer",
"itop",
"joomla",
"known",
"kohana",
"laravel",
"lavalite",
"lithium",
"magento",
"majima",
"mako",
"mediawiki",
"modulework",
"modx",
"moodle",
"osclass",
"phpbb",
"piwik",
"ppi",
"processwire",
"puppet",
"pxcms",
"reindex",
"roundcube",
"shopware",
"silverstripe",
"sydes",
"sylius",
"symfony",
"tastyigniter",
"typo3",
"wordpress",
"yawik",
"zend",
"zikula"
],
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
]
},
{
"name": "google/recaptcha",
"version": "dev-master",
"version_normalized": "9999999-dev",
"source": {
"type": "git",
"url": "https://github.com/google/recaptcha.git",
"reference": "f911286ad361c9fba1b422c07f040852c0c193a3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/google/recaptcha/zipball/f911286ad361c9fba1b422c07f040852c0c193a3",
"reference": "f911286ad361c9fba1b422c07f040852c0c193a3",
"shasum": ""
},
"require": {
"php": ">=5.5"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.2.20|^2.15",
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^4.8.36|^5.7.27|^6.59|^7.5.11"
},
"time": "2020-10-01T15:14:41+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-4": {
"ReCaptcha\\": "src/ReCaptcha"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Client library for reCAPTCHA, a free service that protects websites from spam and abuse.",
"homepage": "https://www.google.com/recaptcha/",
"keywords": [
"Abuse",
"captcha",
"recaptcha",
"spam"
]
}
]

View File

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2019, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,140 @@
# reCAPTCHA PHP client library
[![Build Status](https://travis-ci.org/google/recaptcha.svg)](https://travis-ci.org/google/recaptcha)
[![Coverage Status](https://coveralls.io/repos/github/google/recaptcha/badge.svg)](https://coveralls.io/github/google/recaptcha)
[![Latest Stable Version](https://poser.pugx.org/google/recaptcha/v/stable.svg)](https://packagist.org/packages/google/recaptcha)
[![Total Downloads](https://poser.pugx.org/google/recaptcha/downloads.svg)](https://packagist.org/packages/google/recaptcha)
reCAPTCHA is a free CAPTCHA service that protects websites from spam and abuse.
This is a PHP library that wraps up the server-side verification step required
to process responses from the reCAPTCHA service. This client supports both v2
and v3.
- reCAPTCHA: https://www.google.com/recaptcha
- This repo: https://github.com/google/recaptcha
- Hosted demo: https://recaptcha-demo.appspot.com/
- Version: 1.2.4
- License: BSD, see [LICENSE](LICENSE)
## Installation
### Composer (recommended)
Use [Composer](https://getcomposer.org) to install this library from Packagist:
[`google/recaptcha`](https://packagist.org/packages/google/recaptcha)
Run the following command from your project directory to add the dependency:
```sh
composer require google/recaptcha "^1.2"
```
Alternatively, add the dependency directly to your `composer.json` file:
```json
"require": {
"google/recaptcha": "^1.2"
}
```
### Direct download
Download the [ZIP file](https://github.com/google/recaptcha/archive/master.zip)
and extract into your project. An autoloader script is provided in
`src/autoload.php` which you can require into your script. For example:
```php
require_once '/path/to/recaptcha/src/autoload.php';
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
```
The classes in the project are structured according to the
[PSR-4](http://www.php-fig.org/psr/psr-4/) standard, so you can also use your
own autoloader or require the needed files directly in your code.
## Usage
First obtain the appropriate keys for the type of reCAPTCHA you wish to
integrate for v2 at https://www.google.com/recaptcha/admin or v3 at
https://g.co/recaptcha/v3.
Then follow the [integration guide on the developer
site](https://developers.google.com/recaptcha/intro) to add the reCAPTCHA
functionality into your frontend.
This library comes in when you need to verify the user's response. On the PHP
side you need the response from the reCAPTCHA service and secret key from your
credentials. Instantiate the `ReCaptcha` class with your secret key, specify any
additional validation rules, and then call `verify()` with the reCAPTCHA
response and user's IP address. For example:
```php
<?php
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$resp = $recaptcha->setExpectedHostname('recaptcha-demo.appspot.com')
->verify($gRecaptchaResponse, $remoteIp);
if ($resp->isSuccess()) {
// Verified!
} else {
$errors = $resp->getErrorCodes();
}
```
The following methods are available:
- `setExpectedHostname($hostname)`: ensures the hostname matches. You must do
this if you have disabled "Domain/Package Name Validation" for your
credentials.
- `setExpectedApkPackageName($apkPackageName)`: if you're verifying a response
from an Android app. Again, you must do this if you have disabled
"Domain/Package Name Validation" for your credentials.
- `setExpectedAction($action)`: ensures the action matches for the v3 API.
- `setScoreThreshold($threshold)`: set a score threshold for responses from the
v3 API
- `setChallengeTimeout($timeoutSeconds)`: set a timeout between the user passing
the reCAPTCHA and your server processing it.
Each of the `set`\*`()` methods return the `ReCaptcha` instance so you can chain
them together. For example:
```php
<?php
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$resp = $recaptcha->setExpectedHostname('recaptcha-demo.appspot.com')
->setExpectedAction('homepage')
->setScoreThreshold(0.5)
->verify($gRecaptchaResponse, $remoteIp);
if ($resp->isSuccess()) {
// Verified!
} else {
$errors = $resp->getErrorCodes();
}
```
You can find the constants for the libraries error codes in the `ReCaptcha`
class constants, e.g. `ReCaptcha::E_HOSTNAME_MISMATCH`
For more details on usage and structure, see [ARCHITECTURE](ARCHITECTURE.md).
### Examples
You can see examples of each reCAPTCHA type in [examples/](examples/). You can
run the examples locally by using the Composer script:
```sh
composer run-script serve-examples
```
This makes use of the in-built PHP dev server to host the examples at
http://localhost:8080/
These are also hosted on Google AppEngine Flexible environment at
https://recaptcha-demo.appspot.com/. This is configured by
[`app.yaml`](./app.yaml) which you can also use to [deploy to your own AppEngine
project](https://cloud.google.com/appengine/docs/flexible/php/download).
## Contributing
No one ever has enough engineers, so we're very happy to accept contributions
via Pull Requests. For details, see [CONTRIBUTING](CONTRIBUTING.md)

View File

@ -0,0 +1,39 @@
{
"name": "google/recaptcha",
"description": "Client library for reCAPTCHA, a free service that protects websites from spam and abuse.",
"type": "library",
"keywords": ["recaptcha", "captcha", "spam", "abuse"],
"homepage": "https://www.google.com/recaptcha/",
"license": "BSD-3-Clause",
"support": {
"forum": "https://groups.google.com/forum/#!forum/recaptcha",
"source": "https://github.com/google/recaptcha"
},
"require": {
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36|^5.7.27|^6.59|^7.5.11",
"friendsofphp/php-cs-fixer": "^2.2.20|^2.15",
"php-coveralls/php-coveralls": "^2.1"
},
"autoload": {
"psr-4": {
"ReCaptcha\\": "src/ReCaptcha"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"scripts": {
"lint": "vendor/bin/php-cs-fixer -vvv fix --using-cache=no --dry-run .",
"lint-fix": "vendor/bin/php-cs-fixer -vvv fix --using-cache=no .",
"test": "vendor/bin/phpunit --colors=always",
"serve-examples": "@php -S localhost:8080 -t examples"
},
"config": {
"process-timeout": 0
}
}

View File

@ -0,0 +1,269 @@
<?php
/**
* This is a PHP library that handles calling reCAPTCHA.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace ReCaptcha;
/**
* reCAPTCHA client.
*/
class ReCaptcha
{
/**
* Version of this client library.
* @const string
*/
const VERSION = 'php_1.2.4';
/**
* URL for reCAPTCHA siteverify API
* @const string
*/
const SITE_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
/**
* Invalid JSON received
* @const string
*/
const E_INVALID_JSON = 'invalid-json';
/**
* Could not connect to service
* @const string
*/
const E_CONNECTION_FAILED = 'connection-failed';
/**
* Did not receive a 200 from the service
* @const string
*/
const E_BAD_RESPONSE = 'bad-response';
/**
* Not a success, but no error codes received!
* @const string
*/
const E_UNKNOWN_ERROR = 'unknown-error';
/**
* ReCAPTCHA response not provided
* @const string
*/
const E_MISSING_INPUT_RESPONSE = 'missing-input-response';
/**
* Expected hostname did not match
* @const string
*/
const E_HOSTNAME_MISMATCH = 'hostname-mismatch';
/**
* Expected APK package name did not match
* @const string
*/
const E_APK_PACKAGE_NAME_MISMATCH = 'apk_package_name-mismatch';
/**
* Expected action did not match
* @const string
*/
const E_ACTION_MISMATCH = 'action-mismatch';
/**
* Score threshold not met
* @const string
*/
const E_SCORE_THRESHOLD_NOT_MET = 'score-threshold-not-met';
/**
* Challenge timeout
* @const string
*/
const E_CHALLENGE_TIMEOUT = 'challenge-timeout';
/**
* Shared secret for the site.
* @var string
*/
private $secret;
/**
* Method used to communicate with service. Defaults to POST request.
* @var RequestMethod
*/
private $requestMethod;
/**
* Create a configured instance to use the reCAPTCHA service.
*
* @param string $secret The shared key between your site and reCAPTCHA.
* @param RequestMethod $requestMethod method used to send the request. Defaults to POST.
* @throws \RuntimeException if $secret is invalid
*/
public function __construct($secret, RequestMethod $requestMethod = null)
{
if (empty($secret)) {
throw new \RuntimeException('No secret provided');
}
if (!is_string($secret)) {
throw new \RuntimeException('The provided secret must be a string');
}
$this->secret = $secret;
$this->requestMethod = (is_null($requestMethod)) ? new RequestMethod\Post() : $requestMethod;
}
/**
* Calls the reCAPTCHA siteverify API to verify whether the user passes
* CAPTCHA test and additionally runs any specified additional checks
*
* @param string $response The user response token provided by reCAPTCHA, verifying the user on your site.
* @param string $remoteIp The end user's IP address.
* @return Response Response from the service.
*/
public function verify($response, $remoteIp = null)
{
// Discard empty solution submissions
if (empty($response)) {
$recaptchaResponse = new Response(false, array(self::E_MISSING_INPUT_RESPONSE));
return $recaptchaResponse;
}
$params = new RequestParameters($this->secret, $response, $remoteIp, self::VERSION);
$rawResponse = $this->requestMethod->submit($params);
$initialResponse = Response::fromJson($rawResponse);
$validationErrors = array();
if (isset($this->hostname) && strcasecmp($this->hostname, $initialResponse->getHostname()) !== 0) {
$validationErrors[] = self::E_HOSTNAME_MISMATCH;
}
if (isset($this->apkPackageName) && strcasecmp($this->apkPackageName, $initialResponse->getApkPackageName()) !== 0) {
$validationErrors[] = self::E_APK_PACKAGE_NAME_MISMATCH;
}
if (isset($this->action) && strcasecmp($this->action, $initialResponse->getAction()) !== 0) {
$validationErrors[] = self::E_ACTION_MISMATCH;
}
if (isset($this->threshold) && $this->threshold > $initialResponse->getScore()) {
$validationErrors[] = self::E_SCORE_THRESHOLD_NOT_MET;
}
if (isset($this->timeoutSeconds)) {
$challengeTs = strtotime($initialResponse->getChallengeTs());
if ($challengeTs > 0 && time() - $challengeTs > $this->timeoutSeconds) {
$validationErrors[] = self::E_CHALLENGE_TIMEOUT;
}
}
if (empty($validationErrors)) {
return $initialResponse;
}
return new Response(
false,
array_merge($initialResponse->getErrorCodes(), $validationErrors),
$initialResponse->getHostname(),
$initialResponse->getChallengeTs(),
$initialResponse->getApkPackageName(),
$initialResponse->getScore(),
$initialResponse->getAction()
);
}
/**
* Provide a hostname to match against in verify()
* This should be without a protocol or trailing slash, e.g. www.google.com
*
* @param string $hostname Expected hostname
* @return ReCaptcha Current instance for fluent interface
*/
public function setExpectedHostname($hostname)
{
$this->hostname = $hostname;
return $this;
}
/**
* Provide an APK package name to match against in verify()
*
* @param string $apkPackageName Expected APK package name
* @return ReCaptcha Current instance for fluent interface
*/
public function setExpectedApkPackageName($apkPackageName)
{
$this->apkPackageName = $apkPackageName;
return $this;
}
/**
* Provide an action to match against in verify()
* This should be set per page.
*
* @param string $action Expected action
* @return ReCaptcha Current instance for fluent interface
*/
public function setExpectedAction($action)
{
$this->action = $action;
return $this;
}
/**
* Provide a threshold to meet or exceed in verify()
* Threshold should be a float between 0 and 1 which will be tested as response >= threshold.
*
* @param float $threshold Expected threshold
* @return ReCaptcha Current instance for fluent interface
*/
public function setScoreThreshold($threshold)
{
$this->threshold = floatval($threshold);
return $this;
}
/**
* Provide a timeout in seconds to test against the challenge timestamp in verify()
*
* @param int $timeoutSeconds Expected hostname
* @return ReCaptcha Current instance for fluent interface
*/
public function setChallengeTimeout($timeoutSeconds)
{
$this->timeoutSeconds = $timeoutSeconds;
return $this;
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* This is a PHP library that handles calling reCAPTCHA.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace ReCaptcha;
/**
* Method used to send the request to the service.
*/
interface RequestMethod
{
/**
* Submit the request with the specified parameters.
*
* @param RequestParameters $params Request parameters
* @return string Body of the reCAPTCHA response
*/
public function submit(RequestParameters $params);
}

View File

@ -0,0 +1,82 @@
<?php
/**
* This is a PHP library that handles calling reCAPTCHA.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace ReCaptcha\RequestMethod;
/**
* Convenience wrapper around the cURL functions to allow mocking.
*/
class Curl
{
/**
* @see http://php.net/curl_init
* @param string $url
* @return resource cURL handle
*/
public function init($url = null)
{
return curl_init($url);
}
/**
* @see http://php.net/curl_setopt_array
* @param resource $ch
* @param array $options
* @return bool
*/
public function setoptArray($ch, array $options)
{
return curl_setopt_array($ch, $options);
}
/**
* @see http://php.net/curl_exec
* @param resource $ch
* @return mixed
*/
public function exec($ch)
{
return curl_exec($ch);
}
/**
* @see http://php.net/curl_close
* @param resource $ch
*/
public function close($ch)
{
curl_close($ch);
}
}

View File

@ -0,0 +1,104 @@
<?php
/**
* This is a PHP library that handles calling reCAPTCHA.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace ReCaptcha\RequestMethod;
use ReCaptcha\ReCaptcha;
use ReCaptcha\RequestMethod;
use ReCaptcha\RequestParameters;
/**
* Sends cURL request to the reCAPTCHA service.
* Note: this requires the cURL extension to be enabled in PHP
* @see http://php.net/manual/en/book.curl.php
*/
class CurlPost implements RequestMethod
{
/**
* Curl connection to the reCAPTCHA service
* @var Curl
*/
private $curl;
/**
* URL for reCAPTCHA siteverify API
* @var string
*/
private $siteVerifyUrl;
/**
* Only needed if you want to override the defaults
*
* @param Curl $curl Curl resource
* @param string $siteVerifyUrl URL for reCAPTCHA siteverify API
*/
public function __construct(Curl $curl = null, $siteVerifyUrl = null)
{
$this->curl = (is_null($curl)) ? new Curl() : $curl;
$this->siteVerifyUrl = (is_null($siteVerifyUrl)) ? ReCaptcha::SITE_VERIFY_URL : $siteVerifyUrl;
}
/**
* Submit the cURL request with the specified parameters.
*
* @param RequestParameters $params Request parameters
* @return string Body of the reCAPTCHA response
*/
public function submit(RequestParameters $params)
{
$handle = $this->curl->init($this->siteVerifyUrl);
$options = array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $params->toQueryString(),
CURLOPT_HTTPHEADER => array(
'Content-Type: application/x-www-form-urlencoded'
),
CURLINFO_HEADER_OUT => false,
CURLOPT_HEADER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true
);
$this->curl->setoptArray($handle, $options);
$response = $this->curl->exec($handle);
$this->curl->close($handle);
if ($response !== false) {
return $response;
}
return '{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}';
}
}

View File

@ -0,0 +1,88 @@
<?php
/**
* This is a PHP library that handles calling reCAPTCHA.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace ReCaptcha\RequestMethod;
use ReCaptcha\ReCaptcha;
use ReCaptcha\RequestMethod;
use ReCaptcha\RequestParameters;
/**
* Sends POST requests to the reCAPTCHA service.
*/
class Post implements RequestMethod
{
/**
* URL for reCAPTCHA siteverify API
* @var string
*/
private $siteVerifyUrl;
/**
* Only needed if you want to override the defaults
*
* @param string $siteVerifyUrl URL for reCAPTCHA siteverify API
*/
public function __construct($siteVerifyUrl = null)
{
$this->siteVerifyUrl = (is_null($siteVerifyUrl)) ? ReCaptcha::SITE_VERIFY_URL : $siteVerifyUrl;
}
/**
* Submit the POST request with the specified parameters.
*
* @param RequestParameters $params Request parameters
* @return string Body of the reCAPTCHA response
*/
public function submit(RequestParameters $params)
{
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => $params->toQueryString(),
// Force the peer to validate (not needed in 5.6.0+, but still works)
'verify_peer' => true,
),
);
$context = stream_context_create($options);
$response = file_get_contents($this->siteVerifyUrl, false, $context);
if ($response !== false) {
return $response;
}
return '{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}';
}
}

View File

@ -0,0 +1,112 @@
<?php
/**
* This is a PHP library that handles calling reCAPTCHA.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace ReCaptcha\RequestMethod;
/**
* Convenience wrapper around native socket and file functions to allow for
* mocking.
*/
class Socket
{
private $handle = null;
/**
* fsockopen
*
* @see http://php.net/fsockopen
* @param string $hostname
* @param int $port
* @param int $errno
* @param string $errstr
* @param float $timeout
* @return resource
*/
public function fsockopen($hostname, $port = -1, &$errno = 0, &$errstr = '', $timeout = null)
{
$this->handle = fsockopen($hostname, $port, $errno, $errstr, (is_null($timeout) ? ini_get("default_socket_timeout") : $timeout));
if ($this->handle != false && $errno === 0 && $errstr === '') {
return $this->handle;
}
return false;
}
/**
* fwrite
*
* @see http://php.net/fwrite
* @param string $string
* @param int $length
* @return int | bool
*/
public function fwrite($string, $length = null)
{
return fwrite($this->handle, $string, (is_null($length) ? strlen($string) : $length));
}
/**
* fgets
*
* @see http://php.net/fgets
* @param int $length
* @return string
*/
public function fgets($length = null)
{
return fgets($this->handle, $length);
}
/**
* feof
*
* @see http://php.net/feof
* @return bool
*/
public function feof()
{
return feof($this->handle);
}
/**
* fclose
*
* @see http://php.net/fclose
* @return bool
*/
public function fclose()
{
return fclose($this->handle);
}
}

View File

@ -0,0 +1,108 @@
<?php
/**
* This is a PHP library that handles calling reCAPTCHA.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace ReCaptcha\RequestMethod;
use ReCaptcha\ReCaptcha;
use ReCaptcha\RequestMethod;
use ReCaptcha\RequestParameters;
/**
* Sends a POST request to the reCAPTCHA service, but makes use of fsockopen()
* instead of get_file_contents(). This is to account for people who may be on
* servers where allow_url_open is disabled.
*/
class SocketPost implements RequestMethod
{
/**
* Socket to the reCAPTCHA service
* @var Socket
*/
private $socket;
/**
* Only needed if you want to override the defaults
*
* @param \ReCaptcha\RequestMethod\Socket $socket optional socket, injectable for testing
* @param string $siteVerifyUrl URL for reCAPTCHA siteverify API
*/
public function __construct(Socket $socket = null, $siteVerifyUrl = null)
{
$this->socket = (is_null($socket)) ? new Socket() : $socket;
$this->siteVerifyUrl = (is_null($siteVerifyUrl)) ? ReCaptcha::SITE_VERIFY_URL : $siteVerifyUrl;
}
/**
* Submit the POST request with the specified parameters.
*
* @param RequestParameters $params Request parameters
* @return string Body of the reCAPTCHA response
*/
public function submit(RequestParameters $params)
{
$errno = 0;
$errstr = '';
$urlParsed = parse_url($this->siteVerifyUrl);
if (false === $this->socket->fsockopen('ssl://' . $urlParsed['host'], 443, $errno, $errstr, 30)) {
return '{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}';
}
$content = $params->toQueryString();
$request = "POST " . $urlParsed['path'] . " HTTP/1.0\r\n";
$request .= "Host: " . $urlParsed['host'] . "\r\n";
$request .= "Content-Type: application/x-www-form-urlencoded\r\n";
$request .= "Content-length: " . strlen($content) . "\r\n";
$request .= "Connection: close\r\n\r\n";
$request .= $content . "\r\n\r\n";
$this->socket->fwrite($request);
$response = '';
while (!$this->socket->feof()) {
$response .= $this->socket->fgets(4096);
}
$this->socket->fclose();
if (0 !== strpos($response, 'HTTP/1.0 200 OK')) {
return '{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_RESPONSE.'"]}';
}
$parts = preg_split("#\n\s*\n#Uis", $response);
return $parts[1];
}
}

View File

@ -0,0 +1,111 @@
<?php
/**
* This is a PHP library that handles calling reCAPTCHA.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace ReCaptcha;
/**
* Stores and formats the parameters for the request to the reCAPTCHA service.
*/
class RequestParameters
{
/**
* The shared key between your site and reCAPTCHA.
* @var string
*/
private $secret;
/**
* The user response token provided by reCAPTCHA, verifying the user on your site.
* @var string
*/
private $response;
/**
* Remote user's IP address.
* @var string
*/
private $remoteIp;
/**
* Client version.
* @var string
*/
private $version;
/**
* Initialise parameters.
*
* @param string $secret Site secret.
* @param string $response Value from g-captcha-response form field.
* @param string $remoteIp User's IP address.
* @param string $version Version of this client library.
*/
public function __construct($secret, $response, $remoteIp = null, $version = null)
{
$this->secret = $secret;
$this->response = $response;
$this->remoteIp = $remoteIp;
$this->version = $version;
}
/**
* Array representation.
*
* @return array Array formatted parameters.
*/
public function toArray()
{
$params = array('secret' => $this->secret, 'response' => $this->response);
if (!is_null($this->remoteIp)) {
$params['remoteip'] = $this->remoteIp;
}
if (!is_null($this->version)) {
$params['version'] = $this->version;
}
return $params;
}
/**
* Query string representation for HTTP request.
*
* @return string Query string formatted parameters.
*/
public function toQueryString()
{
return http_build_query($this->toArray(), '', '&');
}
}

View File

@ -0,0 +1,218 @@
<?php
/**
* This is a PHP library that handles calling reCAPTCHA.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace ReCaptcha;
/**
* The response returned from the service.
*/
class Response
{
/**
* Success or failure.
* @var boolean
*/
private $success = false;
/**
* Error code strings.
* @var array
*/
private $errorCodes = array();
/**
* The hostname of the site where the reCAPTCHA was solved.
* @var string
*/
private $hostname;
/**
* Timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
* @var string
*/
private $challengeTs;
/**
* APK package name
* @var string
*/
private $apkPackageName;
/**
* Score assigned to the request
* @var float
*/
private $score;
/**
* Action as specified by the page
* @var string
*/
private $action;
/**
* Build the response from the expected JSON returned by the service.
*
* @param string $json
* @return \ReCaptcha\Response
*/
public static function fromJson($json)
{
$responseData = json_decode($json, true);
if (!$responseData) {
return new Response(false, array(ReCaptcha::E_INVALID_JSON));
}
$hostname = isset($responseData['hostname']) ? $responseData['hostname'] : null;
$challengeTs = isset($responseData['challenge_ts']) ? $responseData['challenge_ts'] : null;
$apkPackageName = isset($responseData['apk_package_name']) ? $responseData['apk_package_name'] : null;
$score = isset($responseData['score']) ? floatval($responseData['score']) : null;
$action = isset($responseData['action']) ? $responseData['action'] : null;
if (isset($responseData['success']) && $responseData['success'] == true) {
return new Response(true, array(), $hostname, $challengeTs, $apkPackageName, $score, $action);
}
if (isset($responseData['error-codes']) && is_array($responseData['error-codes'])) {
return new Response(false, $responseData['error-codes'], $hostname, $challengeTs, $apkPackageName, $score, $action);
}
return new Response(false, array(ReCaptcha::E_UNKNOWN_ERROR), $hostname, $challengeTs, $apkPackageName, $score, $action);
}
/**
* Constructor.
*
* @param boolean $success
* @param string $hostname
* @param string $challengeTs
* @param string $apkPackageName
* @param float $score
* @param string $action
* @param array $errorCodes
*/
public function __construct($success, array $errorCodes = array(), $hostname = null, $challengeTs = null, $apkPackageName = null, $score = null, $action = null)
{
$this->success = $success;
$this->hostname = $hostname;
$this->challengeTs = $challengeTs;
$this->apkPackageName = $apkPackageName;
$this->score = $score;
$this->action = $action;
$this->errorCodes = $errorCodes;
}
/**
* Is success?
*
* @return boolean
*/
public function isSuccess()
{
return $this->success;
}
/**
* Get error codes.
*
* @return array
*/
public function getErrorCodes()
{
return $this->errorCodes;
}
/**
* Get hostname.
*
* @return string
*/
public function getHostname()
{
return $this->hostname;
}
/**
* Get challenge timestamp
*
* @return string
*/
public function getChallengeTs()
{
return $this->challengeTs;
}
/**
* Get APK package name
*
* @return string
*/
public function getApkPackageName()
{
return $this->apkPackageName;
}
/**
* Get score
*
* @return float
*/
public function getScore()
{
return $this->score;
}
/**
* Get action
*
* @return string
*/
public function getAction()
{
return $this->action;
}
public function toArray()
{
return array(
'success' => $this->isSuccess(),
'hostname' => $this->getHostname(),
'challenge_ts' => $this->getChallengeTs(),
'apk_package_name' => $this->getApkPackageName(),
'score' => $this->getScore(),
'action' => $this->getAction(),
'error-codes' => $this->getErrorCodes(),
);
}
}

View File

@ -0,0 +1,69 @@
<?php
/* An autoloader for ReCaptcha\Foo classes. This should be required()
* by the user before attempting to instantiate any of the ReCaptcha
* classes.
*
* BSD 3-Clause License
* @copyright (c) 2019, Google Inc.
* @link https://www.google.com/recaptcha
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
spl_autoload_register(function ($class) {
if (substr($class, 0, 10) !== 'ReCaptcha\\') {
/* If the class does not lie under the "ReCaptcha" namespace,
* then we can exit immediately.
*/
return;
}
/* All of the classes have names like "ReCaptcha\Foo", so we need
* to replace the backslashes with frontslashes if we want the
* name to map directly to a location in the filesystem.
*/
$class = str_replace('\\', '/', $class);
/* First, check under the current directory. It is important that
* we look here first, so that we don't waste time searching for
* test classes in the common case.
*/
$path = dirname(__FILE__).'/'.$class.'.php';
if (is_readable($path)) {
require_once $path;
return;
}
/* If we didn't find what we're looking for already, maybe it's
* a test class?
*/
$path = dirname(__FILE__).'/../tests/'.$class.'.php';
if (is_readable($path)) {
require_once $path;
}
});

View File

@ -0,0 +1,77 @@
subject = "Contact form confirmation"
==
Hello,
this is a confirmation from Contact form.
{% if fieldsDetails|length %}
You have sent this:
<table border="0">
<tbody>
{% for field in fieldsDetails %}
{% if field.label == 'form_description' or field.label == 'form_alias' %}
{% else %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
<th>{{field.label}}</th>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% endif %}
Best regards,
Contact form
==
<p>Hello,</p>
<p>this is a confirmation from Contact form.</p>
{% if fieldsDetails|length %}
<br>
<p>You have sent this:</p>
<table border="0">
<tbody>
{% for field in fieldsDetails %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<br>
<p>Best regards,<br>
Contact form</p>

View File

@ -0,0 +1,76 @@
subject = "Potvrzení doručení zprávy z kontaktního formuláře"
==
Dobrý den,
posíláme potvrzení přijetí vaší zprávy odeslané z kontaktního formuláře.
{% if fields|length %}
Vyplnil/a jste toto:
<table border="0">
<tbody>
{% for field in fieldsDetails %}
{% if field.label == 'form_description' or field.label == 'form_alias' %}
{% else %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% endif %}
S pozdravem,
Kontaktní formulář
==
<p>Dobrý den,</p>
<p>posíláme potvrzení přijetí vaší zprávy odeslané z kontaktního formuláře.</p>
{% if fields|length %}
<br>
<p>Vyplnil/a jste toto:</p>
<table border="0">
<tbody>
{% for field in fieldsDetails %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<br>
<p>S pozdravem,<br>
Kontaktní formulář</p>

View File

@ -0,0 +1,77 @@
subject = "Confirmación del formulario de contacto"
==
Hola,
esto es una confirmación del formulario de contacto.
{% if fieldsDetails|length %}
Ha enviado lo siguiente:
<table border="0">
<tbody>
{% for field in fieldsDetails %}
{% if field.label == 'form_description' or field.label == 'form_alias' %}
{% else %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
<th>{{field.label}}</th>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% endif %}
Le saluda atentamente,
El formulario de contacto
==
<p>Hola,</p>
<p>esto es una confirmación del formulario de contacto.</p>
{% if fieldsDetails|length %}
<br>
<p>Ha enviado lo siguiente:</p>
<table border="0">
<tbody>
{% for field in fieldsDetails %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<br>
<p>Le saluda atentamente,<br>
El formulario de contacto</p>

View File

@ -0,0 +1,77 @@
subject = "Potwierdzenie wysłania formularza"
==
Dzień dobry,
to jest potwierdzenie wysłane z formularza kontaktowego.
{% if fieldsDetails|length %}
Wiadomość, którą wysłałeś:
<table border="0">
<tbody>
{% for field in fieldsDetails %}
{% if field.label == 'form_description' or field.label == 'form_alias' %}
{% else %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
<th>{{field.label}}</th>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% endif %}
Z poważaniem,
Formularz kontaktowy
==
<p>Dzień dobry,</p>
<p>to jest potwierdzenie wysłane z formularza kontaktowego.</p>
{% if fieldsDetails|length %}
<br>
<p>Wiadomość, którą wysłałeś:</p>
<table border="0">
<tbody>
{% for field in fieldsDetails %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<br>
<p>Z poważaniem,<br>
Formularz kontaktowy</p>

View File

@ -0,0 +1,71 @@
subject = "Contact form notification"
==
Hello,
this is a notification from a Contact form.
{% if fields|length %}
Sent form content:
<table border="0">
<tbody>
{% for key,value in fields %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ key|upper }}</th>
<td style="text-align: left;">{{ value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
Best regards,
Contact form
==
<p>Hello,</p>
<p>this is a notification from a Contact form.</p>
{% if fields|length %}
<br>
<p>Sent form content:</p>
<table border="0">
<tbody>
{% for key,value in fields %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ key|upper }}</th>
<td style="text-align: left;">{{ value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<br>
<p>Best regards,<br>
Contact form</p>

View File

@ -0,0 +1,71 @@
subject = "Oznámení o odeslání kontaktního formuláře"
==
Dobrý den,
toto je oznámení o odeslání kontaktního formuláře.
{% if fields|length %}
Odeslaný obsah:
<table border="0">
<tbody>
{% for key,value in fields %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ key|upper }}</th>
<td style="text-align: left;">{{ value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
S pozdravem,
Kontaktní formulář
==
<p>Dobrý den,</p>
<p>toto je oznámení o odeslání kontaktního formuláře.</p>
{% if fields|length %}
<br>
<p>Odeslaný obsah:</p>
<table border="0">
<tbody>
{% for key,value in fields %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ key|upper }}</th>
<td style="text-align: left;">{{ value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<br>
<p>S pozdravem,<br>
Kontaktní formulář</p>

View File

@ -0,0 +1,70 @@
subject = "Notificación del formulario de contacto"
==
Hola,
esto es una notificación de un formulario de contacto.
{% if fields|length %}
Contenido del formulario enviado:
<table border="0">
<tbody>
{% for key,value in fields %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ key|upper }}</th>
<td style="text-align: left;">{{ value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
Le saluda atentamente,
El formulario de contacto
==
<p>Hola,</p>
<p>esto es una notificación de un formulario de contacto..</p>
{% if fields|length %}
<br>
<p>Sent form content:</p>
<table border="0">
<tbody>
{% for key,value in fields %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ key|upper }}</th>
<td style="text-align: left;">{{ value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<br>
<p>Le saluda atentamente,<br>
El formulario de contacto</p>

View File

@ -0,0 +1,77 @@
subject = "Powiadomienie o nowej wiadomości"
==
Dzień dobry,
to jest powiadomienie wysłane z formularza kontaktowego.
{% if fieldsDetails|length %}
Otrzymałeś nową wiadomość:
<table border="0">
<tbody>
{% for field in fieldsDetails %}
{% if field.label == 'form_description' or field.label == 'form_alias' %}
{% else %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
<th>{{field.label}}</th>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% endif %}
Z poważaniem,
Formularz kontaktowy
==
<p>Dzień dobry,</p>
<p>to jest powiadomienie wysłane z formularza kontaktowego.</p>
{% if fieldsDetails|length %}
<br>
<p>Otrzymałeś nową wiadomość:</p>
<table border="0">
<tbody>
{% for field in fieldsDetails %}
<tr>
<th style="vertical-align: top; text-align: left; padding-right: 10px;">{{ field.label }}</th>
<td style="text-align: left;">{{ field.value|raw|nl2br }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<br>
<p>Z poważaniem,<br>
Formularz kontaktowy</p>

View File

@ -8,3 +8,24 @@ tabs:
type: number
default: "0"
about_us:
tab: About us
prompt: 'Add new item'
span: auto
type: repeater
form:
fields:
title:
label: Text
span: auto
type: text
description:
label: Description
size: ''
span: auto
type: textarea
image:
label: 'Image'
mode: file
span: auto
type: mediafinder

View File

@ -0,0 +1,90 @@
title = "about"
url = "/about"
layout = "default"
is_hidden = 0
==
<!-- Intro ============================= -->
<section class="intro">
<div class="auto_container">
<div class="intro_wrap">
<div class="breadcrumb">
<a href="{{'home'|page }}" class="breadcrumb_title">
<span>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M1.25 12.88V6.91459C1.25 6.33752 1.51642 5.79278 1.97193 5.4385L6.85193 1.64294C7.52721 1.11773 8.47279 1.11773 9.14807 1.64294L14.0281 5.4385C14.4836 5.79278 14.75 6.33752 14.75 6.91459V12.88C14.75 13.9128 13.9128 14.75 12.88 14.75H10.75C10.4739 14.75 10.25 14.5261 10.25 14.25V11.6487C10.25 11.3855 10.207 11.1193 10.0677 10.896C9.88545 10.6039 9.64228 10.3523 9.35303 10.1595C8.95253 9.89251 8.48167 9.75 8 9.75C7.51833 9.75 7.04747 9.89251 6.64697 10.1595C6.35772 10.3523 6.11455 10.6039 5.93234 10.896C5.79305 11.1193 5.75 11.3855 5.75 11.6487V14.25C5.75 14.5261 5.52614 14.75 5.25 14.75H3.12C2.08723 14.75 1.25 13.9128 1.25 12.88Z"
stroke="#292929" stroke-width="1.5" stroke-linecap="round"
stroke-linejoin="round" />
</svg>
</span>
Главная
</a>
<h4 class="breadcrumb_title">
О нас
</h4>
</div>
<div class="intro_info">
<h2 class="intro_info-title wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".1s">
О нас
</h2>
<p class="intro_info-txt wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".13s">
«Беркарар» — крупнейший в Туркменистане торгово-развлекательный центр. Комплекс расположен в
южной части Ашхабада, на пересечении улиц 10 йыл Абаданчылык и Ататюрка. Построен в 2014 году.
</p>
<p class="intro_info-txt wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".13s">
«Беркарар» — крупнейший в Туркменистане торгово-развлекательный центр. Комплекс расположен в
южной части Ашхабада, на пересечении улиц 10 йыл Абаданчылык и Ататюрка. Построен в 2014 году.
</p>
<div class="intro_info-link wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".17s">
<a href="#">
Узнать подробней
<span>
<svg width="14" height="12" viewBox="0 0 14 12" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M1.16732 6.83342H11.0507L8.02565 10.4668C7.95561 10.551 7.90286 10.6482 7.8704 10.7529C7.83794 10.8576 7.82641 10.9676 7.83647 11.0767C7.85678 11.297 7.9638 11.5003 8.13398 11.6418C8.30416 11.7832 8.52356 11.8513 8.74392 11.8309C8.96428 11.8106 9.16753 11.7036 9.30898 11.5334L13.4756 6.53342C13.5037 6.49365 13.5288 6.45187 13.5507 6.40842C13.5507 6.36675 13.5923 6.34175 13.609 6.30008C13.6468 6.20453 13.6665 6.10282 13.6673 6.00008C13.6665 5.89734 13.6468 5.79563 13.609 5.70008C13.609 5.65842 13.5673 5.63342 13.5507 5.59175C13.5288 5.5483 13.5037 5.50652 13.4756 5.46675L9.30898 0.46675C9.23063 0.372681 9.13251 0.297031 9.02161 0.24518C8.91071 0.193329 8.78974 0.166551 8.66732 0.16675C8.47261 0.166369 8.28391 0.234182 8.13398 0.358416C8.0496 0.428374 7.97985 0.514291 7.92872 0.611247C7.8776 0.708203 7.8461 0.814293 7.83604 0.92344C7.82597 1.03259 7.83754 1.14265 7.87008 1.24732C7.90262 1.35199 7.95548 1.44921 8.02565 1.53342L11.0507 5.16675H1.16732C0.946304 5.16675 0.734342 5.25455 0.578062 5.41083C0.421782 5.56711 0.333984 5.77907 0.333984 6.00008C0.333984 6.2211 0.421782 6.43306 0.578062 6.58934C0.734342 6.74562 0.946304 6.83342 1.16732 6.83342Z"
fill="#292929" />
</svg>
</span>
</a>
</div>
</div>
</div>
</div>
</section>
<!-- Intro end ========================= -->
<!-- About ============================= -->
<section class="about">
<div class="auto_container">
<div class="about_wrap">
{% for item in this.theme.about_us %}
<div class="about_item">
<div class="about_item-photo wow fadeInUp" data-wow-duration=".3s" data-wow-delay=".1s">
<img src="{{item.image|media}}" alt="about-photo">
</div>
<div class="about_item-info wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".1s">
<h4 class="about_item-title">
{{item.title}}
</h4>
<p class="about_item-txt">
{{item.description}}
</p>
</div>
</div>
{% endfor %}
</div>
</div>
</section>
<!-- About end ========================= -->

View File

@ -0,0 +1,62 @@
title = "contact"
url = "/contact"
layout = "default"
is_hidden = 0
[contactForm]
==
<!-- Intro ============================= -->
<section class="intro">
<div class="auto_container">
<div class="intro_wrap">
<div class="breadcrumb">
<a href="{{'home'|page }}" class="breadcrumb_title">
<span>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M1.25 12.88V6.91459C1.25 6.33752 1.51642 5.79278 1.97193 5.4385L6.85193 1.64294C7.52721 1.11773 8.47279 1.11773 9.14807 1.64294L14.0281 5.4385C14.4836 5.79278 14.75 6.33752 14.75 6.91459V12.88C14.75 13.9128 13.9128 14.75 12.88 14.75H10.75C10.4739 14.75 10.25 14.5261 10.25 14.25V11.6487C10.25 11.3855 10.207 11.1193 10.0677 10.896C9.88545 10.6039 9.64228 10.3523 9.35303 10.1595C8.95253 9.89251 8.48167 9.75 8 9.75C7.51833 9.75 7.04747 9.89251 6.64697 10.1595C6.35772 10.3523 6.11455 10.6039 5.93234 10.896C5.79305 11.1193 5.75 11.3855 5.75 11.6487V14.25C5.75 14.5261 5.52614 14.75 5.25 14.75H3.12C2.08723 14.75 1.25 13.9128 1.25 12.88Z"
stroke="#292929" stroke-width="1.5" stroke-linecap="round"
stroke-linejoin="round" />
</svg>
</span>
Главная
</a>
<h4 class="breadcrumb_title">
Контакты
</h4>
</div>
<div class="intro_info intro_contact">
<h2 class="intro_info-title wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".1s">
Свяжитесь с нами
</h2>
<p class="intro_info-txt wow fadeInRight" data-wow-duration=".3s" data-wow-delay=".15s">
Свяжитесь с нами(очень длинное описание)
</p>
</div>
</div>
</div>
</section>
<!-- Intro end ========================= -->
<!-- Contact ============================= -->
<section class="contact">
<div class="auto_container">
<div class="contact_wrap">
{% component 'contactForm' %}
<div class="contact_map">
<iframe
src="https://www.google.com/maps/embed?pb=!1m16!1m12!1m3!1d6297.044395419706!2d58.36783108806193!3d37.89485524007183!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!2m1!1sashgabat%20berkarar%20sowda%20merkezi!5e0!3m2!1sru!2s!4v1660069090324!5m2!1sru!2s"
width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy"
referrerpolicy="no-referrer-when-downgrade"></iframe>
</div>
</div>
</div>
</section>
<!-- Contact end ========================= -->

View File

@ -5,9 +5,7 @@ is_hidden = 0
==
<?php
function onStart(){
$id = $this->param('id');
// $this["category"] = $this->param('category');
$this['shop'] = Tps\Shops\Models\Shop::where("id", $id)->get()->first();
@ -39,10 +37,9 @@ function onStart(){
{{shop.category.top_category.name}}
</h4>
<h4 class="crumb_title">
<a href="{{ url('/') }}/category/{{shop.category.id}}/{{shop.category.name}}">
{{shop.category.name}}
</a>
<a href="{{ url('/') }}/category/{{shop.category.id}}/{{shop.category.name}}">
{{shop.category.name}}
</a>
</h4>
<h4 class="crumb_title">
{{shop.name}}

View File

@ -13,9 +13,9 @@ function onStart(){
<span></span>
</div>
<a href="#" class="header_item-link m-rl"> Подробней о нас </a>
<a href="{{ 'about'|page}}" class="header_item-link m-rl"> Подробней о нас </a>
<a href="#" class="header_item-link">
<a href="{{ 'contact'|page}}" class="header_item-link">
<span>
<svg
width="18"
@ -92,34 +92,22 @@ function onStart(){
</h6>
<div class="lang_box">
<a href="{{ url('/tk') }}">
<span class="lang_flag">
<img
src="{{ 'assets/images/flag_tk.png'|theme }}"
alt="lang-flag"
/>
</span>
{% for code, name in locales %}
{% if code != activeLocale %}
{% set aa = 'assets/images/flag_'~ code ~'.png'%}
<a href="{{ url('/' ~ code) }}">
<span class="lang_flag">
<img
src="{{ aa|theme }}"
alt="lang-flag"
/>
</span>
TK
</a>
<a href="{{ url('/ru') }}">
<span class="lang_flag">
<img
src="{{ 'assets/images/flag_ru.png'|theme }}"
alt="lang-flag"
/>
</span>
RU
</a>
<a href="{{ url('/en') }}">
<span class="lang_flag">
<img
src="{{ 'assets/images/flag_en.png'|theme }}"
alt="lang-flag"
/>
</span>
EN
</a>
{{code|upper }}
</a>
{% endif %}
{% endfor %}
</div>
</div>
</div>