diff --git a/.gitignore b/.gitignore index af8c675..99d37f1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ composer.lock mix-manifest.json package-lock.json yarn.lock +.idea/* diff --git a/README.md b/README.md index fe9c6ec..c8b6335 100644 --- a/README.md +++ b/README.md @@ -37,13 +37,24 @@ php artisan vendor:publish --tag="campaign-monitor-config" ## Usage -Create your Statamic [forms](https://statamic.dev/forms#content) as usual. Don't forget to add the consent field to your blueprint. +Create your Statamic [forms](https://statamic.dev/forms#content) as usual. When editing the form you'll see a "Campaign Monitor Integration" section where you can configure if and how that form integrates with Campaign Monitor. + +Don't forget to add the consent field to your blueprint. + +You can also manage if new users are added a list using the dedicated settings view in the control panel. *Configuration in the Control Panel:* ![control panel](https://raw.githubusercontent.com/statamic-rad-pack/campaign-monitor/main/images/config.png) +### Data storage + +Any user related settings are stored by default in `resources/campaign_monitor.yaml`. + +If you want to change this or use a different data store, you can bind `\StatamicRadPack\Mailchimp\UserConfig::class` in your app service provider. You should modify the `getSavedSettings`, `save`, and `exists` methods according to your requirements. + + ## Testing Run the tests with: diff --git a/composer.json b/composer.json index b02082e..17ed707 100644 --- a/composer.json +++ b/composer.json @@ -14,13 +14,14 @@ "require": { "php": "^8.1", "bashy/laravel-campaignmonitor": "^6.0", - "edalzell/forma": "^3.0", "laravel/framework": "^10.25.0 || ^11.0", "pixelfear/composer-dist-plugin": "^0.1", - "statamic/cms": "^4.0 || ^5.0" + "statamic/cms": "^5.18", + "stillat/proteus": "^4.0" }, "require-dev": { "jasonmccreary/laravel-test-assertions": "^2.0", + "laravel/pint": "^1.17", "mockery/mockery": "^1.3.1", "orchestra/testbench": "^7.0 || ^8.0 || ^9.0", "phpunit/phpunit": "^9.0 || ^10.0" @@ -54,6 +55,5 @@ "description": "Campaign Monitor addon", "name": "Campaign Monitor" } - }, - "minimum-stability": "alpha" + } } diff --git a/config/campaign-monitor.php b/config/campaign-monitor.php index f2f475b..fb9def5 100644 --- a/config/campaign-monitor.php +++ b/config/campaign-monitor.php @@ -3,83 +3,6 @@ return [ 'api_key' => env('CAMPAIGNMONITOR_API_KEY'), - - 'client_id' => env('CAMPAIGNMONITOR_CLIENT_ID'), - /* - * Set to `true` to add new user registrations to a Campaign Monitor list - */ - 'add_new_users' => false, - - 'users' => [ - /* - * A Campaign Monitor List ID. - * - */ - 'list_id' => null, - - /* - * Set to `true` to require consent before subscribing someone - * Default: `true` - */ - 'check_consent' => true, - - /* - * Field name used to check for consent. - * Default: 'consent' - */ - 'consent_field' => 'consent', - - /* - * Set to `true` to require consent before SMS subscribing someone - * Default: `true` - */ - 'check_consent_sms' => true, - - /* - * Field name used to check for consent. - * Default: 'consent_sms' - */ - 'consent_field_sms' => 'consent_sms', - - /* - * Store information about your contacts with custom fields. - */ - 'custom_fields' => [ - // [ - // /* - // * The Campaign Monitor key - // */ - // 'key'=> null, - - // /* - // * Blueprint field name to use for the merge field - // */ - // 'field_name' => null, - // ], - ], - - /* - * Field that contains the mobile number - * Default: 'mobile' - */ - 'mobile_field' => 'mobile', - - /* - * Field that contains the name - * Default: 'name' - */ - 'name_field' => 'name', - - /* - * Field that contains the primary email address - * Default: 'email' - */ - 'primary_email_field' => 'email', - ], - - /* - * The form submissions to add to your Campaign Monitor lists - */ - 'forms' => [], + 'client_id' => env('CAMPAIGNMONITOR_CLIENT_ID'), ]; diff --git a/images/config.png b/images/config.png index 10d51b3..a0b31b4 100644 Binary files a/images/config.png and b/images/config.png differ diff --git a/resources/blueprints/config.yaml b/resources/blueprints/config.yaml index 30c80ac..75bf070 100644 --- a/resources/blueprints/config.yaml +++ b/resources/blueprints/config.yaml @@ -1,133 +1,4 @@ tabs: - forms: - display: 'Forms' - sections: - - - fields: - - - handle: forms - field: - fields: - - - handle: form - field: - display: Form - type: form - max_items: 1 - mode: select - width: 33 - - - handle: list_id - field: - display: 'List ID' - type: campaign_monitor_list - mode: select - max_items: 1 - width: 33 - - - handle: name_field - field: - display: 'Name Field' - type: campaign_monitor_form_fields - max_items: 1 - default: name - width: 33 - - - handle: primary_email_field - field: - display: 'Email Field' - type: campaign_monitor_form_fields - max_items: 1 - default: email - width: 33 - - - handle: check_consent - field: - display: 'Check Consent?' - type: toggle - width: 33 - default: false - - - handle: consent_field - field: - display: 'Consent Field' - type: campaign_monitor_form_fields - default: consnet - width: 33 - if: - check_consent: true - - - handle: spacer_field - field: - display: 'Consent Field' - type: spacer - width: 33 - if: - check_consent: false - - - handle: mobile_field - field: - display: 'Mobile Number Field' - type: campaign_monitor_form_fields - default: mobile - width: 33 - - - handle: check_consent_sms - field: - display: 'Check Consent to SMS?' - type: toggle - width: 33 - default: false - - - handle: consent_field_sms - field: - display: 'SMS Consent Field' - type: campaign_monitor_form_fields - default: consent_sms - width: 33 - if: - check_consent_sms: true - - - handle: spacer_field_sms - field: - display: 'Consent Field' - type: spacer - width: 33 - if: - check_consent_sms: false - - - handle: custom_fields - field: - fields: - - - handle: field_name - field: - input_type: text - display: Form Field - type: campaign_monitor_form_fields - icon: text - listable: hidden - - - handle: key - field: - input_type: text - display: 'Custom Field' - type: campaign_monitor_custom_fields - max_items: 1 - icon: text - listable: hidden - mode: table - reorderable: true - display: 'Custom Fields' - type: grid - icon: grid - add_row: 'Add Custom Field' - listable: hidden - display: ' ' - type: grid - mode: stacked - add_row: 'Add Form' - instructions: 'Add the forms you want to process Campaign Monitor submissions for.' users: display: 'Users' sections: @@ -155,7 +26,7 @@ tabs: handle: name_field field: display: 'Name Field' - type: campaign_monitor_form_fields + type: campaign_monitor_user_fields max_items: 1 default: name width: 33 @@ -169,7 +40,7 @@ tabs: handle: primary_email_field field: display: 'Email Field' - type: campaign_monitor_form_fields + type: campaign_monitor_user_fields max_items: 1 default: email width: 33 @@ -184,7 +55,7 @@ tabs: handle: consent_field field: display: 'Consent Field' - type: campaign_monitor_form_fields + type: campaign_monitor_user_fields default: consnet width: 33 if: @@ -201,7 +72,7 @@ tabs: handle: mobile_field field: display: 'Mobile Number Field' - type: campaign_monitor_form_fields + type: campaign_monitor_user_fields default: mobile width: 33 - @@ -215,7 +86,7 @@ tabs: handle: consent_field_sms field: display: 'SMS Consent Field' - type: campaign_monitor_form_fields + type: campaign_monitor_user_fields default: consent_sms width: 33 if: @@ -237,7 +108,7 @@ tabs: field: input_type: text display: Form Field - type: campaign_monitor_form_fields + type: campaign_monitor_user_fields icon: text listable: hidden - @@ -257,12 +128,12 @@ tabs: add_row: 'Add Custom Field' listable: hidden display: ' ' - instructions: 'Add the forms you want to process Campaign Monitor submissions for.' type: grid mode: stacked max_rows: 1 min_rows: 1 reorderable: false + fullscreen: false if: add_new_users: 'equals true' credentials: diff --git a/resources/js/components/fieldtypes/CustomFieldsFieldtype.vue b/resources/js/components/fieldtypes/CustomFieldsFieldtype.vue index 6d5c4bf..ebf9d0b 100644 --- a/resources/js/components/fieldtypes/CustomFieldsFieldtype.vue +++ b/resources/js/components/fieldtypes/CustomFieldsFieldtype.vue @@ -42,7 +42,12 @@ export default { computed: { key() { - let matches = this.namePrefix.match(/([a-z]*?)\[(.*?)\]/); + let matches = this.namePrefix.match(/([a-z_]*?)\[(.*?)\]/); + + if (matches[1] == 'campaign_monitor') { // form page + return 'campaign_monitor.settings.list_id.0'; + } + return matches[0].replace('[', '.').replace(']', '.') + 'list_id.0'; }, @@ -62,7 +67,8 @@ export default { .get(cp_url(`/campaign-monitor/custom-fields/${this.list}`)) .then(response => { this.fields = response.data; - }); + }) + .catch(() => { this.fields = []; }); } } }; diff --git a/resources/js/components/fieldtypes/FormFieldsFieldtype.vue b/resources/js/components/fieldtypes/FormFieldsFieldtype.vue index 30af343..38a4769 100644 --- a/resources/js/components/fieldtypes/FormFieldsFieldtype.vue +++ b/resources/js/components/fieldtypes/FormFieldsFieldtype.vue @@ -42,16 +42,8 @@ export default { computed: { form() { - let key = 'forms.' + this.row + '.form.0' ; - - return data_get(this.$store.state.publish[this.storeName].values, key) + return StatamicConfig.urlPath.split('/')[1] ?? ''; }, - - row() { - let matches = this.namePrefix.match(/\[(.*?)\]/); - - return matches[1]; - } }, mounted() { @@ -66,7 +58,8 @@ export default { .get(cp_url(`/campaign-monitor/form-fields/${this.form}`)) .then(response => { this.fields = response.data; - }); + }) + .catch(() => { this.fields = []; }); } } }; diff --git a/resources/js/components/fieldtypes/UserFieldsFieldtype.vue b/resources/js/components/fieldtypes/UserFieldsFieldtype.vue index 4bf07df..dc612e3 100644 --- a/resources/js/components/fieldtypes/UserFieldsFieldtype.vue +++ b/resources/js/components/fieldtypes/UserFieldsFieldtype.vue @@ -37,7 +37,8 @@ export default { .get(cp_url(`/campaign-monitor/user-fields`)) .then(response => { this.fields = response.data; - }); + }) + .catch(() => { this.fields = []; }); } } }; diff --git a/resources/views/cp/config.blade.php b/resources/views/cp/config.blade.php new file mode 100644 index 0000000..f71dc72 --- /dev/null +++ b/resources/views/cp/config.blade.php @@ -0,0 +1,12 @@ +@extends('statamic::layout') +@section('title', __('Manage Campaign Monitor Settings')) + +@section('content') + +@stop \ No newline at end of file diff --git a/routes/cp.php b/routes/cp.php index 67ac707..8ab6f63 100644 --- a/routes/cp.php +++ b/routes/cp.php @@ -1,12 +1,13 @@ prefix('campaign-monitor')->group(function () { - Route::get('form-fields/{form}', [GetFormFieldsController::class, '__invoke'])->name('form-fields'); - Route::get('custom-fields/{list}', [GetCustomFieldsController::class, '__invoke'])->name('custom-fields'); - Route::get('user-fields', [GetUserFieldsController::class, '__invoke'])->name('user-fields'); + Route::get('config', [Controllers\ConfigController::class, 'edit'])->name('config.edit'); + Route::post('config', [Controllers\ConfigController::class, 'update'])->name('config.update'); + + Route::get('form-fields/{form}', [Controllers\GetFormFieldsController::class, '__invoke'])->name('form-fields'); + Route::get('custom-fields/{list}', [Controllers\GetCustomFieldsController::class, '__invoke'])->name('custom-fields'); + Route::get('user-fields', [Controllers\GetUserFieldsController::class, '__invoke'])->name('user-fields'); }); diff --git a/src/Fieldtypes/CampaignMonitorList.php b/src/Fieldtypes/CampaignMonitorList.php index f12d018..8f82a9a 100644 --- a/src/Fieldtypes/CampaignMonitorList.php +++ b/src/Fieldtypes/CampaignMonitorList.php @@ -4,14 +4,13 @@ use Bashy\CampaignMonitor\Facades\CampaignMonitor; use Statamic\Fieldtypes\Relationship; -use Statamic\Support\Arr; class CampaignMonitorList extends Relationship { public function getIndexItems($request) { $lists = CampaignMonitor::clients(config('campaign-monitor.client_id'))->get_lists(); - + return collect($lists->response ?? []) ->map(function ($list) { return ['id' => $list->ListID, 'title' => $list->Name]; @@ -27,7 +26,7 @@ protected function toItemArray($id) if (! $list = CampaignMonitor::lists($id)->get()?->response ?? false) { return []; } - + return [ 'id' => $list->ListID, 'title' => $list->Title, diff --git a/src/Http/Controllers/ConfigController.php b/src/Http/Controllers/ConfigController.php index f32b1d4..8e132b6 100644 --- a/src/Http/Controllers/ConfigController.php +++ b/src/Http/Controllers/ConfigController.php @@ -2,33 +2,53 @@ namespace StatamicRadPack\CampaignMonitor\Http\Controllers; -use Edalzell\Forma\ConfigController as BaseController; +use Illuminate\Http\Request; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Auth; +use Statamic\Facades\Blueprint; +use Statamic\Facades\YAML; +use Statamic\Fields\Blueprint as BlueprintContract; +use Statamic\Http\Controllers\CP\CpController; +use StatamicRadpack\CampaignMonitor\UserConfig; -class ConfigController extends BaseController +class ConfigController extends CpController { - protected function postProcess(array $values): array + public function edit() { - $userConfig = Arr::get($values, 'users'); + abort_if(Auth::user()->cant('manage campaign-monitor settings'), 403); - return array_merge( - $values, - ['users' => $userConfig[0]] - ); + $values = config('campaign-monitor'); + $values['users'] = [$values['users']]; + + $blueprint = $this->getBlueprint(); + + $fields = $blueprint->fields()->addValues($values)->preProcess(); + + return view('campaign-monitor::cp.config', [ + 'blueprint' => $blueprint->toPublishArray(), + 'values' => $fields->values(), + 'meta' => $fields->meta(), + ]); } - protected function preProcess(string $handle): array + public function update(Request $request) { - $config = config($handle); + abort_if(Auth::user()->cant('manage campaign-monitor settings'), 403); + + $fields = $this->getBlueprint()->fields()->addValues($request->all()); - return array_merge( - $config, - ['users' => [Arr::get($config, 'users', [])]] - ); + $fields->validate(); + + $values = $fields->process()->values()->all(); + $values['users'] = $values['users'][0]; + + UserConfig::load(Arr::only($values, ['add_new_users', 'users']))->save(); + + return response()->json(['message' => __('Settings updated')]); } - - public static function cpIcon() + + private function getBlueprint(): BlueprintContract { - return ''; + return Blueprint::make()->setContents(YAML::file(__DIR__.'/../../../resources/blueprints/config.yaml')->parse()); } } diff --git a/src/Http/Controllers/GetCustomFieldsController.php b/src/Http/Controllers/GetCustomFieldsController.php index d01cfbd..a9ec983 100644 --- a/src/Http/Controllers/GetCustomFieldsController.php +++ b/src/Http/Controllers/GetCustomFieldsController.php @@ -3,7 +3,6 @@ namespace StatamicRadPack\CampaignMonitor\Http\Controllers; use Bashy\CampaignMonitor\Facades\CampaignMonitor; -use Illuminate\Support\Arr; use Statamic\Http\Controllers\Controller; class GetCustomFieldsController extends Controller @@ -14,6 +13,7 @@ public function __invoke(string $list): array return collect($fields->response ?? []) ->map(fn ($mergeField) => ['id' => $mergeField->Key, 'label' => $mergeField->FieldName]) + ->values() ->all(); } } diff --git a/src/Migrators/ConfigToFormData.php b/src/Migrators/ConfigToFormData.php new file mode 100644 index 0000000..a3aa2c1 --- /dev/null +++ b/src/Migrators/ConfigToFormData.php @@ -0,0 +1,27 @@ +merge([ + 'campaign_monitor' => [ + 'enabled' => true, + 'settings' => Arr::except($config, ['form', 'id']), + ], + ])->saveQuietly(); + } +} diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index 552faf5..2d666db 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -2,18 +2,20 @@ namespace StatamicRadPack\CampaignMonitor; -use Edalzell\Forma\Forma; use Statamic\Events\SubmissionCreated; use Statamic\Events\UserRegistered; +use Statamic\Facades\CP\Nav; +use Statamic\Facades\Form; +use Statamic\Facades\Permission; use Statamic\Providers\AddonServiceProvider; use Statamic\Support\Arr; use StatamicRadPack\CampaignMonitor\Fieldtypes\CampaignMonitorCustomFields; use StatamicRadPack\CampaignMonitor\Fieldtypes\CampaignMonitorFormFields; use StatamicRadPack\CampaignMonitor\Fieldtypes\CampaignMonitorList; use StatamicRadPack\CampaignMonitor\Fieldtypes\CampaignMonitorUserFields; -use StatamicRadPack\CampaignMonitor\Http\Controllers\ConfigController; use StatamicRadPack\CampaignMonitor\Listeners\AddFromSubmission; use StatamicRadPack\CampaignMonitor\Listeners\AddFromUser; +use Stillat\Proteus\Support\Facades\ConfigWriter; class ServiceProvider extends AddonServiceProvider { @@ -43,25 +45,47 @@ public function boot() { parent::boot(); - Forma::add('statamic-rad-pack/campaign-monitor', ConfigController::class); + Permission::extend(function () { + Permission::register('manage campaign-monitor settings') + ->label(__('Manage Campaign Monitor Settings')); + }); + + Nav::extend(fn ($nav) => $nav + ->content(__('Campaign Monitor')) + ->section(__('Settings')) + ->can('manage campaign-monitor settings') + ->route('campaign-monitor.config.edit') + ->icon('') + ); + + $this->addFormConfigFields(); $this->app->booted(function () { + $this->migrateToFormConfig(); + $this->migrateUserToYaml(); + $this->addFormsToNewsletterConfig(); }); } private function addFormsToNewsletterConfig() { - $lists = collect(config('campaign-monitor.forms')) + $lists = Form::all() ->flatMap(function ($form) { - if (! $handle = Arr::get($form, 'form')) { + $data = $form->get('campaign_monitor', []); + + if (! $enabled = Arr::get($data, 'enabled')) { + return []; + } + + if (! $data = Arr::get($data, 'settings', [])) { return []; } return [ - $handle => Arr::removeNullValues([ - 'id' => Arr::get($form, 'list_id'), - 'marketing_permissions' => collect(Arr::get($form, 'marketing_permissions_field_ids')) + $form->handle() => Arr::removeNullValues([ + 'id' => Arr::get($data, 'list_id'), + 'marketing_permissions' => collect(Arr::get($data, 'marketing_permissions_field_ids')) ->filter() ->flatMap(fn ($value) => [$value['field_name'] => $value['id']]) ->all(), @@ -74,4 +98,221 @@ private function addFormsToNewsletterConfig() config(['campaign-monitor.lists' => $lists]); } + + private function addFormConfigFields() + { + Form::appendConfigFields('*', __('Campaign Monitor Integration'), [ + 'campaign_monitor' => [ + 'handle' => 'campaign_monitor', + 'type' => 'group', + 'display' => ' ', + 'fullscreen' => false, + 'border' => false, + 'fields' => [ + [ + 'handle' => 'enabled', + 'field' => [ + 'type' => 'toggle', + 'display' => __('Enabled'), + 'width' => 100, + ], + ], + + [ + 'handle' => 'settings', + 'field' => [ + 'type' => 'group', + 'display' => ' ', + 'width' => 100, + 'fullscreen' => false, + 'show_when' => ['enabled' => true], + 'fields' => [ + + [ + 'handle' => 'list_id', + 'field' => [ + 'type' => 'campaign_monitor_list', + 'max_items' => 1, + 'mode' => 'select', + 'display' => __('List ID'), + 'width' => 33, + ], + ], + + [ + 'handle' => 'name_field', + 'field' => [ + 'type' => 'campaign_monitor_form_fields', + 'max_items' => 1, + 'default' => 'name', + 'display' => __('Name Field'), + 'width' => 33, + ], + ], + + [ + 'handle' => 'primary_email_field', + 'field' => [ + 'type' => 'campaign_monitor_form_fields', + 'max_items' => 1, + 'default' => 'email', + 'display' => __('Email Field'), + 'width' => 33, + ], + ], + + [ + 'handle' => 'check_consent', + 'field' => [ + 'type' => 'toggle', + 'display' => __('Check Consent?'), + 'width' => 33, + 'default' => false, + ], + ], + + [ + 'handle' => 'consent_field', + 'field' => [ + 'type' => 'campaign_monitor_form_fields', + 'default' => 'consent', + 'max_items' => 1, + 'display' => __('Consent Field'), + 'width' => 33, + 'if' => ['check_consent' => true], + ], + ], + + [ + 'handle' => 'spacer_field', + 'field' => [ + 'type' => 'spacer', + 'width' => 33, + 'if' => ['check_consent' => false], + ], + ], + + [ + 'handle' => 'mobile_field', + 'field' => [ + 'type' => 'campaign_monitor_form_fields', + 'default' => 'mobile', + 'max_items' => 1, + 'display' => __('Mobile Number Field'), + 'width' => 33, + ], + ], + + [ + 'handle' => 'check_consent_sms', + 'field' => [ + 'type' => 'toggle', + 'display' => __('Check Consent to SMS?'), + 'width' => 33, + 'default' => false, + ], + ], + + [ + 'handle' => 'consent_field_sms', + 'field' => [ + 'type' => 'campaign_monitor_form_fields', + 'default' => 'consent_sms', + 'max_items' => 1, + 'display' => __('SMS Consent Field'), + 'width' => 33, + 'if' => ['check_consent_sms' => true], + ], + ], + + [ + 'handle' => 'spacer_field_sms', + 'field' => [ + 'type' => 'spacer', + 'width' => 33, + 'if' => ['check_consent_sms' => false], + ], + ], + + [ + 'handle' => 'custom_fields', + 'field' => [ + 'type' => 'grid', + 'mode' => 'table', + 'reorderable' => true, + 'listable' => 'hidden', + 'display' => __('Custom Fields'), + 'width' => 100, + 'add_row' => __('Add Custom Field'), + 'fields' => [ + + [ + 'handle' => 'field_name', + 'field' => [ + 'type' => 'campaign_monitor_form_fields', + 'display' => __('Form Field'), + 'width' => 33, + ], + ], + + [ + 'handle' => 'key', + 'field' => [ + 'type' => 'campaign_monitor_custom_fields', + 'display' => __('Custom Field'), + 'max_items' => 1, + 'width' => 33, + ], + ], + + ], + ], + ], + + ], + + ], + + ], + + ], + ], + ]); + } + + private function migrateToFormConfig() + { + if (! $forms = config('campaign-monitor.forms')) { + return; + } + + foreach ($forms as $config) { + (new Migrators\ConfigToFormData)->handle($config); + } + + ConfigWriter::edit('campaign-monitor')->remove('forms')->save(); + } + + private function migrateUserToYaml() + { + $config = UserConfig::load(); + + if ($config->exists()) { + $config = $config->config(); + config(['campaign-monitor.add_new_users' => $config['add_new_users'] ?? false]); + config(['campaign-monitor.users' => $config['users'] ?? []]); + + return; + } + + UserConfig::load([ + 'add_new_users' => config('campaign-monitor.add_new_users', false), + 'users' => config('campaign-monitor.users', []), + ])->save(); + + ConfigWriter::edit('campaign-monitor') + ->remove('add_new_users') + ->remove('users') + ->save(); + } } diff --git a/src/Subscriber.php b/src/Subscriber.php index 9eb5780..e5e29e2 100644 --- a/src/Subscriber.php +++ b/src/Subscriber.php @@ -15,15 +15,25 @@ class Subscriber private Collection $config; - public static function fromSubmission(Submission $submission): self + public static function fromSubmission(Submission $submission): ?self { - return new self( - $submission->data(), - Arr::first( - config('campaign-monitor.forms', []), - fn (array $formConfig) => $formConfig['form'] == $submission->form()->handle() - ) - ); + if (! $form = $submission->form()) { + return null; + } + + if (! $config = $form->get('campaign_monitor', [])) { + return null; + } + + if (! $config['enabled'] ?? false) { + return null; + } + + if (! $config = Arr::get($config, 'settings', [])) { + return null; + } + + return new self($submission->data(), $config); } public static function fromUser(User $user): self @@ -37,13 +47,18 @@ public static function fromUser(User $user): self /** * @param array|Collection $data */ - public function __construct($data, array $config = null) + public function __construct($data, ?array $config = null) { $this->data = collect($data); $this->config = collect($config); } - private function email(): string + public function config(): array + { + return $this->config->all(); + } + + public function email(): string { return $this->get($this->config->get('primary_email_field', 'email')) ?? ''; } @@ -127,6 +142,7 @@ public function subscribe(): void 'Value' => $data, ]; } + return $r; } @@ -134,12 +150,12 @@ public function subscribe(): void [ 'Key' => $item['key'], 'Value' => $fieldData, - ] + ], ]; }) - ->filter() - ->values() - ->all(), + ->filter() + ->values() + ->all(), ]; $result = CampaignMonitor::subscribers($this->config->get('list_id'))->add($payload); @@ -149,4 +165,4 @@ public function subscribe(): void Log::error(json_encode($result)); } } -} \ No newline at end of file +} diff --git a/src/UserConfig.php b/src/UserConfig.php new file mode 100644 index 0000000..002b6b8 --- /dev/null +++ b/src/UserConfig.php @@ -0,0 +1,87 @@ +all(); + } + + $this->config = $config ?? $this->getSavedSettings(); + } + + /** + * Load user config collection. + * + * @param array|Collection|null $config + * @return static + */ + public static function load($config = null) + { + $class = app(UserConfig::class); + + return new $class($config); + } + + /** + * Save user config to yaml. + */ + public function config() + { + return $this->config; + } + + /** + * Does it exist yet? + */ + public function exists() + { + return File::exists($this->path()); + } + + /** + * Save user config to yaml. + */ + public function save() + { + File::put($this->path(), YAML::dump($this->config)); + } + + /** + * Get user config from yaml + * + * @return array + */ + protected function getSavedSettings() + { + return Blink::once('statamic-campaign-monitor::user-config', function () { + return collect(YAML::file($this->path())->parse()) + ->all() ?? []; + }); + } + + /** + * Get site defaults yaml path. + * + * @return string + */ + protected function path() + { + return resource_path('campaign_monitor.yaml'); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 951b7e2..f2d3882 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,16 +2,21 @@ namespace StatamicRadPack\CampaignMonitor\Tests; -use Statamic\Extend\AddonTestCase; use Statamic\Facades\Blueprint as BlueprintFacade; use Statamic\Facades\YAML; use Statamic\Statamic; +use Statamic\Testing\AddonTestCase; use StatamicRadPack\CampaignMonitor\ServiceProvider; class TestCase extends AddonTestCase { protected string $addonServiceProvider = ServiceProvider::class; + protected function getPackageProviders($app) + { + return array_merge(parent::getPackageProviders($app), [\Stillat\Proteus\WriterServiceProvider::class]); + } + protected function resolveApplicationConfiguration($app) { parent::resolveApplicationConfiguration($app); diff --git a/tests/Unit/ListenersTest.php b/tests/Unit/ListenersTest.php index 60cfa18..334c484 100644 --- a/tests/Unit/ListenersTest.php +++ b/tests/Unit/ListenersTest.php @@ -3,6 +3,7 @@ namespace StatamicRadPack\CampaignMonitor\Tests\Unit; use Illuminate\Support\Facades\Event; +use PHPUnit\Framework\Attributes\Test; use Statamic\Events\SubmissionCreated; use Statamic\Events\UserRegistered; use Statamic\Facades\Form as FormAPI; @@ -35,7 +36,7 @@ public function setUp(): void ->data(['foo' => 'bar']); } - /** @test */ + #[Test] public function does_respond_to_submission_created_event() { $event = new SubmissionCreated($this->submission); @@ -45,7 +46,7 @@ public function does_respond_to_submission_created_event() Event::dispatch($event); } - /** @test */ + #[Test] public function does_respond_to_user_registered_event() { $event = new UserRegistered([]); diff --git a/tests/Unit/MigratorTest.php b/tests/Unit/MigratorTest.php new file mode 100644 index 0000000..5882146 --- /dev/null +++ b/tests/Unit/MigratorTest.php @@ -0,0 +1,37 @@ +handle('test') + ->data([]) + ->save(); + + (new ConfigToFormData) + ->handle([ + 'form' => 'test', + 'check_consent' => true, + ]); + + $data = Form::find('test')->data()->all(); + + $this->assertArrayHasKey('campaign_monitor', $data); + + $this->assertSame($data['campaign_monitor'], [ + 'enabled' => true, + 'settings' => [ + 'check_consent' => true, + ], + ]); + } +} diff --git a/tests/Unit/SubscriberFromSubmissionTest.php b/tests/Unit/SubscriberFromSubmissionTest.php index ef1c1a9..d14fdf4 100644 --- a/tests/Unit/SubscriberFromSubmissionTest.php +++ b/tests/Unit/SubscriberFromSubmissionTest.php @@ -2,6 +2,7 @@ namespace StatamicRadPack\CampaignMonitor\Tests\Unit; +use PHPUnit\Framework\Attributes\Test; use Statamic\Facades\Form as FormAPI; use Statamic\Forms\Form; use Statamic\Forms\Submission; @@ -33,7 +34,7 @@ public function setUp(): void ]); } - /** @test */ + #[Test] public function can_create_subscriber_from_submission() { $formConfig = [[ @@ -46,7 +47,7 @@ public function can_create_subscriber_from_submission() $this->assertInstanceOf(Subscriber::class, $subscriber); } - /** @test */ + #[Test] public function has_consent_by_default() { $formConfig = [ @@ -60,7 +61,7 @@ public function has_consent_by_default() $this->assertTrue($consent); } - /** @test */ + #[Test] public function no_consent_when_no_consent_field() { $formConfig = [ @@ -77,7 +78,7 @@ public function no_consent_when_no_consent_field() $this->assertFalse($consent); } - /** @test */ + #[Test] public function no_consent_when_consent_field_is_false() { $formConfig = [ @@ -96,7 +97,7 @@ public function no_consent_when_consent_field_is_false() $this->assertFalse($consent); } - /** @test */ + #[Test] public function consent_when_default_consent_field_is_true() { $formConfig = [ @@ -115,7 +116,7 @@ public function consent_when_default_consent_field_is_true() $this->assertTrue($consent); } - /** @test */ + #[Test] public function consent_when_configured_consent_field_is_true() { $formConfig = @@ -135,4 +136,25 @@ public function consent_when_configured_consent_field_is_true() $this->assertTrue($consent); } + + #[Test] + public function it_gets_config_from_form() + { + $settings = [ + 'check_consent' => true, + 'primary_email_field' => 'email', + ]; + + $this->form->merge([ + 'campaign_monitor' => [ + 'enabled' => true, + 'settings' => $settings, + ], + ])->save(); + + $subscriber = Subscriber::fromSubmission($this->submission); + + $this->assertSame($settings, $subscriber->config()); + $this->assertSame($subscriber->email(), 'foo@bar.com'); + } } diff --git a/tests/Unit/SubscriberFromUserTest.php b/tests/Unit/SubscriberFromUserTest.php index 0f1c60b..b4c2ea3 100644 --- a/tests/Unit/SubscriberFromUserTest.php +++ b/tests/Unit/SubscriberFromUserTest.php @@ -2,6 +2,7 @@ namespace StatamicRadPack\CampaignMonitor\Tests\Unit; +use PHPUnit\Framework\Attributes\Test; use Statamic\Facades\User; use StatamicRadPack\CampaignMonitor\Subscriber; use StatamicRadPack\CampaignMonitor\Tests\TestCase; @@ -19,7 +20,7 @@ public function setUp(): void ->password('password'); } - /** @test */ + #[Test] public function can_create_subscriber_from_user() { $config = [[ @@ -31,7 +32,7 @@ public function can_create_subscriber_from_user() $this->assertInstanceOf(Subscriber::class, $subscriber); } - /** @test */ + #[Test] public function has_consent_by_default() { $subscriber = new Subscriber($this->userData(), []); @@ -39,7 +40,7 @@ public function has_consent_by_default() $this->assertTrue($subscriber->hasConsent()); } - /** @test */ + #[Test] public function no_consent_when_no_consent_field() { $config = [ @@ -51,7 +52,7 @@ public function no_consent_when_no_consent_field() $this->assertFalse($subscriber->hasConsent()); } - // /** @test */ + // #[Test] // public function no_consent_when_consent_field_is_false() // { // $formConfig = [ @@ -70,7 +71,7 @@ public function no_consent_when_no_consent_field() // $this->assertFalse($consent); // } - // /** @test */ + // #[Test] // public function consent_when_default_consent_field_is_true() // { // $formConfig = [ @@ -89,7 +90,7 @@ public function no_consent_when_no_consent_field() // $this->assertTrue($consent); // } - // /** @test */ + // #[Test] // public function consent_when_configured_consent_field_is_true() // { // $formConfig =