Compare commits

..

168 Commits
4.0.1 ... 4.2.0

Author SHA1 Message Date
57abbbfacd Release 4.2.0 2022-12-12 14:18:33 +01:00
78446d174a Fix quotes in a queries processed by $wpdb
These queries failed when ANSI_QUOTES mode is enabled
[MAILPOET-4887]
2022-12-12 13:59:09 +01:00
917d64a3e3 Print sql_mode when starting test environment
[MAILPOET-4887]
2022-12-12 13:59:09 +01:00
a3d51b2b08 Add ANSI and ONLY_FULL_GROUP_BY to sql_mode for tests environment
The default modes shipped with the mysql or mariaDB docker containers are
STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
In this commit I added ANSI, ONLY_FULL_GROUP_BY so that we are sure that we don't break compatibility with those modes
[MAILPOET-4887]
2022-12-12 13:59:09 +01:00
3ffbd6e236 Add ANSI and ONLY_FULL_GROUP_BY to sql_mode for dev environment
The default modes shipped with the mysql or mariaDB docker containers are
STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
in this commit I added ANSI, ONLY_FULL_GROUP_BY so that we are sure that we don't break compatibility with those modes
[MAILPOET-4887]
2022-12-12 13:59:09 +01:00
9753331d52 Improve sql_mode replace code to support both ANSI and ANSI_QUOTES
[MAILPOET-4887]
2022-12-12 13:59:09 +01:00
b266edb8e7 Make initial migration ANSI_QUOTES compatible
We run the initial migrations via dbDelta which internally uses
$wpdb. ANSI_QUOTES is not on the list of WPDB's incompatible modes
(767bdad516/wp-includes/class-wpdb.php (L648-L655))
So we need to make sure SQL queries we run through wpdb are ANSI_QUOTES compatible.
This commit makes initial migrations compatible with the ANSI_QUETES mode.
[MAILPOET-4887]
2022-12-12 13:59:09 +01:00
f1899055b8 Drop StepType from mailpoet.automation.step.more-controls filter
[MAILPOET-4889]
2022-12-12 12:23:52 +01:00
c3f0a36665 Make it possible to display the MP logo without a link
[MAILPOET-4819]
2022-12-08 13:30:12 +01:00
88efb1f3d1 Move logo to the top bar in the welcome wizard
[MAILPOET-4819]
2022-12-08 13:30:12 +01:00
146f5881f7 Adjustments to the layout of the welcome wizard layout
[MAILPOET-4819]
2022-12-08 13:30:12 +01:00
3279fb1154 Move regexes out of KeyActivation to avoid rerunning them in every render
[MAILPOET-4749]
2022-12-08 11:00:09 +01:00
5f5efbe876 Change title and description of the key activation settings tab
This commit changes the text of the title and the description of the key
activation settings tab to hopefully make it more clear the meaning of the
key and what they should do if they don't have one or if they are unsure
where they can get their key.

[MAILPOET-4749]
2022-12-08 11:00:09 +01:00
12afcfb656 Improve readability
[MAILPOET-3487]
2022-12-07 11:53:48 +01:00
0aac9e9d60 Test language switches in newsletters
[MAILPOET-3487]
2022-12-07 11:53:48 +01:00
4e3b1527cd If no translation for the current language exists, return 'en'
[MAILPOET-3487]
2022-12-07 11:53:48 +01:00
b27dcdd40a Use new language function in twig email templates
[MAILPOET-3487]
2022-12-07 11:53:48 +01:00
7b584dd482 Add language function to twig
[MAILPOET-3487]
2022-12-07 11:53:48 +01:00
5e71d94b62 Use website language for newsletters
[MAILPOET-3487]
2022-12-07 11:53:48 +01:00
8bb4338627 Inject WPFunctions
[MAILPOET-3487]
2022-12-07 11:53:48 +01:00
4bcd4a2cf2 Add single const to expose shortcodes for unsubscribe link
[MAILPOET-4862]
2022-12-07 10:52:07 +01:00
ea7971cb3b Translate the shortcode for instance unsubscribe link
The [link:subscription_instant_unsubscribe_url] shown on
stats page was not translated

[MAILPOET-4862]
2022-12-07 10:52:07 +01:00
9036b210a0 Add test for click stat recording for 1-click
[MAILPOET-4862]
2022-12-07 10:52:07 +01:00
f337ac388b Fix wrong assertions in PagesTest
[MAILPOET-4862]
2022-12-07 10:52:07 +01:00
b0ae21ec60 Record click stat for 1-click unsubscribe
[MAILPOET-4862]
2022-12-07 10:52:07 +01:00
7d11eeeddd Add triggering of the actionScheduler
[MAILPOET-4899]
2022-12-07 07:42:03 +01:00
4577ca5476 Fix tests
[MAILPOET-3982]
2022-12-06 14:17:49 +01:00
846794b60d Improve Cron error message
This commit gives more context to the maximum execution limit error

[MAILPOET-3982]
2022-12-06 14:17:49 +01:00
5757af95aa Release 4.1.1 2022-12-06 13:04:01 +01:00
b8c3b38652 Skip SwitchingLanguagesCest on release branch
The test would fail because the translations packs are not ready
at the time when we prepare the release.
[MAILPOET-4863]
2022-12-05 12:02:15 +01:00
3d21e4f35e Increase retries when waiting for languages update to be available
[MAILPOET-4863]
2022-12-05 12:02:15 +01:00
73ce89d051 Mention both forms and emails when describing 3rd-party libraries and Google Fonts
[MAILPOET-4888]
2022-12-05 11:59:48 +01:00
49d9dd666b Fix coding styles issues in DisableMailFunctionNotice
[MAILPOET-4760]
2022-12-05 11:59:16 +01:00
53dda33c02 Update method and constant name
MAILPOET-4760
2022-12-05 10:25:28 +01:00
9b9f61bf13 Only queue test mail for sending when the mailpoet sending method is updated
MAILPOET-4760
2022-12-05 10:25:28 +01:00
651e2d3c56 Update tests and refactor method name
MAILPOET-4760
2022-12-05 10:25:28 +01:00
0bd627d3b1 Add support for checking misconfiguration of the PHP mail function
Some hosts do perform intentional misconfiguration of the mail function, causing it not to work.

When the mail function is misconfigured, we can still access and execute the mail function from within the codebase, but we get an error.

There’s no accurate way to know the PHP mail function is misconfigured. Unless we execute the function with all the proper parameters and check the exception error message against this error `Could not instantiate mail function.`

MAILPOET-4760
2022-12-05 10:25:28 +01:00
99d0eede80 Add tests for DisabledMailFunctionNotice
MAILPOET-4760
2022-12-05 10:25:28 +01:00
d09b4ca409 Add check for mail function and display notice if disabled
MAILPOET-4760
2022-12-05 10:25:28 +01:00
caa76983e4 Ensure action scheduler jobs are done
[MAILPOET-4864]
2022-12-02 14:58:48 +01:00
7b6bbb0bc3 Remove unnecessary integration test job for woo
After the release of HPOS we no longer need to install the special Woo build and
that caused that integration_test_woocommerce job and integration_test_woo_cot_off job
have completely same configuration.
This commit removes one of those job.
[MAILPOET-4880]
2022-12-01 12:20:42 -03:00
cdf7c81a94 Remove unnecessary acceptance_tests_woo_cot_off job
The same set of tests run within acceptance_tests_base_and_woo_cot_off job
[MAILPOET-4880]
2022-12-01 12:20:42 -03:00
86812c5259 Rename acceptance test job to contain info about HPOS configuration
[MAILPOET-4880]
2022-12-01 12:20:42 -03:00
657302b720 Simplify <Tags> component and add wrapper components
[MAILPOET-4628]
2022-12-01 13:36:18 +01:00
172b5215d2 Fix strict types definition spacing
[MAILPOET-4879]
2022-11-30 12:39:19 +01:00
52a9d9f76c Remove redundant name from package.json 2022-11-30 12:30:52 +01:00
8eb7a48d3e Fix display of Text option in the editor sidebar
[MAILPOET-4808]
2022-11-30 12:30:52 +01:00
a8bceffc9c Add forgotten strict_types to Homepage page class
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
2c728c793a Redirect to main page instead of emails page from logo and after reinstall
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
8d974d8147 Add mainPageSlug to MailPoet module
In some places we hardcode emails page as the main page.
This property is meant to be used in places where we want to link
to main plugin page so that the links change when homepage is active
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
8fbc5c270a Place home at the first position in submenu
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
92dc5921df Set main page to homepage in case the feature is active
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
3c3ce37720 Temporarily add static property for MAIN_PAGE_SLUG
We need to be able to change it when homepage feature is active.
When we remove the feature flag will switch back to using constant.
Note I also kept the constant in case a third party plugin uses it.
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
f369e399ed Distinguish main page and emails page
There are some cases where we link or redirect to main page but
actually we want to redirect to emails page. It happens that currently they are
the same page, but we need to distinguish these cases for the future when
we switch the main page to new homepage.
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
01aa1e1e52 Refactor page slugs into constants
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
2bbc1b7063 Add homepage page and submenu item hidden behind feature flag
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
04b8a0ed73 Add feature flag for homepage
[MAILPOET-4824]
2022-11-30 11:42:41 +01:00
761f7c6537 Prevent issues if other plugins define WC function
It's possible that other plugins might define wc_get_page_id, so it's
more important to know that WC is installed/active than to know if the
function itself exists.

For good measure I'm including a cast to int even though the WC version
of the function always returns an integer. This is probably unnecessary
but it protects us from the possibility of the WC version of the
function returning something other than an integer in the future.

[MAILPOET-4834]
2022-11-30 11:03:40 +01:00
723dc2c9d3 Fix type errors in tests
[MAILPOET-2688]
2022-11-29 15:04:09 +01:00
d66fbb1c20 Fix confirmed IP value in tests
[MAILPOET-2688]
2022-11-29 15:04:09 +01:00
c2107b8d59 Enable strict types rule for all files
[MAILPOET-2688]
2022-11-29 15:04:09 +01:00
926620e8f8 Ignore strict types rule in all existing files that don't have it
[MAILPOET-2688]
2022-11-29 15:04:09 +01:00
82aeb89854 Use strict types in tests
[MAILPOET-2688]
2022-11-29 15:04:09 +01:00
c67c58709b Unify spacing of declare statements
[MAILPOET-2688]
2022-11-29 15:04:09 +01:00
75b5958a53 Release 4.1.0 2022-11-29 13:56:02 +01:00
bba5101669 Replace switching groups' tab by a new function
[MAILPOET-4861]
2022-11-29 10:58:11 +01:00
b9c5dddbaf Try switch group multiple times
[MAILPOET-4861]
2022-11-29 10:58:11 +01:00
0566b3f5fa Fix remaining code style issues
[MAILPOET-4850]
2022-11-28 22:24:54 +01:00
ac4adac1ab Fix test class name
[MAILPOET-4850]
2022-11-28 22:24:54 +01:00
33a9097719 Fix trim(null) issue
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
08c74cdf8b Fix SlevomatCodingStandard.Namespaces.UnusedUses.MismatchingCaseSensitivity
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
8c5222d850 Fix WordPress.Security.ValidatedSanitizedInput.InputNotSanitized and related errors
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
08c76a46af Fix Squiz.Classes.ClassFileName.NoMatch and related errors
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
3d24cb1deb Fix Generic.Classes.DuplicateClassName.Found
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
a151f93be1 Fix Generic.CodeAnalysis.JumbledIncrementer.Found
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
bce6a06c15 Fix Sniffs.ControlSignature.Found
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
10a6e387f3 Fix Squiz.Scope.MethodScope.Missing
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
b6a37f274c Fix Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
2cdbc68643 Fix Squiz.Classes.ValidClassName.NotCamelCaps
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
7db40b27b5 Fix errors automatically with phpcbf
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
b1760ff676 Add MinimalPluginStandard to lint-staged command
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
293eef2c78 Add MinimalPluginStandard to Robofile
./do qa:minimal-plugin-standard will not execute the MinimalPluginStandard phpcs sniffs
./do qa:php has been extended to include the sniffs as well

[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
299c6b779e Remove MinimalPluginStandard from ruleset
[MAILPOET-4850]
2022-11-28 22:54:13 +03:00
842f435976 Add default value for method to StatisticsUnsubscribeEntity
When entity is created the default value is not set and it may causes
failures when it is not set additionally.
This commit sets default value and also defines a constant for the default value.
[PREMIUM-211]
2022-11-28 18:21:52 +01:00
11faf925cc Refactor time assertions in AutomaticEmailTest to use assert with delta
Carbon:setTestNow was not working because we are instantiating the new Carbon instance with value.
This commit updates all DateTime assertions to use the new assertEqualDateTimes method
[MAILPOET-4867]
2022-11-28 14:19:30 +01:00
1295aa21cc Skip congratulatory email if we know it will fail
[MAILPOET-4641]
2022-11-28 14:12:50 +01:00
84cd137c76 Don't switch to MSS when activating key without sending
[MAILPOET-4641]
2022-11-28 14:12:50 +01:00
37067dff67 Add state to MSS key check response
[MAILPOET-4641]
2022-11-28 14:12:50 +01:00
c7f850e1ba Declare strict types
[MAILPOET-4842]
2022-11-28 13:03:06 +01:00
b25f2cd5f4 Enable a Trigger to activate a second automation
[MAILPOET-4842]
2022-11-28 13:03:06 +01:00
af95080b67 Add test for TriggerHandler
[MAILPOET-4842]
2022-11-28 13:03:06 +01:00
6b8c35d5fe Fix Manage Sender Domain modal hides underneath Preview newsletter modal
MAILPOET-4812
2022-11-28 12:14:52 +01:00
a35e0dced4 Accept null opt-in values for in Woo Blocks integration
[MAILPOET-4804]
2022-11-28 11:51:27 +01:00
c6259eb185 Create acceptance test container upfront with one retry
This is and attempt to fix random issue with
Error response from daemon: Conflict. The container name "/wordpress_X" is already in use
[MAILPOET-4851]
2022-11-28 09:14:56 +01:00
670017b342 Update nesbot/carbon to the latest version
This is needed for MailPoet to work well with the upcoming PHP 8.2.

nesbot/carbon versions previous to 2.62.1 could cause issues when used
with PHP 8.2, see this PR for more information:
https://github.com/briannesbitt/Carbon/pull/2663

Without this update MailPoet users will see the following fatal error
when using PHP 8.2:

```
TypeError
MailPoetVendor\Carbon\Carbon::setLastErrors(): Argument #1 ($lastErrors) must be of type array, bool given, called in /srv/www/mp/public_html/wp-content/plugins/mailpoet/vendor-prefixed/nesbot/carbon/src/Carbon/Traits/Creator.php on line 567
```

[MAILPOET-4838]
2022-11-26 09:38:05 +01:00
ce7b210da9 Bump tested up to
[MAILPOET-4841]
2022-11-26 09:09:00 +01:00
1a2d8b8d40 Add saving nicename for created WP users
[MAILPOET-4841]
2022-11-26 09:09:00 +01:00
fe2df00a8c Use the latest WP version as default for acceptance tests
[MAILPOET-4841]
2022-11-26 09:09:00 +01:00
20577d974f Replace custom createSubscriber method with common factory method
[MAILPOET-4860]
2022-11-25 17:17:48 +01:00
7369465a3a Add subscribers cleanup to stats notification worker test
The test creates subscribers and there was not cleanup so this was increasing
probability of conflict in subscribers email.
[MAILPOET-4860]
2022-11-25 17:17:48 +01:00
5769fa45f5 Use helper methods for method column migration
This fixes issues with MailPoet in multiple schemas on the same MySQL instance as well
as simplifies the code. The migration was also renamed to a newer date. Additionally, the
edit of the initial MailPoet migration was reverted as this is not needed.

[MAILPOET-4733]
2022-11-25 14:51:57 +01:00
193b4cbf98 Set missing unsubscribe method for failing tests
[MAILPOET-4733]
2022-11-25 14:51:57 +01:00
461df1a560 Adjust strict_types & method typehint based on PR feedback
[MAILPOET-4733]
2022-11-25 14:51:57 +01:00
d5f78680eb Add integration test for unsubscibe properties
[MAILPOET-4733]
2022-11-25 14:51:57 +01:00
96dde7107b Expose unsubscribe analytics properperties
[MAILPOET-4733]
2022-11-25 14:51:57 +01:00
3e756bfadd Add test to assert correct unsubscription method is saved
[MAILPOET-4733]
2022-11-25 14:51:57 +01:00
82c755200e Augment track persister test with method as meta
[MAILPOET-4733]
2022-11-25 14:51:57 +01:00
735d33d05b Add method of tracking when tracking unsubscriptions
[MAILPOET-4733]
2022-11-25 14:51:57 +01:00
90c8e5b2c9 Introduce method column to statistics_unsubscribes table
[MAILPOET-4733]
2022-11-25 14:51:57 +01:00
cd1f06b116 Forbid assert() in code base
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
173f347431 Fix assert in Helper
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
353d3389cd Fix assert in data factories
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
fe364978a1 Fix usage of assert in acceptance tests
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
cd512bbb01 Fix instanceOf assertions in unit tests
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
f5193df721 Fix not null assertions in integration tests
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
25b5d24867 Fix is_array assertion in integration tests
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
1d99ff0943 Fix all is_string assertions in integration tests
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
99d6d96b05 Fix all is_numeric asserts in integration tests
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
6ddfe2c605 Remove ignores no longer needed
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
d2ec7bba42 Replace instance_of asserts in integration tests
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
2557171953 Fix assert() in lib
[MAILPOET-4258]
2022-11-25 14:32:34 +01:00
0d7e45ea03 Fix filename that is removed by fix-monolog.php
The following error is being thrown when running composer commands:

```
> php fix-monolog.php
rm: cannot remove 'mailpoet/mailpoet/prefixer/../vendor-prefixed/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php': No such file or directory
```

This is happening because in commit 9b71a7804c
we updated Monolog from v1 to v2. v2 renamed the file ElasticSearchHandler.php
to ElasticsearchHandler.php (see
4c7795d310).
Note that search is not spelled with a capital S anymore. We didn’t update
fix-monolog.php to reflect this change.

This commit updates fix-monolog.php to use the new file name and to remove
the error.

[MAILPOET-4856]
2022-11-25 13:47:24 +01:00
e677169a51 Update Mysql image for integration and acceptance tests
[MAILPOET-4851]
2022-11-25 13:37:08 +01:00
e268eac378 Add healthcheck for mysql service in the test environment
This is replacement for custom wait scripts and also should ensure
that DB is ready before starting the wordpress serive container,
which was missing the check.
[MAILPOET-4851]
2022-11-25 13:37:08 +01:00
375f2b13c5 Try select option in select 2 multiple times
[MAILPOET-4555]
2022-11-25 13:21:42 +01:00
34406a2f72 Fix flaky WooCommercePurchaseTest
[MAILPOET-4854]
2022-11-25 13:10:30 +01:00
cc658bcc3d Split one big test case into three smaller
[MAILPOET-4846]
2022-11-25 13:04:46 +01:00
973aefe7ae Hide black Friday notice in acceptance tests
[MAILPOET-4846]
2022-11-25 13:04:46 +01:00
34e91251e8 Add waiting on clickable trash button
[MAILPOET-4846]
2022-11-25 13:04:46 +01:00
882402645d Do not wrap automations beta badge, make it a bit smaller
[MAILPOET-4840]
2022-11-25 09:55:11 +01:00
d9d4dccc09 Make instruction on how to test with different PHP versions more generic
This commit just updates the README file so that it doesn't mention
specific PHP versions. This way we don't have to update it every time we
add a new version to the dev environment.

[MAILPOET-4855]
2022-11-25 09:33:39 +01:00
9d2fcccbf5 Add option to run the dev env with PHP 8.2RC6
[MAILPOET-4855]
2022-11-25 09:33:39 +01:00
c4fdd881e6 Retry language updates if they are not scheduled yet
[MAILPOET-4849]
2022-11-24 16:58:18 +01:00
83f7eee8ae Early return to make the migration idempotent
[MAILPOET-4852]
2022-11-24 16:04:29 +01:00
dc1f63d8bb Rename segments migration to be executed again
[MAILPOET-4852]
2022-11-24 16:04:29 +01:00
3e2425abd8 Rewrite segments migration to use helper methods, Doctrine DBAL, and lower number of queries
[MAILPOET-4852]
2022-11-24 16:04:29 +01:00
65e78c7990 Add helper to determine whether a column exists
[MAILPOET-4852]
2022-11-24 16:04:29 +01:00
2bdc5d3683 Add helper to get current table name
[MAILPOET-4852]
2022-11-24 16:04:29 +01:00
1de276378f Use different container names for different parallel runs
[MAILPOET-4851]
2022-11-24 15:48:43 +01:00
cc76fe77f0 Ensure that docker caching on CircleCi is disabled
[MAILPOET-4851]
2022-11-24 13:29:20 +01:00
c8636aac6f Update selenium and chrome image
[MAILPOET-4848]
2022-11-24 10:34:59 +01:00
a09f41143e Update codeception, webdriver and lucatume/browser
[MAILPOET-4848]
2022-11-24 10:34:59 +01:00
8b29694446 Compare scheduledAt with delta 2022-11-24 10:06:59 +01:00
5e0e89408c Test CaptchaFormRenderer
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
86076547c3 Raise aria-live level
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
b1bbabe14d early return when no audioCaptcha element was found
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
f5c678ec2d Initialize session when no ID exists
[MAILPOET-4514]
2022-11-24 09:20:39 +01:00
223625bd9b Use constant for endpoint
[MAILPOET-4514]
2022-11-24 09:20:39 +01:00
fbd7cf8cc7 Use SubscriberEntity instead of the Model
[MAILPOET-4514]
2022-11-24 09:20:39 +01:00
26c7e4d1cc Use null instead of empty string
[MAILPOET-4514]
2022-11-24 09:20:39 +01:00
4832771185 Refactor the captcha system
The current Captcha class has a lot of responsibilities. It renders the captcha
image, can check if a certain captcha type is a Google captcha, if a captcha is
required for a certain email. The SubscriberSubscribeController is not only in
charge of "controlling" the subscription process but also validates, whether a
captcha is correct or not. This architecture made it difficult to extend the
functionality and introduce the audio captcha feature.

Therefore this commit refactors the captcha architecture and tries to seperate
the different concerns into several classes and objects. Validation is now done
by validators.

The CaptchaPhrase now is in charge of keeping the captcha phrase consistent
between the image and the new audio, so that you can renew the captcha and both
captchas are in sync.

[MAILPOET-4514]
2022-11-24 09:20:39 +01:00
7fb8d64628 Rename CaptchaRenderer to CaptchaFormRenderer
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
36fed3bbf8 Enable output of audio captcha when image captcha has not yet been generated
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
8ab738b315 Use classes instead of ids for captcha elements
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
b84b9606e9 Remove type residual from audio captcha url building
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
aa68b7e148 Bust caching when building the audio captcha url
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
ca44339512 Fix typo in button cursor property
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
91f5376dfc Apply prettier
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
d51ef70db6 Add audio assets
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
c164268c20 Change file name to lower case
and codestyle
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
4c7c94c75d Update JavaScript for captcha audio player
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
ccf141b279 Add button icons
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
e42808f22d Update Captcha UI to add audio button
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
75a4b2c538 Add Captcha Audio endpoint to Router
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
f1d64c0572 Add Captcha styles
[MAILPOET-4203]
2022-11-24 09:20:39 +01:00
25c57bf9fe Fix flaky acceptance test for tag filter
[MAILPOET-4844]
2022-11-23 16:38:49 +01:00
079c90dbba Add acceptance test for switching languages
[MAILPOET-4147]
2022-11-23 12:50:32 +01:00
0fc342ee4c Release 4.0.1 2022-11-22 13:57:46 +01:00
1376 changed files with 5601 additions and 3137 deletions

View File

@ -312,6 +312,7 @@ jobs:
working_directory: /home/circleci/mailpoet/mailpoet
machine:
image: ubuntu-2204:2022.10.2
docker_layer_caching: false
parameters:
multisite:
type: integer
@ -411,6 +412,12 @@ jobs:
circleci tests glob "tests/acceptance/**/*Cest.php" | circleci tests split --split-by=timings > tests/acceptance/_groups/circleci_split_group
fi
cat tests/acceptance/_groups/circleci_split_group
- run:
name: Create docker containers for test
# We experienced some failures when creating containers so we do it explicitly with one retry
command: |
cd tests/docker
docker-compose create || docker-compose create
- run:
name: Run acceptance tests
command: |
@ -477,6 +484,7 @@ jobs:
working_directory: /home/circleci/mailpoet/mailpoet
machine:
image: ubuntu-2204:2022.10.2
docker_layer_caching: false
environment:
CODECEPTION_IMAGE_VERSION: << parameters.codeception_image_version >>
parameters:
@ -618,7 +626,7 @@ workflows:
- build
- acceptance_tests:
<<: *slack-fail-post-step
name: acceptance_tests
name: acceptance_tests_base_and_woo_cot_off
requires:
- unit_tests
- static_analysis_php8
@ -646,28 +654,10 @@ workflows:
- static_analysis_php8
- qa_js
- qa_php
- acceptance_tests:
<<: *slack-fail-post-step
name: acceptance_tests_woo_cot_off
group: woo
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- js_tests:
<<: *slack-fail-post-step
requires:
- build
- integration_tests:
<<: *slack-fail-post-step
group: woo
name: integration_test_woocommerce
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- integration_tests:
<<: *slack-fail-post-step
group: woo
@ -728,15 +718,13 @@ workflows:
<<: *slack-fail-post-step
requires:
- build
- acceptance_tests
- acceptance_tests_base_and_woo_cot_off
- js_tests
- integration_test_woocommerce
- integration_test_base
- integration_test_woo_cot_no_sync
- integration_test_woo_cot_off
- integration_test_woo_cot_sync
- acceptance_tests_woo_cot_sync
- acceptance_tests_woo_cot_off
- acceptance_tests_woo_cot_no_sync
nightly:

View File

@ -126,23 +126,24 @@ You can access this help in your command line running `./do` without parameters.
[Read the article.](https://mailpoet.atlassian.net/wiki/spaces/MAILPOET/pages/629374977/Adding+new+templates+to+the+plugin)
## 🚥 Testing with PHP 7.4 or PHP 8.0
## 🚥 Testing with different PHP versions
To switch the environment to PHP 7.4/8.0:
To switch the environment to a different PHP version:
1. Configure the `wordpress` service in `docker-compose.override.yml` to build from the php74 Dockerfile:
1. Check https://github.com/mailpoet/mailpoet/tree/trunk/dev for a list of available PHP versions. Each directory starting with `php` corresponds to a available version.
2. Configure the `wordpress` service in `docker-compose.override.yml` to build from the desired PHP version Dockerfile (replace {PHP_VERSION} with the name of the directory that corresponds to the version that you want to use):
```yaml
wordpress:
build:
context: .
dockerfile: dev/php74/Dockerfile # OR dev/php80/Dockerfile
dockerfile: dev/{PHP_VERSION}/Dockerfile
```
2. Run `docker-compose build wordpress`.
3. Start the stack with `./do start`.
3. Run `docker-compose build wordpress`.
4. Start the stack with `./do start`.
To switch back to PHP 8.1 remove what was added in 1) and, run `docker-compose build wordpress` for application container and `docker-compose build test_wordpress` for tests container,
To switch back to the default PHP version remove what was added in 2) and, run `docker-compose build wordpress` for application container and `docker-compose build test_wordpress` for tests container,
and start the stack using `./do start`.
## ✅ TODO

46
dev/php82/Dockerfile Normal file
View File

@ -0,0 +1,46 @@
FROM php:8.2.0RC6-apache
ARG UID=1000
ARG GID=1000
# additinal extensions
RUN apt-get update \
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev gettext subversion \
&& \
# Install NodeJS, enable Corepack
curl -sL https://deb.nodesource.com/setup_17.x | bash - && \
apt-get install -y nodejs build-essential && \
corepack enable && \
\
# Install WP-CLI
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
chmod +x /usr/local/bin/wp && \
\
# Clean up
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY dev/php.ini /usr/local/etc/php/conf.d/php_user.ini
# msmtp config
RUN printf "account default\nhost smtp\nport 1025" > /etc/msmtprc
# xdebug build an config
ENV XDEBUGINI_PATH=/usr/local/etc/php/conf.d/xdebug.ini
RUN git clone -b "3.2.0RC2" --depth 1 https://github.com/xdebug/xdebug.git /usr/src/php/ext/xdebug \
&& docker-php-ext-configure xdebug --enable-xdebug-dev \
&& docker-php-ext-install xdebug \
&& mkdir /tmp/debug
COPY dev/xdebug.ini /tmp/xdebug.ini
RUN cat /tmp/xdebug.ini >> $XDEBUGINI_PATH
# php extensions
RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install mysqli
# allow .htaccess files (between <Directory /var/www/> and </Directory>, which is WordPress installation)
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
# ensure existing content in /var/www/html respects UID and GID, give Node permissions for Corepack
RUN chown -R ${UID}:${GID} /var/www/html && \
mkdir -p /.node && chown -R ${UID}:${GID} /.node

View File

@ -15,6 +15,7 @@ services:
volumes:
- my-datavolume:/var/lib/mysql
- ./dev/database/create_test_db.sh:/docker-entrypoint-initdb.d/10-create_test_db.sh
command: --sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,ANSI,ONLY_FULL_GROUP_BY
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
// phpcs:disable PSR1.Classes.ClassDeclaration
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
@ -425,6 +425,9 @@ class RoboFile extends \Robo\Tasks {
$collection->addCode(function() {
return $this->qaCodeSniffer([]);
});
$collection->addCode(function() {
return $this->qaMinimalPluginStandard([]);
});
return $collection->run();
}
@ -536,6 +539,55 @@ class RoboFile extends \Robo\Tasks {
$stringFilesToCheck = !empty($filesToCheck) ? implode(' ', $filesToCheck) : '.';
return $this->taskExec($task)
->arg('--ignore=' . implode(',', $ignorePatterns))
->rawArg($stringFilesToCheck)
->run();
}
public function qaMinimalPluginStandard(array $filesToCheck, $opts = ['severity' => 'all']) {
$severityFlag = $opts['severity'] === 'all' ? '-w' : '-n';
$task = implode(' ', [
'php -d memory_limit=-1',
'./tasks/code_sniffer/vendor/bin/phpcs',
'--extensions=php',
$severityFlag,
'--standard=tasks/code_sniffer/vendor/wporg/plugin-directory/MinimalPluginStandard',
'-s',
]);
$ignorePaths = [
'.mp_svn',
'assets',
'doc',
'generated',
'lib/Config/PopulatorData/Templates',
'lib-3rd-party',
'node_modules',
'plugin_repository',
'prefixer/build',
'prefixer/vendor',
'tasks/code_sniffer/vendor',
'tasks/phpstan/vendor',
'tasks/makepot',
'tools/vendor',
'temp',
'tests/_data',
'tests/_output',
'tests/_support/_generated',
'vendor',
'vendor-prefixed',
'views',
];
// the "--ignore" arg takes a list of regexes, we need to anchor and escape them
$ignorePatterns = array_map(function (string $path): string {
return '^' . preg_quote(__DIR__ . DIRECTORY_SEPARATOR . $path);
}, $ignorePaths);
$stringFilesToCheck = !empty($filesToCheck) ? implode(' ', $filesToCheck) : '.';
return $this
->taskExec($task)
->arg('--ignore=' . implode(',', $ignorePatterns))

BIN
mailpoet/assets/audio/0.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/1.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/2.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/3.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/4.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/5.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/6.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/7.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/8.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/9.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/a.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/b.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/c.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/d.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/e.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/f.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/g.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/h.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/i.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/j.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/k.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/l.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/m.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/n.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/o.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/p.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/q.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/r.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/s.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/t.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/u.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/v.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/w.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/x.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/y.mp3 Normal file

Binary file not shown.

BIN
mailpoet/assets/audio/z.mp3 Normal file

Binary file not shown.

View File

@ -51,4 +51,8 @@
.mailpoet_form_field_block {
display: block;
}
.mailpoet_form_field_input_nowrap {
white-space: nowrap;
}
}

View File

@ -22,6 +22,12 @@
}
}
#mailpoet-wizard-container {
.mailpoet-top-bar {
left: 0;
}
}
.mailpoet-wizard-logo {
margin-bottom: 100px;
text-align: center;
@ -35,6 +41,7 @@
align-items: center;
display: flex;
justify-content: center;
margin-top: 8px;
@include respond-to(medium-screen) {
flex-direction: column;
@ -42,7 +49,7 @@
}
.mailpoet-wizard-step-illustration {
margin-right: $grid-gap;
margin-right: $grid-gap-xl;
max-width: $grid-column;
text-align: center;
width: 100%;
@ -63,12 +70,16 @@
}
.mailpoet-wizard-step-content {
max-width: $grid-column-small + $grid-gap + $grid-column;
max-width: 480px;
width: 100%;
@include respond-to(medium-screen) {
max-width: $grid-column;
}
.mailpoet-button {
height: 36px;
}
}
.mailpoet-wizard-label {

View File

@ -0,0 +1,12 @@
.mailpoet_captcha_form {
.mailpoet_icon_button {
background: transparent;
border: 0;
cursor: pointer;
img {
height: 20px;
width: 20px;
}
}
}

View File

@ -112,3 +112,11 @@
max-width: 100%;
width: 100%;
}
.authorize-sender-email-and-domain-modal {
z-index: 30; // overlay other modals
}
.authorize-sender-email-and-domain-modal-overlay {
z-index: $modal-screen-overlay-z-index + 4; // overlay other modals
}

View File

@ -29,7 +29,6 @@ $beamer-dot-size: 8px;
}
.mailpoet-top-bar-logo {
cursor: pointer;
position: relative;
top: 2px;
z-index: 1;
@ -39,6 +38,10 @@ $beamer-dot-size: 8px;
max-width: 100%;
}
}
a.mailpoet-top-bar-logo {
cursor: pointer;
}
}
.mailpoet-top-bar-logo-desktop {

View File

@ -19,3 +19,4 @@
@import 'components-public/public';
@import 'components-public/animation';
@import 'components-public/form_colors';
@import 'components-public/captcha';

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="20" height="20"/><g><path d="M2 7h4l5-4v14l-5-4H2V7zm12.69-2.46C14.82 4.59 18 5.92 18 10s-3.18 5.41-3.31 5.46c-.06.03-.13.04-.19.04-.2 0-.39-.12-.46-.31-.11-.26.02-.55.27-.65.11-.05 2.69-1.15 2.69-4.54 0-3.41-2.66-4.53-2.69-4.54-.25-.1-.38-.39-.27-.65.1-.25.39-.38.65-.27zM16 10c0 2.57-2.23 3.43-2.32 3.47-.06.02-.12.03-.18.03-.2 0-.39-.12-.47-.32-.1-.26.04-.55.29-.65.07-.02 1.68-.67 1.68-2.53s-1.61-2.51-1.68-2.53c-.25-.1-.38-.39-.29-.65.1-.25.39-.39.65-.29.09.04 2.32.9 2.32 3.47z"/></g></svg>

After

Width:  |  Height:  |  Size: 587 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="20" height="20"/><g><path d="M10.25 1.02c5.1 0 8.75 4.04 8.75 9s-3.65 9-8.75 9c-3.2 0-6.02-1.59-7.68-3.99l2.59-1.52c1.1 1.5 2.86 2.51 4.84 2.51 3.3 0 6-2.79 6-6s-2.7-6-6-6c-1.97 0-3.72 1-4.82 2.49L7 8.02l-6 2v-7L2.89 4.6c1.69-2.17 4.36-3.58 7.36-3.58z"/></g></svg>

After

Width:  |  Height:  |  Size: 355 B

View File

@ -1,12 +1,10 @@
import { useState, Fragment } from 'react';
import { DropdownMenu } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { moreVertical, trash } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';
import { Hooks } from 'wp-js-hooks';
import { PremiumModal } from 'common/premium_modal';
import { Step as StepData } from './types';
import { storeName } from '../../store';
import { StepMoreControlsType } from '../../../types/filters';
type Props = {
@ -14,12 +12,6 @@ type Props = {
};
export function StepMoreMenu({ step }: Props): JSX.Element {
const { stepType } = useSelect(
(select) => ({
stepType: select(storeName).getStepType(step.key),
}),
[step],
);
const [showModal, setShowModal] = useState(false);
const moreControls: StepMoreControlsType = Hooks.applyFilters(
@ -53,7 +45,6 @@ export function StepMoreMenu({ step }: Props): JSX.Element {
},
},
step,
stepType,
);
const slots = Object.values(moreControls).filter(

View File

@ -2,7 +2,6 @@ import { __ } from '@wordpress/i18n';
import { chartBar } from '@wordpress/icons';
import { Hooks } from 'wp-js-hooks';
import { MoreControlType, StepMoreControlsType } from '../../../types/filters';
import { StepType } from '../../../editor/store';
import { Step } from '../../../editor/components/automation/types';
const emailStatisticsControl = (step: Step): MoreControlType => {
@ -30,12 +29,8 @@ export function registerStepControls() {
Hooks.addFilter(
'mailpoet.automation.step.more-controls',
'mailpoet',
(
controls: StepMoreControlsType,
step: Step,
stepType: StepType,
): StepMoreControlsType => {
if (stepType.key === 'mailpoet:send-email') {
(controls: StepMoreControlsType, step: Step): StepMoreControlsType => {
if (step.key === 'mailpoet:send-email') {
return {
statistics: emailStatisticsControl(step),
...controls,

View File

@ -92,6 +92,7 @@ function AuthorizeSenderEmailAndDomainModal({
<Modal
onRequestClose={onRequestClose}
contentClassName="authorize-sender-email-and-domain-modal"
overlayClassName="authorize-sender-email-and-domain-modal-overlay"
>
<Tabs activeKey={initialTab}>
<Tab

View File

@ -1,5 +1,5 @@
import { Heading } from 'common/typography/heading/heading';
import { Tags } from '../tags';
import { SegmentTags, StringTags } from '../tags';
export default {
title: 'Tags',
@ -18,15 +18,20 @@ export function Segments() {
<>
<Heading level={1}>Tags</Heading>
<Heading level={2}>Segments</Heading>
<Tags segments={segments} dimension="large" />
<SegmentTags segments={segments} dimension="large" />
<div className="mailpoet-gap" />
<Tags segments={segments}>
<SegmentTags segments={segments}>
<span>Prefix: </span>
</Tags>
</SegmentTags>
<Heading level={2}>Strings</Heading>
<Tags strings={strings} dimension="large" variant="good" />
<StringTags strings={strings} dimension="large" variant="good" />
<div className="mailpoet-gap" />
<Tags strings={strings} dimension="large" variant="good" isInverted />
<StringTags
strings={strings}
dimension="large"
variant="good"
isInverted
/>
</>
);
}

View File

@ -3,11 +3,36 @@ import { Tag, TagVariant } from './tag';
import { Tooltip } from '../tooltip/tooltip';
import { MailPoet } from '../../mailpoet';
type SharedTagProps = {
children?: ReactNode;
dimension?: 'large';
variant?: TagVariant;
isInverted?: boolean;
};
type TagData = {
name: string;
target?: string;
tooltip?: string;
};
type TagProps = SharedTagProps & {
tags: TagData[];
};
type StringTagsProps = SharedTagProps & {
strings: string[];
};
type Segment = {
name: string;
id?: string;
};
type SegmentTagsProps = SharedTagProps & {
segments: Segment[];
};
type SubscriberTag = {
id: string;
name: string;
@ -15,99 +40,89 @@ type SubscriberTag = {
tag_id: string;
};
type Props = {
children?: ReactNode;
dimension?: 'large';
segments?: Segment[];
subscriberTags?: SubscriberTag[];
strings?: string[];
variant?: TagVariant;
isInverted?: boolean;
type SubscriberTagsProps = SharedTagProps & {
subscribers: SubscriberTag[];
};
function Tags({
children,
dimension,
segments,
subscriberTags,
strings,
variant,
isInverted,
}: Props) {
function Tags({ children, tags, dimension, variant, isInverted }: TagProps) {
return (
<div className="mailpoet-tags">
{children}
{segments &&
segments.map((segment) => {
const tag = (
<Tag key={segment.name} dimension={dimension} variant="list">
{segment.name}
</Tag>
);
if (!segment.id) {
return tag;
}
const randomId = Math.random().toString(36).substring(2, 15);
const tooltipId = `segment-tooltip-${randomId}`;
return (
<div key={randomId}>
<Tooltip id={tooltipId} place="top">
{MailPoet.I18n.t('viewFilteredSubscribersMessage')}
</Tooltip>
<a
data-tip=""
data-for={tooltipId}
href={`admin.php?page=mailpoet-subscribers#/filter[segment=${segment.id}]`}
>
{tag}
</a>
</div>
);
})}
{subscriberTags &&
subscriberTags.map((subscriberTag) => {
const randomId = Math.random().toString(36).substring(2, 15);
const tooltipId = `tag-tooltip-${randomId}`;
const tag = (
<Tag
key={subscriberTag.name}
dimension={dimension}
variant={variant || 'list'}
isInverted={isInverted}
>
{subscriberTag.name}
</Tag>
);
return (
<div key={randomId}>
<Tooltip id={tooltipId} place="top">
{MailPoet.I18n.t('viewFilteredSubscribersMessage')}
</Tooltip>
<a
data-tip=""
data-for={tooltipId}
href={`admin.php?page=mailpoet-subscribers#/filter[tag=${subscriberTag.tag_id}]`}
>
{tag}
</a>
</div>
);
})}
{strings &&
strings.map((string) => (
{tags.map((item) => {
const tag = (
<Tag
key={string}
key={item.name}
dimension={dimension}
variant={variant || 'list'} // due to backward compatibility we use `list` as the default value
variant={variant || 'list'}
isInverted={isInverted}
>
{string}
{item.name}
</Tag>
))}
);
if (!item.target) {
return tag;
}
const randomId = Math.random().toString(36).substring(2, 15);
const tooltipId = `segment-tooltip-${randomId}`;
return (
<div key={randomId}>
{item.tooltip && (
<Tooltip id={tooltipId} place="top">
{MailPoet.I18n.t('viewFilteredSubscribersMessage')}
</Tooltip>
)}
<a data-tip="" data-for={tooltipId} href={item.target}>
{tag}
</a>
</div>
);
})}
</div>
);
}
export { Tags };
function StringTags({ children, strings, ...props }: StringTagsProps) {
const tags: TagData[] = strings.map((item) => ({
name: item,
}));
return (
<Tags tags={tags} {...props}>
{children}
</Tags>
);
}
function SegmentTags({ children, segments, ...props }: SegmentTagsProps) {
const tags: TagData[] = segments.map((segment) => ({
name: segment.name,
target: segment.id
? `admin.php?page=mailpoet-subscribers#/filter[segment=${segment.id}]`
: undefined,
tooltip: MailPoet.I18n.t('viewFilteredSubscribersMessage'),
}));
return (
<Tags tags={tags} {...props}>
{children}
</Tags>
);
}
function SubscriberTags({
children,
subscribers,
...props
}: SubscriberTagsProps) {
const tags: TagData[] = subscribers.map((item) => ({
name: item.name,
target: `admin.php?page=mailpoet-subscribers#/filter[tag=${item.tag_id}]`,
tooltip: MailPoet.I18n.t('viewFilteredSubscribersMessage'),
}));
return (
<Tags tags={tags} {...props}>
{children}
</Tags>
);
}
export { SegmentTags, StringTags, SubscriberTags };

View File

@ -5,36 +5,54 @@ import { MailPoetLogoMobile } from './mailpoet_logo_mobile';
type Props = {
onClick?: () => void;
withLink?: boolean;
};
export function MailPoetLogoResponsive({ onClick }: Props) {
export function MailPoetLogoResponsive({ onClick, withLink = true }: Props) {
const history = useHistory();
let logo;
let onLogoClick = onClick;
if (!onClick) {
onLogoClick = () => history.push('/');
}
return (
<a
role="button"
className="mailpoet-top-bar-logo"
title={t('topBarLogoTitle')}
onClick={onLogoClick}
tabIndex={0}
onKeyDown={(event) => {
if (
['keydown', 'keypress'].includes(event.type) &&
['Enter', ' '].includes(event.key)
) {
event.preventDefault();
onLogoClick();
}
}}
>
<div className="mailpoet-top-bar-logo-desktop">
<MailPoetLogo />
if (withLink) {
logo = (
<a
role="button"
className="mailpoet-top-bar-logo"
title={t('topBarLogoTitle')}
onClick={onLogoClick}
tabIndex={0}
onKeyDown={(event) => {
if (
['keydown', 'keypress'].includes(event.type) &&
['Enter', ' '].includes(event.key)
) {
event.preventDefault();
onLogoClick();
}
}}
>
<div className="mailpoet-top-bar-logo-desktop">
<MailPoetLogo />
</div>
<div className="mailpoet-top-bar-logo-mobile">
<MailPoetLogoMobile />
</div>
</a>
);
} else {
logo = (
<div className="mailpoet-top-bar-logo">
<div className="mailpoet-top-bar-logo-desktop">
<MailPoetLogo />
</div>
<div className="mailpoet-top-bar-logo-mobile">
<MailPoetLogoMobile />
</div>
</div>
<div className="mailpoet-top-bar-logo-mobile">
<MailPoetLogoMobile />
</div>
</a>
);
);
}
return logo;
}

View File

@ -10,16 +10,22 @@ type Props = {
children?: ReactNode;
hasNews?: boolean;
onBeamerClick?: () => void;
logoWithLink?: boolean;
};
export function TopBar({ children, hasNews, onBeamerClick }: Props) {
export function TopBar({
children,
hasNews,
onBeamerClick,
logoWithLink = true,
}: Props) {
const buttonClasses = classnames(
'mailpoet-top-bar-beamer',
hasNews ? 'mailpoet-top-bar-beamer-dot' : '',
);
return (
<div className="mailpoet-top-bar">
<MailPoetLogoResponsive />
<MailPoetLogoResponsive withLink={logoWithLink} />
<div className="mailpoet-top-bar-children">{children}</div>
<div className="mailpoet-flex-grow" />
{onBeamerClick && (

View File

@ -7,7 +7,7 @@ import { Button } from 'common';
import { Listing } from 'listing/listing.jsx';
import { MailPoet } from 'mailpoet';
import { plusIcon } from 'common/button/icon/plus';
import { Tags } from 'common/tag/tags';
import { SegmentTags } from 'common/tag/tags';
import { Toggle } from 'common/form/toggle/toggle';
import { withNpsPoll } from 'nps_poll.jsx';
import { FormsHeading, onAddNewForm } from './heading';
@ -248,13 +248,13 @@ class FormListComponent extends Component {
{actions}
</td>
<td className="column" data-colname={MailPoet.I18n.t('segments')}>
<Tags segments={segments} dimension="large">
<SegmentTags segments={segments} dimension="large">
{form.settings.segments_selected_by === 'user' && (
<span className="mailpoet-tags-prefix">
{MailPoet.I18n.t('userChoice')}
</span>
)}
</Tags>
</SegmentTags>
</td>
<td className="column" data-colname={MailPoet.I18n.t('type')}>
{placement}

View File

@ -124,6 +124,7 @@ interface Window {
mailpoet_current_date_time?: string;
mailpoet_urls: Record<string, string>;
recaptcha?: unknown;
grecaptcha?: any;
MailPoetForm?: {
ajax_url: string;
};
@ -142,4 +143,5 @@ interface Window {
name: string;
}[];
mailpoet_cdn_url: string;
mailpoet_main_page_slug: string;
}

View File

@ -65,6 +65,7 @@ export const MailPoet = {
window.mailpoet_deactivate_subscriber_after_inactive_days,
tags: window.mailpoet_tags,
cdnUrl: window.mailpoet_cdn_url,
mainPageSlug: window.mailpoet_main_page_slug,
} as const;
declare global {

View File

@ -15,7 +15,7 @@ const renderHeading = (newsletterType, newsletterOptions) => {
let buttons = null;
let onLogoClick = () => {
window.location = `admin.php?page=mailpoet-newsletters`;
window.location = `admin.php?page=${MailPoet.mainPageSlug}`;
};
if (newsletterType === 'automation') {
const automationId = newsletterOptions.automationId;

View File

@ -13,7 +13,7 @@ import {
import { Listing } from 'listing/listing.jsx';
import { MailPoet } from 'mailpoet';
import { NewsletterTypes } from 'newsletters/types';
import { ScheduledIcon, Tags, Toggle } from 'common';
import { ScheduledIcon, StringTags, Toggle } from 'common';
import { Statistics } from 'newsletters/listings/statistics.jsx';
const mailpoetTrackingEnabled = MailPoet.trackingConfig.emailTrackingEnabled;
@ -269,13 +269,13 @@ class ListingsComponent extends Component {
displayText = ReactStringReplace(
event.listingScheduleDisplayTextPlural,
'%s',
(match, i) => <Tags strings={metaOptionValues} key={i} />,
(match, i) => <StringTags strings={metaOptionValues} key={i} />,
);
} else {
displayText = ReactStringReplace(
event.listingScheduleDisplayText,
'%s',
(match, i) => <Tags strings={metaOptionValues} key={i} />,
(match, i) => <StringTags strings={metaOptionValues} key={i} />,
);
}

View File

@ -1,7 +1,7 @@
import { MailPoet } from 'mailpoet';
import { Heading } from 'common/typography/heading/heading';
import { Grid } from 'common/grid';
import { Button, Tags } from 'common';
import { Button, SegmentTags } from 'common';
import { NewsletterType } from './newsletter_type';
type Props = {
@ -28,7 +28,7 @@ export function NewsletterStatsInfo({ newsletter }: Props) {
{MailPoet.I18n.t('statsToSegments')}
</span>
{': '}
<Tags dimension="large" segments={newsletter.segments} />
<SegmentTags dimension="large" segments={newsletter.segments} />
</div>
)}
</div>

View File

@ -15,7 +15,7 @@ import {
monthDayValues,
nthWeekDayValues,
} from 'newsletters/scheduling/common.jsx';
import { Tags } from 'common/tag/tags';
import { SegmentTags } from 'common/tag/tags';
import { Toggle } from 'common/form/toggle/toggle';
import {
@ -227,7 +227,7 @@ class NewsletterListNotificationComponent extends Component {
const sendingToSegments = ReactStringReplace(
MailPoet.I18n.t('sendTo'),
'%1$s',
(match, i) => <Tags segments={newsletter.segments} key={i} />,
(match, i) => <SegmentTags segments={newsletter.segments} key={i} />,
);
// set sending frequency

View File

@ -11,7 +11,7 @@ import {
checkCronStatus,
checkMailerStatus,
} from 'newsletters/listings/utils.jsx';
import { Tags } from 'common/tag/tags';
import { SegmentTags } from 'common/tag/tags';
const mailpoetTrackingEnabled = MailPoet.trackingConfig.emailTrackingEnabled;
@ -147,7 +147,7 @@ const renderItem = (newsletter, actions, meta) => {
className="column mailpoet-hide-on-mobile"
data-colname={MailPoet.I18n.t('lists')}
>
<Tags segments={newsletter.segments} dimension="large" />
<SegmentTags segments={newsletter.segments} dimension="large" />
</td>
{mailpoetTrackingEnabled === true ? (
<td

View File

@ -5,7 +5,7 @@ import { Link, withRouter } from 'react-router-dom';
import ReactStringReplace from 'react-string-replace';
import { Toggle } from 'common/form/toggle/toggle';
import { Tags } from 'common/tag/tags';
import { SegmentTags } from 'common/tag/tags';
import { ScheduledIcon } from 'common/listings/newsletter_status';
import { Listing } from 'listing/listing.jsx';
import { MailPoet } from 'mailpoet';
@ -238,7 +238,7 @@ class NewsletterListReEngagementComponent extends Component {
const sendingToSegments = ReactStringReplace(
MailPoet.I18n.t('sendTo'),
'%1$s',
(match, i) => <Tags segments={newsletter.segments} key={i} />,
(match, i) => <SegmentTags segments={newsletter.segments} key={i} />,
);
let frequencyKey = 'reEngagementFrequencyMonth';

View File

@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import { confirmAlert } from 'common/confirm_alert.jsx';
import { Tags } from 'common/tag/tags';
import { SegmentTags } from 'common/tag/tags';
import { Listing } from 'listing/listing.jsx';
import { QueueStatus } from 'newsletters/listings/queue_status.jsx';
import { Statistics } from 'newsletters/listings/statistics.jsx';
@ -218,7 +218,7 @@ class NewsletterListStandardComponent extends Component {
className="column mailpoet-hide-on-mobile"
data-colname={MailPoet.I18n.t('lists')}
>
<Tags segments={newsletter.segments} dimension="large" />
<SegmentTags segments={newsletter.segments} dimension="large" />
</td>
{mailpoetTrackingEnabled === true ? (
<td

View File

@ -18,7 +18,7 @@ function successPageClosed() {
action: 'set',
data: { show_congratulate_after_first_newsletter: false },
}).always(() => {
window.location = window.mailpoet_main_page;
window.location = window.mailpoet_emails_page;
});
}
@ -60,7 +60,7 @@ function renderFail() {
return (
<Fail
failClicked={() => {
window.location = window.mailpoet_main_page;
window.location = window.mailpoet_emails_page;
}}
/>
);

View File

@ -53,13 +53,40 @@ jQuery(($) => {
Cookies.set(formCookieName, '1', { expires: 182, path: '/' });
}
function playCaptcha(e?: Event) {
e.preventDefault();
const audioSelector = '.mailpoet_captcha_player';
const audio = document.querySelector<HTMLAudioElement>(audioSelector);
if (!audio) {
return;
}
audio.play().catch(() => {});
}
function updateCaptcha(e?: Event) {
const captcha = $('img.mailpoet_captcha');
if (!captcha.length) return false;
const captchaSrc = captcha.attr('src');
const hashPos = captchaSrc.indexOf('#');
const newSrc = hashPos > 0 ? captchaSrc.substring(0, hashPos) : captchaSrc;
captcha.attr('src', `${newSrc}#${new Date().getTime()}`);
const imgSelector = 'img.mailpoet_captcha';
const audioSelector = '.mailpoet_captcha_player';
const captcha = document.querySelector(imgSelector);
const audioCaptcha =
document.querySelector<HTMLAudioElement>(audioSelector);
if (!captcha || !audioCaptcha) {
return false;
}
const audioCaptchaSource = audioCaptcha.querySelector('source');
let captchaSrc = captcha.getAttribute('src');
let hashPos = captchaSrc.indexOf('#');
let newSrc = hashPos > 0 ? captchaSrc.substring(0, hashPos) : captchaSrc;
captcha.setAttribute('src', `${newSrc}#${new Date().getTime()}`);
captchaSrc = audioCaptchaSource.getAttribute('src');
hashPos = captchaSrc.indexOf('&cachebust=');
newSrc = hashPos > 0 ? captchaSrc.substring(0, hashPos) : captchaSrc;
audioCaptchaSource.setAttribute(
'src',
`${newSrc}&cachebust=${new Date().getTime()}`,
);
audioCaptcha.load();
if (e) e.preventDefault();
return true;
}
@ -198,7 +225,7 @@ jQuery(($) => {
}
const widgetId = window.grecaptcha.render(container, params);
field.val(widgetId);
field.val(widgetId as string);
}
}
@ -448,6 +475,7 @@ jQuery(($) => {
});
$('.mailpoet_captcha_update').on('click', updateCaptcha);
$('.mailpoet_captcha_audio').on('click', playCaptcha);
// Manage subscription form
$('.mailpoet-manage-subscription').on('submit', (event) => {

View File

@ -1,5 +1,6 @@
import { useContext } from 'react';
import { MailPoet } from 'mailpoet';
import { Button } from 'common/button/button';
import { t } from 'common/functions';
import { GlobalContext } from 'context';
@ -24,7 +25,7 @@ export function Reinstall() {
{ scroll: true },
);
} else {
window.location.href = 'admin.php?page=mailpoet-newsletters';
window.location.href = `admin.php?page=${MailPoet.mainPageSlug}`;
}
}
};

View File

@ -1,5 +1,7 @@
import { useContext } from 'react';
import { MailPoet } from 'mailpoet';
import { STORE_NAME } from 'settings/store/store_name';
import { select } from '@wordpress/data';
import { useAction, useSelector, useSetting } from 'settings/store/hooks';
import { GlobalContext } from 'context';
import { Button } from 'common/button/button';
@ -8,6 +10,7 @@ import { Input } from 'common/form/input/input';
import { KeyActivationState, MssStatus } from 'settings/store/types';
import { Inputs, Label } from 'settings/components';
import { SetFromAddressModal } from 'common/set_from_address_modal';
import ReactStringReplace from 'react-string-replace';
import {
KeyMessages,
MssMessages,
@ -79,7 +82,39 @@ function Messages(
);
}
export function KeyActivation() {
type Props = {
subscribersCount: number;
};
const premiumTabDescription = ReactStringReplace(
t('premiumTabDescription'),
/\[link\](.*?)\[\/link\]/g,
(text) => (
<a
href="https://account.mailpoet.com/account?utm_source=plugin&utm_medium=settings&utm_campaign=activate-existing-plan&ref=settings-key-activation"
target="_blank"
rel="noopener noreferrer"
>
{text}
</a>
),
);
const premiumTabGetKey = ReactStringReplace(
t('premiumTabGetKey'),
/\[link\](.*?)\[\/link\]/g,
(text) => (
<a
href="https://account.mailpoet.com/account?utm_source=plugin&utm_medium=settings&utm_campaign=activate-existing-plan&ref=settings-key-activation"
target="_blank"
rel="noopener noreferrer"
>
{text}
</a>
),
);
export function KeyActivation({ subscribersCount }: Props) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { notices } = useContext<any>(GlobalContext);
const state = useSelector('getKeyActivationState')();
@ -123,7 +158,11 @@ export function KeyActivation() {
MailPoet.Modal.loading(true);
setState({ inProgress: true });
await verifyMssKey(state.key);
await sendCongratulatoryMssEmail();
const currentMssStatus =
select(STORE_NAME).getKeyActivationState().mssStatus;
if (currentMssStatus === MssStatus.VALID_MSS_ACTIVE) {
await sendCongratulatoryMssEmail();
}
await verifyPremiumKey(state.key);
setState({ inProgress: false });
MailPoet.Modal.loading(false);
@ -141,7 +180,29 @@ export function KeyActivation() {
<Label
htmlFor="mailpoet_premium_key"
title={t('premiumTabActivationKeyLabel')}
description={t('premiumTabDescription')}
description={
<>
{premiumTabDescription}
<br />
<br />
{premiumTabGetKey}
<br />
<br />
{ReactStringReplace(
t('premiumTabGetPlan'),
/\[link\](.*?)\[\/link\]/g,
(text) => (
<a
href={`https://account.mailpoet.com/?s=${subscribersCount}&utm_source=plugin&utm_medium=settings&utm_campaign=create-new-plan&ref=settings-key-activation`}
target="_blank"
rel="noopener noreferrer"
>
{text}
</a>
),
)}
</>
}
/>
<Inputs>
<Input

View File

@ -78,7 +78,7 @@ export function Settings() {
title={t('keyActivationTab')}
automationId="activation_settings_tab"
>
<KeyActivation />
<KeyActivation subscribersCount={window.mailpoet_subscribers_count} />
</Tab>
</RoutedTabs>
</>

View File

@ -9,7 +9,7 @@ import {
PremiumStatus,
} from 'settings/store/types';
import { updateKeyActivationState } from './key_activation';
import { setSettings, setSetting } from './settings';
import { setSetting, setSettings } from './settings';
import { getMssStatus } from '../make_default_state';
export function* verifyMssKey(key: string) {
@ -29,6 +29,11 @@ export function* verifyMssKey(key: string) {
mssMessage: res.data.message || null,
};
if (res.data.state === 'valid_underprivileged') {
fields.mssStatus = MssStatus.VALID_UNDERPRIVILEGED;
return updateKeyActivationState(fields);
}
const data = select(STORE_NAME).getSettings();
data.mta_group = 'mailpoet';
data.mta = { ...data.mta, method: 'MailPoet', mailpoet_api_key: key };

View File

@ -3,7 +3,7 @@ import jQuery from 'jquery';
import { Link, useLocation } from 'react-router-dom';
import PropTypes from 'prop-types';
import { Button, Tags } from 'common';
import { Button, SegmentTags, SubscriberTags } from 'common';
import { Listing } from 'listing/listing.jsx';
import { MailPoet } from 'mailpoet';
import { Modal } from 'common/modal/modal.tsx';
@ -439,11 +439,11 @@ function SubscriberList({ match }) {
{status}
</td>
<td className="column" data-colname={MailPoet.I18n.t('lists')}>
<Tags segments={subscribedSegments} dimension="large" />
<SegmentTags segments={subscribedSegments} dimension="large" />
</td>
<td className="column" data-colname={MailPoet.I18n.t('tags')}>
<Tags
subscriberTags={subscriber.tags}
<SubscriberTags
subscribers={subscriber.tags}
variant="wordpress"
isInverted
/>

View File

@ -4,19 +4,9 @@ import { WelcomeWizardStepLayoutBody } from './step_layout_body.jsx';
function WelcomeWizardStepLayout(props) {
return (
<>
<div className="mailpoet-wizard-logo">
<img
src={window.mailpoet_logo_url}
width="160"
height="50"
alt="MailPoet logo"
/>
</div>
<WelcomeWizardStepLayoutBody illustrationUrl={props.illustrationUrl}>
{props.children}
</WelcomeWizardStepLayoutBody>
</>
<WelcomeWizardStepLayoutBody illustrationUrl={props.illustrationUrl}>
{props.children}
</WelcomeWizardStepLayoutBody>
);
}

View File

@ -17,6 +17,7 @@ import {
} from './steps_numbers.jsx';
import { Steps } from '../common/steps/steps';
import { StepsContent } from '../common/steps/steps_content';
import { TopBar } from '../common/top_bar/top_bar';
function WelcomeWizardStepsController(props) {
const stepsCount = getStepsCount();
@ -101,7 +102,9 @@ function WelcomeWizardStepsController(props) {
return (
<>
<Steps count={stepsCount} current={step} />
<TopBar logoWithLink={false}>
<Steps count={stepsCount} current={step} />
</TopBar>
<StepsContent>
{stepName === 'WelcomeWizardSenderStep' ? (
<WelcomeWizardStepLayout

View File

@ -20,7 +20,7 @@
"ext-pdo_mysql": "*",
"ext-xml": "*",
"ext-zip": "*",
"codeception/codeception": "4.1.31",
"codeception/codeception": "4.2.2",
"codeception/module-asserts": "^1.3",
"codeception/module-cli": "^1.0",
"codeception/module-db": "^1.1",
@ -31,7 +31,7 @@
"consolidation/robo": "3.0.10",
"guzzlehttp/guzzle": "6.5.8",
"hoa/console": "^3.17",
"lucatume/wp-browser": "3.1.5",
"lucatume/wp-browser": "3.1.6",
"phpunit/phpunit": "8.5.25",
"totten/lurkerlite": "^1.3",
"vlucas/phpdotenv": "5.4.1",

42
mailpoet/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b59c2173fe3197f3e5227f4038218033",
"content-hash": "9af8d15a6fc384da198a0fa3c1fad408",
"packages": [
{
"name": "mtdowling/cron-expression",
@ -320,16 +320,16 @@
},
{
"name": "codeception/codeception",
"version": "4.1.31",
"version": "4.2.2",
"source": {
"type": "git",
"url": "https://github.com/Codeception/Codeception.git",
"reference": "15524571ae0686a7facc2eb1f40f600e5bbce9e5"
"reference": "b88014f3348c93f3df99dc6d0967b0dbfa804474"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/15524571ae0686a7facc2eb1f40f600e5bbce9e5",
"reference": "15524571ae0686a7facc2eb1f40f600e5bbce9e5",
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/b88014f3348c93f3df99dc6d0967b0dbfa804474",
"reference": "b88014f3348c93f3df99dc6d0967b0dbfa804474",
"shasum": ""
},
"require": {
@ -392,11 +392,11 @@
{
"name": "Michael Bodnarchuk",
"email": "davert@mail.ua",
"homepage": "http://codegyre.com"
"homepage": "https://codegyre.com"
}
],
"description": "BDD-style testing framework",
"homepage": "http://codeception.com/",
"homepage": "https://codeception.com/",
"keywords": [
"BDD",
"TDD",
@ -406,7 +406,7 @@
],
"support": {
"issues": "https://github.com/Codeception/Codeception/issues",
"source": "https://github.com/Codeception/Codeception/tree/4.1.31"
"source": "https://github.com/Codeception/Codeception/tree/4.2.2"
},
"funding": [
{
@ -414,7 +414,7 @@
"type": "open_collective"
}
],
"time": "2022-03-13T17:07:08+00:00"
"time": "2022-08-13T13:28:25+00:00"
},
{
"name": "codeception/lib-asserts",
@ -628,16 +628,16 @@
},
{
"name": "codeception/module-webdriver",
"version": "1.4.0",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/Codeception/module-webdriver.git",
"reference": "baa18b7bf70aa024012f967b5ce5021e1faa9151"
"reference": "e22ac7da756df659df6dd4fac2dff9c859e30131"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/module-webdriver/zipball/baa18b7bf70aa024012f967b5ce5021e1faa9151",
"reference": "baa18b7bf70aa024012f967b5ce5021e1faa9151",
"url": "https://api.github.com/repos/Codeception/module-webdriver/zipball/e22ac7da756df659df6dd4fac2dff9c859e30131",
"reference": "e22ac7da756df659df6dd4fac2dff9c859e30131",
"shasum": ""
},
"require": {
@ -678,9 +678,9 @@
],
"support": {
"issues": "https://github.com/Codeception/module-webdriver/issues",
"source": "https://github.com/Codeception/module-webdriver/tree/1.4.0"
"source": "https://github.com/Codeception/module-webdriver/tree/1.4.1"
},
"time": "2021-09-02T12:01:02+00:00"
"time": "2022-09-12T05:09:51+00:00"
},
{
"name": "codeception/phpunit-wrapper",
@ -3548,16 +3548,16 @@
},
{
"name": "lucatume/wp-browser",
"version": "3.1.5",
"version": "3.1.6",
"source": {
"type": "git",
"url": "https://github.com/lucatume/wp-browser.git",
"reference": "d797924151167eac745ea57768df0da4f9ed2502"
"reference": "5cefdab50d16f69447c48e5a8668d67d4892d6ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lucatume/wp-browser/zipball/d797924151167eac745ea57768df0da4f9ed2502",
"reference": "d797924151167eac745ea57768df0da4f9ed2502",
"url": "https://api.github.com/repos/lucatume/wp-browser/zipball/5cefdab50d16f69447c48e5a8668d67d4892d6ef",
"reference": "5cefdab50d16f69447c48e5a8668d67d4892d6ef",
"shasum": ""
},
"require": {
@ -3641,7 +3641,7 @@
],
"support": {
"issues": "https://github.com/lucatume/wp-browser/issues",
"source": "https://github.com/lucatume/wp-browser/tree/3.1.5"
"source": "https://github.com/lucatume/wp-browser/tree/3.1.6"
},
"funding": [
{
@ -3649,7 +3649,7 @@
"type": "github"
}
],
"time": "2022-03-16T08:39:22+00:00"
"time": "2022-04-28T06:45:08+00:00"
},
{
"name": "mck89/peast",

View File

@ -1,3 +1,3 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
// Silence is golden

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoetVendor;
use MailPoet\Util\pQuery\DomNode;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoetVendor\Idiorm;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoetVendor\Paris;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoetVendor\Sudzy;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoetVendor\Sudzy;
use MailPoetVendor\Paris\Model;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoetVendor\Sudzy;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoetVendor;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoetVendor\pQuery;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
/**
* @author Niels A.D.
* @author Todd Burry <todd@vanillaforums.com>

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
/**
* @author Niels A.D.
* @author Todd Burry <todd@vanillaforums.com>

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
/**
* @author Niels A.D.
* @author Todd Burry <todd@vanillaforums.com>

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
/**
* @author Niels A.D.
* @author Todd Burry <todd@vanillaforums.com>

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
/**
* @author Niels A.D.
* @author Todd Burry <todd@vanillaforums.com>

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
/**
* @author Niels A.D.
* @author Todd Burry <todd@vanillaforums.com>

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
/**
* @author Niels A.D.
* @author Todd Burry <todd@vanillaforums.com>

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
/**
* @author Niels A.D.
* @author Todd Burry <todd@vanillaforums.com>

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoetVendor\pQuery;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\API;

View File

@ -1,11 +1,11 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\API\JSON;
use MailPoet\Config\AccessControl;
use MailPoet\Exception;
use MailPoet\Settings\SettingsController;
use MailPoet\Subscription\Captcha;
use MailPoet\Subscription\Captcha\CaptchaConstants;
use MailPoet\Tracy\ApiPanel\ApiPanel;
use MailPoet\Tracy\DIPanel\DIPanel;
use MailPoet\Util\Helpers;
@ -100,7 +100,7 @@ class API {
}
$ignoreToken = (
$this->settings->get('captcha.type') != Captcha::TYPE_DISABLED &&
$this->settings->get('captcha.type') != CaptchaConstants::TYPE_DISABLED &&
$this->requestEndpoint === 'subscribers' &&
$this->requestMethod === 'subscribe'
);

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\API\JSON;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\API\JSON;

View File

@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\API\JSON;

Some files were not shown because too many files have changed in this diff Show More