Skip to content

Commit 0712607

Browse files
committed
v2.0.0
1 parent 6d2e566 commit 0712607

File tree

9 files changed

+254
-50
lines changed

9 files changed

+254
-50
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Solspace Freeform Changelog
22

3+
## 2.0.0 - 2018-05-14
4+
### Added
5+
- Added mailing list integration support for the Craft Campaign plugin, available on Lite and Pro editions.
6+
7+
### Fixed
8+
- Fixed a bug where 'Display error messages' option for Spam Protection Behavior setting would trip on submitting a form if it initially errored.
9+
- Fixed a bug where submitting a form with a mailing list would error in some cases.
10+
- Fixed a bug where the Salesforce fetch token URL regex restriction was not allowing for less common URLs to pass through.
11+
- Fixed a bug where saving field mapping for HubSpot was not always saving fields correctly.
12+
313
## 2.0.0-beta.20 - 2018-05-09
414
### Added
515
- Added Form Submission Throttling setting to help prevent against spam or attacks.

README.md

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
Freeform is the most powerful form building plugin for Craft CMS. It gives you full control to create simple or complex multi-page forms, as well as connect your forms to many popular API integrations.
44

5-
🚨 **NOTE: Freeform has proven to be fairly stable now, but please take caution if using in production environments.** 🚨
6-
75
![Screenshot](src/icon.svg)
86

97
## Requirements
@@ -12,21 +10,19 @@ This plugin requires Craft CMS 3.0.0 or later.
1210

1311
## Installation
1412

15-
To install the plugin(s), search for **Freeform** in the *Craft Plugin Store*, or install manually with the following instructions:
16-
17-
1. Open your terminal and go to your Craft project:
18-
19-
cd /path/to/project
20-
21-
2. Then tell Composer to require the plugin:
22-
23-
composer require solspace/craft3-freeform
13+
To install Freeform, simply:
2414

25-
And if you'd like the **Pro** edition of Freeform, you'll need to also install Freeform Pro (in addition to Freeform Lite). Tell Composer to also require the plugin:
15+
1. Go to the **Plugin Store** area inside your Craft control panel and search for *Freeform*.
16+
2. Choose to install *Freeform Lite* and/or *Freeform Pro* (*Pro* requires *Lite* to be installed) by clicking on them.
17+
3. Click on the **Try** button to install a trial copy of Freeform.
18+
4. Try things out and if Freeform is right for your site, purchase a copy of if through the Plugin Store when you're ready!
2619

27-
composer require solspace/craft3-freeform-pro
20+
Freeform can also be installed manually through Composer:
2821

29-
3. In the Control Panel, go to *Settings → Plugins* and click the “Install” button for **Freeform Lite** (and **Freeform Pro** if you're wanting Pro edition).
22+
1. Open your terminal and go to your Craft project: `cd /path/to/project`
23+
2. Then tell Composer to require the plugin: `composer require solspace/craft3-freeform`
24+
3. If you'd like Freeform Pro, also run: `composer require solspace/craft3-freeform-pro`
25+
4. In the Craft control panel, go to *Settings → Plugins* and click the **Install** button for Freeform Lite (and Freeform Pro if you're using Pro edition).
3026

3127
## Freeform Overview
3228

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "solspace/craft3-freeform",
33
"description": "The most intuitive and powerful form builder for Craft.",
4-
"version": "2.0.0-beta.20",
4+
"version": "2.0.0",
55
"type": "craft-plugin",
66
"minimum-stability": "dev",
77
"authors": [

src/Freeform.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Solspace\Freeform\Controllers\StatusesController;
3434
use Solspace\Freeform\Controllers\SubmissionsController;
3535
use Solspace\Freeform\Events\Freeform\RegisterCpSubnavItemsEvent;
36+
use Solspace\Freeform\Events\Integrations\FetchMailingListTypesEvent;
3637
use Solspace\Freeform\FieldTypes\FormFieldType;
3738
use Solspace\Freeform\Library\Composer\Components\FieldInterface;
3839
use Solspace\Freeform\Models\FieldModel;
@@ -55,6 +56,8 @@
5556
use Solspace\Freeform\Services\SubmissionsService;
5657
use Solspace\Freeform\Variables\FreeformVariable;
5758
use Solspace\Freeform\Widgets\StatisticsWidget;
59+
use Symfony\Component\Finder\Finder;
60+
use Symfony\Component\Finder\SplFileInfo;
5861
use yii\base\Event;
5962
use yii\db\Query;
6063

@@ -559,6 +562,29 @@ private function initEventListeners()
559562
FormsService::EVENT_RENDER_CLOSING_TAG,
560563
[$this->forms, 'addFormAnchorJavascript']
561564
);
565+
566+
Event::on(
567+
MailingListsService::class,
568+
MailingListsService::EVENT_FETCH_TYPES,
569+
function (FetchMailingListTypesEvent $event) {
570+
$finder = new Finder();
571+
572+
$namespace = 'Solspace\Freeform\Library\MailingLists';
573+
574+
/** @var SplFileInfo[] $files */
575+
$files = $finder
576+
->name('*.php')
577+
->files()
578+
->ignoreDotFiles(true)
579+
->in(__DIR__ . '/Library/MailingLists/');
580+
581+
foreach ($files as $file) {
582+
$className = str_replace('.' . $file->getExtension(), '', $file->getBasename());
583+
$className = $namespace . '\\' . $className;
584+
$event->addType($className);
585+
}
586+
}
587+
);
562588
}
563589

564590
private function initHoneypot()

src/Library/Composer/Components/Form.php

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ class Form implements \JsonSerializable, \Iterator, \ArrayAccess
9595
/** @var bool */
9696
private $valid;
9797

98+
/** @var bool */
99+
private $markedAsSpam;
100+
98101
/** @var SubmissionHandlerInterface */
99102
private $submissionHandler;
100103

@@ -163,6 +166,7 @@ public function __construct(
163166
$this->ipCollectingEnabled = true;
164167
$this->customAttributes = new CustomFormAttributes();
165168
$this->errors = [];
169+
$this->markedAsSpam = false;
166170

167171
$this->layout = new Layout(
168172
$this,
@@ -381,7 +385,7 @@ public function addError(string $message): Form
381385
*/
382386
public function isMarkedAsSpam(): bool
383387
{
384-
return $this->getFormValueContext()->isMarkedAsSpam();
388+
return $this->markedAsSpam;
385389
}
386390

387391
/**
@@ -391,7 +395,7 @@ public function isMarkedAsSpam(): bool
391395
*/
392396
public function setMarkedAsSpam(bool $markedAsSpam): Form
393397
{
394-
$this->getFormValueContext()->setMarkedAsSpam($markedAsSpam);
398+
$this->markedAsSpam = $markedAsSpam;
395399

396400
return $this;
397401
}
@@ -420,17 +424,30 @@ public function isValid(): bool
420424
$currentPageFields = $this->getCurrentPage()->getFields();
421425

422426
$isFormValid = true;
423-
foreach ($currentPageFields as $field) {
424-
if (!$field->isValid()) {
425-
$isFormValid = false;
427+
foreach ($this->getLayout()->getPages() as $page) {
428+
if ($page->getIndex() > $this->getCurrentPage()->getIndex()) {
429+
break;
430+
}
431+
432+
foreach ($page->getFields() as $field) {
433+
if (!$field->isValid()) {
434+
$isFormValid = false;
435+
}
426436
}
427437
}
428438

429439
$this->formHandler->onFormValidate($this, $isFormValid);
430440

431441
if ($isFormValid && $this->isMarkedAsSpam()) {
432-
$this->formHandler->incrementSpamBlockCount($this);
433-
$this->valid = $this->formHandler->isSpamBehaviourSimulateSuccess();
442+
$simulateSuccess = $this->formHandler->isSpamBehaviourSimulateSuccess();
443+
444+
if ($simulateSuccess && $this->isLastPage()) {
445+
$this->formHandler->incrementSpamBlockCount($this);
446+
} else if (!$simulateSuccess) {
447+
$this->formHandler->incrementSpamBlockCount($this);
448+
}
449+
450+
$this->valid = $simulateSuccess;
434451

435452
return $this->valid;
436453
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
<?php
2+
3+
namespace Solspace\Freeform\Library\MailingLists;
4+
5+
use craft\base\Field;
6+
use craft\fields\Checkboxes;
7+
use craft\fields\Color;
8+
use craft\fields\Date;
9+
use craft\fields\Dropdown;
10+
use craft\fields\Email;
11+
use craft\fields\Entries;
12+
use craft\fields\Lightswitch;
13+
use craft\fields\MultiSelect;
14+
use craft\fields\PlainText;
15+
use craft\fields\RadioButtons;
16+
use craft\fields\Tags;
17+
use craft\fields\Url;
18+
use craft\fields\Users;
19+
use Money\Number;
20+
use putyourlightson\campaign\Campaign as CampaignPlugin;
21+
use putyourlightson\campaign\elements\ContactElement;
22+
use putyourlightson\campaign\elements\MailingListElement;
23+
use Solspace\Freeform\Library\Integrations\DataObjects\FieldObject;
24+
use Solspace\Freeform\Library\Integrations\MailingLists\AbstractMailingListIntegration;
25+
use Solspace\Freeform\Library\Integrations\MailingLists\DataObjects\ListObject;
26+
27+
class Campaign extends AbstractMailingListIntegration
28+
{
29+
const TITLE = 'Craft Campaign';
30+
const LOG_CATEGORY = 'CraftCampaign';
31+
32+
/** @var array */
33+
private static $fieldCache;
34+
35+
/** @var array - a list of allowed field types and their value type */
36+
private static $fieldTypeMap = [
37+
Checkboxes::class => FieldObject::TYPE_ARRAY,
38+
Color::class => FieldObject::TYPE_STRING,
39+
Date::class => FieldObject::TYPE_STRING,
40+
Dropdown::class => FieldObject::TYPE_STRING,
41+
Email::class => FieldObject::TYPE_STRING,
42+
Lightswitch::class => FieldObject::TYPE_BOOLEAN,
43+
Entries::class => FieldObject::TYPE_ARRAY,
44+
MultiSelect::class => FieldObject::TYPE_ARRAY,
45+
Number::class => FieldObject::TYPE_NUMERIC,
46+
PlainText::class => FieldObject::TYPE_STRING,
47+
RadioButtons::class => FieldObject::TYPE_STRING,
48+
Tags::class => FieldObject::TYPE_ARRAY,
49+
Url::class => FieldObject::TYPE_ARRAY,
50+
Users::class => FieldObject::TYPE_ARRAY,
51+
];
52+
53+
/**
54+
* @inheritDoc
55+
*/
56+
protected function fetchLists(): array
57+
{
58+
$lists = [];
59+
foreach (MailingListElement::find()->all() as $list) {
60+
$lists[] = new ListObject(
61+
$this,
62+
$list->id,
63+
$list->title,
64+
$this->fetchFields($list->id),
65+
$list->subscribedCount
66+
);
67+
}
68+
69+
return $lists;
70+
}
71+
72+
/**
73+
* @inheritDoc
74+
*/
75+
protected function fetchFields($listId): array
76+
{
77+
if (null === self::$fieldCache) {
78+
$allowedFieldTypes = array_keys(self::$fieldTypeMap);
79+
$fieldLayout = \Craft::$app->fields->getLayoutByType(ContactElement::class);
80+
81+
if (!$fieldLayout) {
82+
self::$fieldCache = [];
83+
84+
return self::$fieldCache;
85+
}
86+
87+
$list = [];
88+
/** @var Field $field */
89+
foreach ($fieldLayout->getFields() as $field) {
90+
$fieldClass = \get_class($field);
91+
92+
if (!\in_array($fieldClass, $allowedFieldTypes, true)) {
93+
continue;
94+
}
95+
96+
$list[] = new FieldObject(
97+
$field->handle,
98+
$field->name,
99+
self::$fieldTypeMap[$fieldClass],
100+
$field->required
101+
);
102+
}
103+
104+
self::$fieldCache = $list;
105+
}
106+
107+
return self::$fieldCache;
108+
}
109+
110+
/**
111+
* @inheritDoc
112+
*/
113+
public function checkConnection(): bool
114+
{
115+
return \Craft::$app->plugins->isPluginInstalled('campaign');
116+
}
117+
118+
/**
119+
* @inheritDoc
120+
*/
121+
public function initiateAuthentication()
122+
{
123+
}
124+
125+
/**
126+
* @inheritDoc
127+
*/
128+
public function fetchAccessToken(): string
129+
{
130+
return '';
131+
}
132+
133+
/**
134+
* @inheritDoc
135+
*/
136+
protected function getApiRootUrl(): string
137+
{
138+
return '';
139+
}
140+
141+
/**
142+
* @inheritDoc
143+
*/
144+
public function pushEmails(ListObject $mailingList, array $emails, array $mappedValues): bool
145+
{
146+
$mailingListElement = MailingListElement::find()->id($mailingList->getId())->one();
147+
$source = \Craft::$app->getRequest()->getReferrer();
148+
149+
if ($mailingListElement === null) {
150+
return false;
151+
}
152+
153+
foreach ($emails as $email) {
154+
$contact = CampaignPlugin::$plugin->contacts->getContactByEmail('name@email.com');
155+
156+
if ($contact === null) {
157+
$contact = new ContactElement();
158+
159+
$contact->email = $email;
160+
foreach ($mappedValues as $key => $value) {
161+
$contact->setFieldValue($key, $value);
162+
}
163+
}
164+
165+
\Craft::$app->getElements()->saveElement($contact);
166+
167+
if (!$contact->id) {
168+
continue;
169+
}
170+
171+
CampaignPlugin::$plugin->tracker->subscribe(
172+
$contact,
173+
$mailingListElement,
174+
'Freeform',
175+
$source
176+
);
177+
}
178+
179+
return true;
180+
}
181+
}

0 commit comments

Comments
 (0)