You will receive an email to confirm your subscription. Please click the link in the email to confirm
'),
+ 'description' => s('Text to display when subscription with an AJAX request was successful'),
+ 'type' => 'textarea',
+ 'allowempty' => true,
+ 'category' => 'subscription',
+ ),
+ 'subscribesubject' => array(
+ 'value' => s('Request for confirmation'),
+ 'description' => s('Subject of the message subscribers receive when they sign up'),
+ 'infoicon' => true,
+ 'type' => 'text',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ 'subscribemessage' => array(
+ 'value' =>
+ ' You have been subscribed to the following newsletters:
+
+[LISTS]
+
+
+Please click the following link to confirm it\'s really you:
+
+[CONFIRMATIONURL]
+
+
+In order to provide you with this service we\'ll need to
+
+Transfer your contact information to [DOMAIN]
+Store your contact information in your [DOMAIN] account
+Send you emails from [DOMAIN]
+Track your interactions with these emails for marketing purposes
+
+If this is not correct, or you do not agree, simply take no action and delete this message.'
+ ,
+ 'description' => s('Message subscribers receive when they sign up'),
+ 'type' => 'textarea',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ 'unsubscribesubject' => array(
+ 'value' => s('Goodbye from our Newsletter'),
+ 'description' => s('Subject of the message subscribers receive when they unsubscribe'),
+ 'type' => 'text',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ 'unsubscribemessage' => array(
+ 'value' =>
+ 'Goodbye from our Newsletter, sorry to see you go.
+
+You have been unsubscribed from our newsletters.
+
+This is the last email you will receive from us. Our newsletter system, phpList,
+will refuse to send you any further messages, without manual intervention by our administrator.
+
+If there is an error in this information, you can re-subscribe:
+please go to [SUBSCRIBEURL] and follow the steps.
+
+Thank you'
+ ,
+ 'description' => s('Message subscribers receive when they unsubscribe'),
+ 'type' => 'textarea',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ 'confirmationsubject' => array(
+ 'value' => s('Welcome to our Newsletter'),
+ 'description' => s('Subject of the message subscribers receive after confirming their email address'),
+ 'type' => 'text',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ 'confirmationmessage' => array(
+ 'value' =>
+ 'Welcome to our Newsletter
+
+Please keep this message for later reference.
+
+Your email address has been added to the following newsletter(s):
+[LISTS]
+
+To update your details and preferences please go to [PREFERENCESURL].
+If you do not want to receive any more messages, please go to [UNSUBSCRIBEURL].
+
+Thank you'
+ ,
+ 'description' => s('Message subscribers receive after confirming their email address'),
+ 'type' => 'textarea',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ 'updatesubject' => array(
+ 'value' => s('[notify] Change of List-Membership details'),
+ 'description' => s('Subject of the message subscribers receive when they have changed their details'),
+ 'type' => 'text',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ // the message that is sent when a user updates their information.
+ // just to make sure they approve of it.
+ // confirmationinfo is replaced by one of the options below
+ // userdata is replaced by the information in the database
+ 'updatemessage' => array(
+ 'value' =>
+ 'This message is to inform you of a change of your details on our newsletter database
+
+You are currently member of the following newsletters:
+
+[LISTS]
+
+[CONFIRMATIONINFO]
+
+The information on our system for you is as follows:
+
+[USERDATA]
+
+If this is not correct, please update your information at the following location:
+
+[PREFERENCESURL]
+
+Thank you'
+ ,
+ 'description' => s('Message subscribers receive when they have changed their details'),
+ 'type' => 'textarea',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ // this is the text that is placed in the [!-- confirmation --] location of the above
+ // message, in case the email is sent to their new email address and they have changed
+ // their email address
+ 'emailchanged_text' => array(
+ 'value' => '
+ When updating your details, your email address has changed.
+ Please confirm your new email address by visiting this webpage:
+
+ [CONFIRMATIONURL]
+
+ ',
+ 'description' => s('Part of the message that is sent to their new email address when subscribers change their information, and the email address has changed'),
+ 'type' => 'textarea',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ // this is the text that is placed in the [!-- confirmation --] location of the above
+ // message, in case the email is sent to their old email address and they have changed
+ // their email address
+ 'emailchanged_text_oldaddress' => array(
+ 'value' =>
+ 'Please Note: when updating your details, your email address has changed.
+
+A message has been sent to your new email address with a URL
+to confirm this change. Please visit this website to activate
+your membership.'
+ ,
+ 'description' => s('Part of the message that is sent to their old email address when subscribers change their information, and the email address has changed'),
+ 'type' => 'textarea',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ 'personallocation_subject' => array(
+ 'value' => s('Your personal location'),
+ 'description' => s('Subject of message when subscribers request their personal location'),
+ 'type' => 'text',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ 'messagefooter' => array(
+ 'value' => '--
+
+
+
+ ',
+ 'description' => s('Default footer for sending a campaign'),
+ 'type' => 'textarea',
+ 'allowempty' => 0,
+ 'category' => 'campaign',
+ ),
+ 'forwardfooter' => array(
+ 'value' => '
+
+ ',
+ 'description' => s('Footer used when a message has been forwarded'),
+ 'type' => 'textarea',
+ 'allowempty' => 0,
+ 'category' => 'campaign',
+ ),
+ 'personallocation_message' => array(
+ 'value' =>
+
+ 'You have requested your personal location to update your details from our website.
+The location is below. Please make sure that you use the full line as mentioned below.
+Sometimes email programmes can wrap the line into multiple lines.
+
+Your personal location is:
+[PREFERENCESURL]
+
+Thank you.'
+ ,
+ 'description' => s('Message to send when they request their personal location'),
+ 'type' => 'textarea',
+ 'allowempty' => 0,
+ 'category' => 'transactional',
+ ),
+ 'remoteurl_append' => array(
+ 'value' => '',
+ 'description' => s('String to always append to remote URL when using send-a-webpage'),
+ 'type' => 'text',
+ 'allowempty' => true,
+ 'category' => 'campaign',
+ ),
+ 'wordwrap' => array(
+ 'value' => '75',
+ 'description' => s('Width for Wordwrap of Text messages'),
+ 'type' => 'text',
+ 'allowempty' => true,
+ 'category' => 'campaign',
+ ),
+ 'html_email_style' => array(
+ 'value' => '',
+ 'description' => s('CSS for HTML messages without a template'),
+ 'type' => 'textarea',
+ 'allowempty' => true,
+ 'category' => 'campaign',
+ ),
+ 'alwayssendtextto' => array(
+ 'value' => '',
+ 'description' => s('Domains that only accept text emails, one per line'),
+ 'type' => 'textarea',
+ 'allowempty' => true,
+ 'category' => 'campaign',
+ ),
+ 'tld_last_sync' => array(
+ 'value' => '0',
+ 'description' => s('last time TLDs were fetched'),
+ 'type' => 'text',
+ 'allowempty' => true,
+ 'category' => 'system',
+ 'hidden' => true,
+ ),
+ 'internet_tlds' => array(
+ 'value' => '',
+ 'description' => s('Top level domains'),
+ 'type' => 'textarea',
+ 'allowempty' => true,
+ 'category' => 'system',
+ 'hidden' => true,
+ ),
+ 'pageheader' => array(
+ 'value' => '
If you did not request this password reset, please ignore this email.
-
Thank you.
]]>
-
-
+
+ <p>Password Reset Request!</p>
+<p>Hello! A password reset has been requested for your account.</p>
+<p>Please use the following token to reset your password:</p>
+<p><a href="%confirmation_link%">Reset Password</a></p>
+<p>If you did not request this password reset, please ignore this email.</p>
+<p>Thank you.</p>
+ Password Reset Request!
Hello! A password reset has been requested for your account.
Please use the following token to reset your password:
If you did not request this password reset, please ignore this email.
Thank you.
- ]]>
-
-
-
-
- Please confirm your subscription
- Please confirm your subscription
-
-
-
- Thank you for subscribing!
+
+ ]]>
+
+
+ Request for confirmation
+ Request for confirmation
+
+
+ Thank you for subscribing!
Please confirm your subscription by clicking the link below:
@@ -92,7 +85,7 @@
If you did not request this subscription, please ignore this email.
- Thank you for subscribing!
+ Thank you for subscribing!
Please confirm your subscription by clicking the link below:
@@ -100,351 +93,597 @@
If you did not request this subscription, please ignore this email.
-
-
-
- Thank you for subscribing!
-
Please confirm your subscription by clicking the link below:
If you did not request this subscription, please ignore this email.
]]>
+
+
+ <p>Thank you for subscribing!</p>
+<p>Please confirm your subscription by clicking the link below:</p>
+<p><a href="%confirmation_link%">Confirm Subscription</a></p>
+<p>If you did not request this subscription, please ignore this email.</p>
- Thank you for subscribing!
+ Thank you for subscribing!
Please confirm your subscription by clicking the link below:
If you did not request this subscription, please ignore this email.
]]>
-
-
-
-
-
- PHP IMAP extension not available. Falling back to Webklex IMAP.
- PHP IMAP extension not available. Falling back to Webklex IMAP.
-
-
-
- Could not apply force lock. Aborting.
- Could not apply force lock. Aborting.
-
-
-
- Another bounce processing is already running. Aborting.
- Another bounce processing is already running. Aborting.
-
-
-
- Queue is already being processed by another instance.
- Queue is already being processed by another instance.
-
-
-
- The system is in maintenance mode, stopping. Try again later.
- The system is in maintenance mode, stopping. Try again later.
-
-
-
- Bounce processing completed.
- Bounce processing completed.
-
-
-
- Recipient email address not provided
- Recipient email address not provided
-
-
-
- Invalid email address: %email%
- Invalid email address: %email%
-
-
-
- Sending test email synchronously to %email%
- Sending test email synchronously to %email%
-
-
-
- Queuing test email for %email%
- Queuing test email for %email%
-
-
-
- Test email sent successfully!
- Test email sent successfully!
-
-
-
- Test email queued successfully! It will be sent asynchronously.
- Test email queued successfully! It will be sent asynchronously.
-
-
-
- Failed to send test email: %error%
- Failed to send test email: %error%
-
-
-
- Email address auto blacklisted by bounce rule %rule_id%
- Email address auto blacklisted by bounce rule %rule_id%
-
-
-
- Auto Unsubscribed
- Auto Unsubscribed
-
-
-
- User auto unsubscribed for bounce rule %rule_id%
- User auto unsubscribed for bounce rule %rule_id%
-
-
-
- email auto unsubscribed for bounce rule %rule_id%
- email auto unsubscribed for bounce rule %rule_id%
-
-
-
- Subscriber auto blacklisted by bounce rule %rule_id%
- Subscriber auto blacklisted by bounce rule %rule_id%
-
-
-
- User auto unsubscribed for bounce rule %%rule_id%
- User auto unsubscribed for bounce rule %%rule_id%
-
-
-
- Auto confirmed
- Auto confirmed
-
-
-
- Auto unconfirmed
- Auto unconfirmed
-
-
-
- Subscriber auto confirmed for bounce rule %rule_id%
- Subscriber auto confirmed for bounce rule %rule_id%
-
-
-
- Requeued campaign; next embargo at %time%
- Requeued campaign; next embargo at %time%
-
-
-
- Subscriber auto unconfirmed for bounce rule %rule_id%
- Subscriber auto unconfirmed for bounce rule %rule_id%
-
-
-
- Running in test mode, not deleting messages from mailbox
- Running in test mode, not deleting messages from mailbox
-
-
-
- Processed messages will be deleted from the mailbox
- Processed messages will be deleted from the mailbox
-
-
-
- Processing bounces based on active bounce rules
- Processing bounces based on active bounce rules
-
-
-
- No active rules
- No active rules
-
-
-
- Processed %processed% out of %total% bounces for advanced bounce rules
- Processed %processed% out of %total% bounces for advanced bounce rules
-
-
-
- %processed% bounces processed by advanced processing
- %processed% bounces processed by advanced processing
-
-
- %not_processed% bounces were not matched by advanced processing rules
- %not_processed% bounces were not matched by advanced processing rules
-
-
-
- Opening mbox %file%
- Opening mbox %file%
-
-
- Connecting to %mailbox%
- Connecting to %mailbox%
-
-
- Please do not interrupt this process
- Please do not interrupt this process
-
-
- mbox file path must be provided with --mailbox.
- mbox file path must be provided with --mailbox.
-
-
-
- Invalid email, marking unconfirmed: %email%
- Invalid email, marking unconfirmed: %email%
-
-
- Failed to send to: %email%
- Failed to send to: %email%
-
-
-
- Reprocessing unidentified bounces
- Reprocessing unidentified bounces
-
-
- %total% bounces to reprocess
- %total% bounces to reprocess
-
-
- %count% out of %total% processed
- %count% out of %total% processed
-
-
- %reparsed% bounces were re-processed and %reidentified% bounces were re-identified
- %reparsed% bounces were re-processed and %reidentified% bounces were re-identified
-
-
-
- Identifying consecutive bounces
- Identifying consecutive bounces
-
-
- Nothing to do
- Nothing to do
-
-
- Processed %processed% out of %total% subscribers
- Processed %processed% out of %total% subscribers
-
-
- Total of %total% subscribers processed
- Total of %total% subscribers processed
-
-
- Subscriber auto unconfirmed for %count% consecutive bounces
- Subscriber auto unconfirmed for %count% consecutive bounces
-
-
- %count% consecutive bounces, threshold reached
- %count% consecutive bounces, threshold reached
-
-
-
- Reached max processing time; stopping cleanly.
- Reached max processing time; stopping cleanly.
-
-
-
- Giving a UUID to %count% subscribers, this may take a while
- Giving a UUID to %count% subscribers, this may take a while
-
-
- Giving a UUID to %count% campaigns
- Giving a UUID to %count% campaigns
-
-
-
- Batch limit reached, sleeping %sleep%s to respect MAILQUEUE_BATCH_PERIOD
- Batch limit reached, sleeping %sleep%s to respect MAILQUEUE_BATCH_PERIOD
-
-
-
- Value must be an array of image URLs.
- Value must be an array of image URLs.
-
-
- Image "%url%" is not a full URL.
- Image "%url%" is not a full URL.
-
-
- Image "%url%" does not exist (HTTP %code%)
- Image "%url%" does not exist (HTTP %code%)
-
-
- Image "%url%" could not be validated: %message%
- Image "%url%" could not be validated: %message%
-
-
-
- Not full URLs: %urls%
- Not full URLs: %urls%
-
-
-
-
-
- Subscriber list not found.
- Subscriber list not found.
-
-
-
- Subscriber does not exists.
- Subscriber does not exists.
-
-
-
- Subscription not found for this subscriber and list.
- Subscription not found for this subscriber and list.
-
-
- Attribute definition already exists
- Attribute definition already exists
-
-
- Another attribute with this name already exists.
- Another attribute with this name already exists.
-
-
-
- Subscribe page not found
- Subscribe page not found
-
-
- Value is required
- Value is required
-
-
- Subscriber not found
- Subscriber not found
-
-
- Unexpected error: %error%
- Unexpected error: %error%
-
-
- Added to blacklist for reason %reason%
- Added to blacklist for reason %reason%
-
-
- Could not read the uploaded file.
- Could not read the uploaded file.
-
-
- Error processing %email%: %error%
- Error processing %email%: %error%
-
-
- General import error: %error%
- General import error: %error%
-
-
- Value must be a string.
- Value must be a string.
-
-
- Invalid attribute type: "%type%". Valid types are: %valid_types%
- Invalid attribute type: "%type%". Valid types are: %valid_types%
-
-
-
-
+
If you did not request this subscription, please ignore this email.
+ ]]>
+
+
+ PHP IMAP extension not available. Falling back to Webklex IMAP.
+ PHP IMAP extension not available. Falling back to Webklex IMAP.
+
+
+ Could not apply force lock. Aborting.
+ Could not apply force lock. Aborting.
+
+
+ Another bounce processing is already running. Aborting.
+ Another bounce processing is already running. Aborting.
+
+
+ Queue is already being processed by another instance.
+ Queue is already being processed by another instance.
+
+
+ The system is in maintenance mode, stopping. Try again later.
+ The system is in maintenance mode, stopping. Try again later.
+
+
+ Bounce processing completed.
+ Bounce processing completed.
+
+
+ Recipient email address not provided
+ Recipient email address not provided
+
+
+ Invalid email address: %email%
+ Invalid email address: %email%
+
+
+ Sending test email synchronously to %email%
+ Sending test email synchronously to %email%
+
+
+ Queuing test email for %email%
+ Queuing test email for %email%
+
+
+ Test email sent successfully!
+ Test email sent successfully!
+
+
+ Test email queued successfully! It will be sent asynchronously.
+ Test email queued successfully! It will be sent asynchronously.
+
+
+ Failed to send test email: %error%
+ Failed to send test email: %error%
+
+
+ Email address auto blacklisted by bounce rule %rule_id%
+ Email address auto blacklisted by bounce rule %rule_id%
+
+
+ Auto Unsubscribed
+ Auto Unsubscribed
+
+
+ User auto unsubscribed for bounce rule %rule_id%
+ User auto unsubscribed for bounce rule %rule_id%
+
+
+ email auto unsubscribed for bounce rule %rule_id%
+ email auto unsubscribed for bounce rule %rule_id%
+
+
+ Subscriber auto blacklisted by bounce rule %rule_id%
+ Subscriber auto blacklisted by bounce rule %rule_id%
+
+
+ User auto unsubscribed for bounce rule %%rule_id%
+ User auto unsubscribed for bounce rule %%rule_id%
+
+
+ Auto confirmed
+ Auto confirmed
+
+
+ Auto unconfirmed
+ Auto unconfirmed
+
+
+ Subscriber auto confirmed for bounce rule %rule_id%
+ Subscriber auto confirmed for bounce rule %rule_id%
+
+
+ Requeued campaign; next embargo at %time%
+ Requeued campaign; next embargo at %time%
+
+
+ Subscriber auto unconfirmed for bounce rule %rule_id%
+ Subscriber auto unconfirmed for bounce rule %rule_id%
+
+
+ Running in test mode, not deleting messages from mailbox
+ Running in test mode, not deleting messages from mailbox
+
+
+ Processed messages will be deleted from the mailbox
+ Processed messages will be deleted from the mailbox
+
+
+ Processing bounces based on active bounce rules
+ Processing bounces based on active bounce rules
+
+
+ No active rules
+ No active rules
+
+
+ Processed %processed% out of %total% bounces for advanced bounce rules
+ Processed %processed% out of %total% bounces for advanced bounce rules
+
+
+ %processed% bounces processed by advanced processing
+ %processed% bounces processed by advanced processing
+
+
+ %not_processed% bounces were not matched by advanced processing rules
+ %not_processed% bounces were not matched by advanced processing rules
+
+
+ Opening mbox %file%
+ Opening mbox %file%
+
+
+ Connecting to %mailbox%
+ Connecting to %mailbox%
+
+
+ Please do not interrupt this process
+ Please do not interrupt this process
+
+
+ mbox file path must be provided with --mailbox.
+ mbox file path must be provided with --mailbox.
+
+
+ Invalid email, marking unconfirmed: %email%
+ Invalid email, marking unconfirmed: %email%
+
+
+ Failed to send to: %email%
+ Failed to send to: %email%
+
+
+ Reprocessing unidentified bounces
+ Reprocessing unidentified bounces
+
+
+ %total% bounces to reprocess
+ %total% bounces to reprocess
+
+
+ %count% out of %total% processed
+ %count% out of %total% processed
+
+
+ %reparsed% bounces were re-processed and %reidentified% bounces were re-identified
+ %reparsed% bounces were re-processed and %reidentified% bounces were re-identified
+
+
+ Identifying consecutive bounces
+ Identifying consecutive bounces
+
+
+ Nothing to do
+ Nothing to do
+
+
+ Processed %processed% out of %total% subscribers
+ Processed %processed% out of %total% subscribers
+
+
+ Total of %total% subscribers processed
+ Total of %total% subscribers processed
+
+
+ Subscriber auto unconfirmed for %count% consecutive bounces
+ Subscriber auto unconfirmed for %count% consecutive bounces
+
+
+ %count% consecutive bounces, threshold reached
+ %count% consecutive bounces, threshold reached
+
+
+ Reached max processing time; stopping cleanly.
+ Reached max processing time; stopping cleanly.
+
+
+ Giving a UUID to %count% subscribers, this may take a while
+ Giving a UUID to %count% subscribers, this may take a while
+
+
+ Giving a UUID to %count% campaigns
+ Giving a UUID to %count% campaigns
+
+
+ Batch limit reached, sleeping %sleep%s to respect MAILQUEUE_BATCH_PERIOD
+ Batch limit reached, sleeping %sleep%s to respect MAILQUEUE_BATCH_PERIOD
+
+
+ Value must be an array of image URLs.
+ Value must be an array of image URLs.
+
+
+ Image "%url%" is not a full URL.
+ Image "%url%" is not a full URL.
+
+
+ Image "%url%" does not exist (HTTP %code%)
+ Image "%url%" does not exist (HTTP %code%)
+
+
+ Image "%url%" could not be validated: %message%
+ Image "%url%" could not be validated: %message%
+
+
+ Not full URLs: %urls%
+ Not full URLs: %urls%
+
+
+ Subscriber list not found.
+ Subscriber list not found.
+
+
+ Subscriber does not exists.
+ Subscriber does not exists.
+
+
+ Subscription not found for this subscriber and list.
+ Subscription not found for this subscriber and list.
+
+
+ Attribute definition already exists
+ Attribute definition already exists
+
+
+ Another attribute with this name already exists.
+ Another attribute with this name already exists.
+
+
+ Subscribe page not found
+ Subscribe page not found
+
+
+ Value is required
+ Value is required
+
+
+ Subscriber not found
+ Subscriber not found
+
+
+ Unexpected error: %error%
+ Unexpected error: %error%
+
+
+ Added to blacklist for reason %reason%
+ Added to blacklist for reason %reason%
+
+
+ Could not read the uploaded file.
+ Could not read the uploaded file.
+
+
+ Error processing %email%: %error%
+ Error processing %email%: %error%
+
+
+ General import error: %error%
+ General import error: %error%
+
+
+ Value must be a string.
+ Value must be a string.
+
+
+ Invalid attribute type: "%type%". Valid types are: %valid_types%
+ Invalid attribute type: "%type%". Valid types are: %valid_types%
+
+
+ Thank you for subscribing!
+
+Please confirm your subscription by clicking the link below:
+
+%confirmation_link%
+
+If you did not request this subscription, please ignore this email.
+ __Thank you for subscribing!
+
+Please confirm your subscription by clicking the link below:
+
+%confirmation_link%
+
+If you did not request this subscription, please ignore this email.
+
+
+ <p>Thank you for subscribing!</p><p>Please confirm your subscription by clicking the link below:</p><p><a href="%confirmation_link%">Confirm Subscription</a></p><p>If you did not request this subscription, please ignore this email.</p>
+ Thank you for subscribing!
Please confirm your subscription by clicking the link below:
If you did not request this subscription, please ignore this email.
]]>
+
+
+ Hello,
+
+A password reset has been requested for your account.
+Please use the following token to reset your password:
+
+%token%
+
+If you did not request this password reset, please ignore this email.
+
+Thank you.
+ __Hello,
+
+A password reset has been requested for your account.
+Please use the following token to reset your password:
+
+%token%
+
+If you did not request this password reset, please ignore this email.
+
+Thank you.
+
+
+ <p>Password Reset Request!</p><p>Hello! A password reset has been requested for your account.</p><p>Please use the following token to reset your password:</p><p><a href="%confirmation_link%">Reset Password</a></p><p>If you did not request this password reset, please ignore this email.</p><p>Thank you.</p>
+ Password Reset Request!
Hello! A password reset has been requested for your account.
Please use the following token to reset your password:
If you did not request this password reset, please ignore this email.
Thank you.
]]>
+
+
+ Person in charge of this system (one email address)
+ __Person in charge of this system (one email address)
+
+
+ Name of the organisation
+ __Name of the organisation
+
+
+ Logo of the organisation
+ __Logo of the organisation
+
+
+ Date format
+ __Date format
+
+
+ Show notification for Release Candidates
+ __Show notification for Release Candidates
+
+
+ Secret for remote processing
+ __Secret for remote processing
+
+
+ Notify admin on login from new location
+ __Notify admin on login from new location
+
+
+ List of email addresses to CC in system messages (separate by commas)
+ __List of email addresses to CC in system messages (separate by commas)
+
+
+ Default for 'From:' in a campaign
+ __Default for 'From:' in a campaign
+
+
+ Default for 'address to alert when sending starts'
+ __Default for 'address to alert when sending starts'
+
+
+ Default for 'address to alert when sending finishes'
+ __Default for 'address to alert when sending finishes'
+
+
+ Always add analytics tracking code to campaigns
+ __Always add analytics tracking code to campaigns
+
+
+ Analytics tracking code to add to campaign URLs
+ __Analytics tracking code to add to campaign URLs
+
+
+ Who gets the reports (email address, separate multiple emails with a comma)
+ __Who gets the reports (email address, separate multiple emails with a comma)
+
+
+ From email address for system messages
+ __From email address for system messages
+
+
+ Webmaster
+ __Webmaster
+
+
+ Name for system messages
+ __Name for system messages
+
+
+ Reply-to email address for system messages
+ __Reply-to email address for system messages
+
+
+ If there is only one visible list, should it be hidden in the page and automatically subscribe users who sign up
+ __If there is only one visible list, should it be hidden in the page and automatically subscribe users who sign up
+
+
+ Categories for lists. Separate with commas.
+ __Categories for lists. Separate with commas.
+
+
+ Display list categories on subscribe page
+ __Display list categories on subscribe page
+
+
+ Width of a textline field (numerical)
+ __Width of a textline field (numerical)
+
+
+ Dimensions of a textarea field (rows,columns)
+ __Dimensions of a textarea field (rows,columns)
+
+
+ Send notifications about subscribe, update and unsubscribe
+ __Send notifications about subscribe, update and unsubscribe
+
+
+ The default subscribe page when there are multiple
+ __The default subscribe page when there are multiple
+
+
+ The default HTML template to use when sending a message
+ __The default HTML template to use when sending a message
+
+
+ The HTML wrapper template for system messages
+ __The HTML wrapper template for system messages
+
+
+ URL where subscribers can sign up
+ __URL where subscribers can sign up
+
+
+ URL where subscribers can unsubscribe
+ __URL where subscribers can unsubscribe
+
+
+ URL where unknown users can unsubscribe (do-not-send-list)
+ __URL where unknown users can unsubscribe (do-not-send-list)
+
+
+ URL where subscribers have to confirm their subscription
+ __URL where subscribers have to confirm their subscription
+
+
+ URL where subscribers can update their details
+ __URL where subscribers can update their details
+
+
+ URL for forwarding messages
+ __URL for forwarding messages
+
+
+ URL for downloading vcf card
+ __URL for downloading vcf card
+
+
+ <h3>Thanks, you have been added to our newsletter</h3><p>You will receive an email to confirm your subscription. Please click the link in the email to confirm</p>
+ Thanks, you have been added to our newsletter
You will receive an email to confirm your subscription. Please click the link in the email to confirm
]]>
+
+
+ Text to display when subscription with an AJAX request was successful
+ __Text to display when subscription with an AJAX request was successful
+
+
+ Subject of the message subscribers receive when they sign up
+ __Subject of the message subscribers receive when they sign up
+
+
+ Message subscribers receive when they sign up
+ __Message subscribers receive when they sign up
+
+
+ Goodbye from our Newsletter
+ __Goodbye from our Newsletter
+
+
+ Subject of the message subscribers receive when they unsubscribe
+ __Subject of the message subscribers receive when they unsubscribe
+
+
+ Message subscribers receive when they unsubscribe
+ __Message subscribers receive when they unsubscribe
+
+
+ Welcome to our Newsletter
+ __Welcome to our Newsletter
+
+
+ Subject of the message subscribers receive after confirming their email address
+ __Subject of the message subscribers receive after confirming their email address
+
+
+ Message subscribers receive after confirming their email address
+ __Message subscribers receive after confirming their email address
+
+
+ [notify] Change of List-Membership details
+ __[notify] Change of List-Membership details
+
+
+ Subject of the message subscribers receive when they have changed their details
+ __Subject of the message subscribers receive when they have changed their details
+
+
+ Message subscribers receive when they have changed their details
+ __Message subscribers receive when they have changed their details
+
+
+ Part of the message that is sent to their new email address when subscribers change their information, and the email address has changed
+ __Part of the message that is sent to their new email address when subscribers change their information, and the email address has changed
+
+
+ Part of the message that is sent to their old email address when subscribers change their information, and the email address has changed
+ __Part of the message that is sent to their old email address when subscribers change their information, and the email address has changed
+
+
+ Your personal location
+ __Your personal location
+
+
+ Subject of message when subscribers request their personal location
+ __Subject of message when subscribers request their personal location
+
+
+ Default footer for sending a campaign
+ __Default footer for sending a campaign
+
+
+ Footer used when a message has been forwarded
+ __Footer used when a message has been forwarded
+
+
+ Message to send when they request their personal location
+ __Message to send when they request their personal location
+
+
+ String to always append to remote URL when using send-a-webpage
+ __String to always append to remote URL when using send-a-webpage
+
+
+ Width for Wordwrap of Text messages
+ __Width for Wordwrap of Text messages
+
+
+ CSS for HTML messages without a template
+ __CSS for HTML messages without a template
+
+
+ Domains that only accept text emails, one per line
+ __Domains that only accept text emails, one per line
+
+
+ last time TLDs were fetched
+ __last time TLDs were fetched
+
+
+ Top level domains
+ __Top level domains
+
+
+ Header of public pages.
+ __Header of public pages.
+
+
+ Footer of public pages
+ __Footer of public pages
+
+
+
diff --git a/resources/translations/security.en.xlf b/resources/translations/security.en.xlf
new file mode 100644
index 00000000..d053cd60
--- /dev/null
+++ b/resources/translations/security.en.xlf
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+ An authentication exception occurred.
+ An authentication exception occurred.
+
+
+ Authentication credentials could not be found.
+ Authentication credentials could not be found.
+
+
+ Authentication request could not be processed due to a system problem.
+ Authentication request could not be processed due to a system problem.
+
+
+ Invalid credentials.
+ Invalid credentials.
+
+
+ Cookie has already been used by someone else.
+ Cookie has already been used by someone else.
+
+
+ Not privileged to request the resource.
+ Not privileged to request the resource.
+
+
+ Invalid CSRF token.
+ Invalid CSRF token.
+
+
+ No authentication provider found to support the authentication token.
+ No authentication provider found to support the authentication token.
+
+
+ No session available, it either timed out or cookies are not enabled.
+ No session available, it either timed out or cookies are not enabled.
+
+
+ No token could be found.
+ No token could be found.
+
+
+ Username could not be found.
+ Username could not be found.
+
+
+ Account has expired.
+ Account has expired.
+
+
+ Credentials have expired.
+ Credentials have expired.
+
+
+ Account is disabled.
+ Account is disabled.
+
+
+ Account is locked.
+ Account is locked.
+
+
+ Too many failed login attempts, please try again later.
+ Too many failed login attempts, please try again later.
+
+
+ Invalid or expired login link.
+ Invalid or expired login link.
+
+
+ Too many failed login attempts, please try again in %minutes% minute.
+ Too many failed login attempts, please try again in %minutes% minute.
+
+
+ Too many failed login attempts, please try again in %minutes% minutes.
+ Too many failed login attempts, please try again in %minutes% minutes.
+
+
+
+
diff --git a/resources/translations/validators.en.xlf b/resources/translations/validators.en.xlf
new file mode 100644
index 00000000..41617e3b
--- /dev/null
+++ b/resources/translations/validators.en.xlf
@@ -0,0 +1,694 @@
+
+
+
+
+
+
+
+
+ This value should be false.
+ This value should be false.
+
+
+ This value should be true.
+ This value should be true.
+
+
+ This value should be of type {{ type }}.
+ This value should be of type {{ type }}.
+
+
+ This value should be blank.
+ This value should be blank.
+
+
+ The value you selected is not a valid choice.
+ The value you selected is not a valid choice.
+
+
+ You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.
+ You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.
+
+
+ You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.
+ You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.
+
+
+ One or more of the given values is invalid.
+ One or more of the given values is invalid.
+
+
+ This field was not expected.
+ This field was not expected.
+
+
+ This field is missing.
+ This field is missing.
+
+
+ This value is not a valid date.
+ This value is not a valid date.
+
+
+ This value is not a valid datetime.
+ This value is not a valid datetime.
+
+
+ This value is not a valid email address.
+ This value is not a valid email address.
+
+
+ The file could not be found.
+ The file could not be found.
+
+
+ The file is not readable.
+ The file is not readable.
+
+
+ The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.
+ The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.
+
+
+ The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.
+ The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.
+
+
+ This value should be {{ limit }} or less.
+ This value should be {{ limit }} or less.
+
+
+ This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.
+ This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.
+
+
+ This value should be {{ limit }} or more.
+ This value should be {{ limit }} or more.
+
+
+ This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.
+ This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.
+
+
+ This value should not be blank.
+ This value should not be blank.
+
+
+ This value should not be null.
+ This value should not be null.
+
+
+ This value should be null.
+ This value should be null.
+
+
+ This value is not valid.
+ This value is not valid.
+
+
+ This value is not a valid time.
+ This value is not a valid time.
+
+
+ This value is not a valid URL.
+ This value is not a valid URL.
+
+
+ The two values should be equal.
+ The two values should be equal.
+
+
+ The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.
+ The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.
+
+
+ The file is too large.
+ The file is too large.
+
+
+ The file could not be uploaded.
+ The file could not be uploaded.
+
+
+ This value should be a valid number.
+ This value should be a valid number.
+
+
+ This file is not a valid image.
+ This file is not a valid image.
+
+
+ This is not a valid IP address.
+ This value is not a valid IP address.
+
+
+ This value is not a valid language.
+ This value is not a valid language.
+
+
+ This value is not a valid locale.
+ This value is not a valid locale.
+
+
+ This value is not a valid country.
+ This value is not a valid country.
+
+
+ This value is already used.
+ This value is already used.
+
+
+ The size of the image could not be detected.
+ The size of the image could not be detected.
+
+
+ The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.
+ The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.
+
+
+ The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.
+ The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.
+
+
+ The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.
+ The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.
+
+
+ The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.
+ The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.
+
+
+ This value should be the user's current password.
+ This value should be the user's current password.
+
+
+ This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.
+ This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.
+
+
+ The file was only partially uploaded.
+ The file was only partially uploaded.
+
+
+ No file was uploaded.
+ No file was uploaded.
+
+
+ No temporary folder was configured in php.ini.
+ No temporary folder was configured in php.ini, or the configured folder does not exist.
+
+
+ Cannot write temporary file to disk.
+ Cannot write temporary file to disk.
+
+
+ A PHP extension caused the upload to fail.
+ A PHP extension caused the upload to fail.
+
+
+ This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.
+ This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.
+
+
+ This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.
+ This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.
+
+
+ This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.
+ This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.
+
+
+ Invalid card number.
+ Invalid card number.
+
+
+ Unsupported card type or invalid card number.
+ Unsupported card type or invalid card number.
+
+
+ This is not a valid International Bank Account Number (IBAN).
+ This value is not a valid International Bank Account Number (IBAN).
+
+
+ This value is not a valid ISBN-10.
+ This value is not a valid ISBN-10.
+
+
+ This value is not a valid ISBN-13.
+ This value is not a valid ISBN-13.
+
+
+ This value is neither a valid ISBN-10 nor a valid ISBN-13.
+ This value is neither a valid ISBN-10 nor a valid ISBN-13.
+
+
+ This value is not a valid ISSN.
+ This value is not a valid ISSN.
+
+
+ This value is not a valid currency.
+ This value is not a valid currency.
+
+
+ This value should be equal to {{ compared_value }}.
+ This value should be equal to {{ compared_value }}.
+
+
+ This value should be greater than {{ compared_value }}.
+ This value should be greater than {{ compared_value }}.
+
+
+ This value should be greater than or equal to {{ compared_value }}.
+ This value should be greater than or equal to {{ compared_value }}.
+
+
+ This value should be identical to {{ compared_value_type }} {{ compared_value }}.
+ This value should be identical to {{ compared_value_type }} {{ compared_value }}.
+
+
+ This value should be less than {{ compared_value }}.
+ This value should be less than {{ compared_value }}.
+
+
+ This value should be less than or equal to {{ compared_value }}.
+ This value should be less than or equal to {{ compared_value }}.
+
+
+ This value should not be equal to {{ compared_value }}.
+ This value should not be equal to {{ compared_value }}.
+
+
+ This value should not be identical to {{ compared_value_type }} {{ compared_value }}.
+ This value should not be identical to {{ compared_value_type }} {{ compared_value }}.
+
+
+ The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.
+ The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.
+
+
+ The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.
+ The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.
+
+
+ The image is square ({{ width }}x{{ height }}px). Square images are not allowed.
+ The image is square ({{ width }}x{{ height }}px). Square images are not allowed.
+
+
+ The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.
+ The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.
+
+
+ The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.
+ The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.
+
+
+ An empty file is not allowed.
+ An empty file is not allowed.
+
+
+ The host could not be resolved.
+ The host could not be resolved.
+
+
+ This value does not match the expected {{ charset }} charset.
+ This value does not match the expected {{ charset }} charset.
+
+
+ This is not a valid Business Identifier Code (BIC).
+ This value is not a valid Business Identifier Code (BIC).
+
+
+ Error
+ Error
+
+
+ This is not a valid UUID.
+ This value is not a valid UUID.
+
+
+ This value should be a multiple of {{ compared_value }}.
+ This value should be a multiple of {{ compared_value }}.
+
+
+ This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.
+ This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.
+
+
+ This value should be valid JSON.
+ This value should be valid JSON.
+
+
+ This collection should contain only unique elements.
+ This collection should contain only unique elements.
+
+
+ This value should be positive.
+ This value should be positive.
+
+
+ This value should be either positive or zero.
+ This value should be either positive or zero.
+
+
+ This value should be negative.
+ This value should be negative.
+
+
+ This value should be either negative or zero.
+ This value should be either negative or zero.
+
+
+ This value is not a valid timezone.
+ This value is not a valid timezone.
+
+
+ This password has been leaked in a data breach, it must not be used. Please use another password.
+ This password has been leaked in a data breach, it must not be used. Please use another password.
+
+
+ This value should be between {{ min }} and {{ max }}.
+ This value should be between {{ min }} and {{ max }}.
+
+
+ This value is not a valid hostname.
+ This value is not a valid hostname.
+
+
+ The number of elements in this collection should be a multiple of {{ compared_value }}.
+ The number of elements in this collection should be a multiple of {{ compared_value }}.
+
+
+ This value should satisfy at least one of the following constraints:
+ This value should satisfy at least one of the following constraints:
+
+
+ Each element of this collection should satisfy its own set of constraints.
+ Each element of this collection should satisfy its own set of constraints.
+
+
+ This value is not a valid International Securities Identification Number (ISIN).
+ This value is not a valid International Securities Identification Number (ISIN).
+
+
+ This value should be a valid expression.
+ This value should be a valid expression.
+
+
+ This value is not a valid CSS color.
+ This value is not a valid CSS color.
+
+
+ This value is not a valid CIDR notation.
+ This value is not a valid CIDR notation.
+
+
+ The value of the netmask should be between {{ min }} and {{ max }}.
+ The value of the netmask should be between {{ min }} and {{ max }}.
+
+
+ The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less.
+ The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less.
+
+
+ The password strength is too low. Please use a stronger password.
+ The password strength is too low. Please use a stronger password.
+
+
+ This value contains characters that are not allowed by the current restriction-level.
+ This value contains characters that are not allowed by the current restriction-level.
+
+
+ Using invisible characters is not allowed.
+ Using invisible characters is not allowed.
+
+
+ Mixing numbers from different scripts is not allowed.
+ Mixing numbers from different scripts is not allowed.
+
+
+ Using hidden overlay characters is not allowed.
+ Using hidden overlay characters is not allowed.
+
+
+ The extension of the file is invalid ({{ extension }}). Allowed extensions are {{ extensions }}.
+ The extension of the file is invalid ({{ extension }}). Allowed extensions are {{ extensions }}.
+
+
+ The detected character encoding is invalid ({{ detected }}). Allowed encodings are {{ encodings }}.
+ The detected character encoding is invalid ({{ detected }}). Allowed encodings are {{ encodings }}.
+
+
+ This value is not a valid MAC address.
+ This value is not a valid MAC address.
+
+
+ This URL is missing a top-level domain.
+ This URL is missing a top-level domain.
+
+
+ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words.
+ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words.
+
+
+ This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less.
+ This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less.
+
+
+ This value does not represent a valid week in the ISO 8601 format.
+ This value does not represent a valid week in the ISO 8601 format.
+
+
+ This value is not a valid week.
+ This value is not a valid week.
+
+
+ This value should not be before week "{{ min }}".
+ This value should not be before week "{{ min }}".
+
+
+ This value should not be after week "{{ max }}".
+ This value should not be after week "{{ max }}".
+
+
+ This value is not a valid Twig template.
+ This value is not a valid Twig template.
+
+
+ This file is not a valid video.
+ This file is not a valid video.
+
+
+ The size of the video could not be detected.
+ The size of the video could not be detected.
+
+
+ The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.
+ The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.
+
+
+ The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.
+ The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.
+
+
+ The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.
+ The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.
+
+
+ The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.
+ The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.
+
+
+ The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels.
+ The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels.
+
+
+ The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels.
+ The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels.
+
+
+ The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.
+ The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.
+
+
+ The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.
+ The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.
+
+
+ The video is square ({{ width }}x{{ height }}px). Square videos are not allowed.
+ The video is square ({{ width }}x{{ height }}px). Square videos are not allowed.
+
+
+ The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed.
+ The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed.
+
+
+ The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed.
+ The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed.
+
+
+ The video file is corrupted.
+ The video file is corrupted.
+
+
+ The video contains multiple streams. Only one stream is allowed.
+ The video contains multiple streams. Only one stream is allowed.
+
+
+ Unsupported video codec "{{ codec }}".
+ Unsupported video codec "{{ codec }}".
+
+
+ Unsupported video container "{{ container }}".
+ Unsupported video container "{{ container }}".
+
+
+ The image file is corrupted.
+ The image file is corrupted.
+
+
+ The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels.
+ The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels.
+
+
+ The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels.
+ The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels.
+
+
+ This filename does not match the expected charset.
+ This filename does not match the expected charset.
+
+
+ This form should not contain extra fields.
+ This form should not contain extra fields.
+
+
+ The uploaded file was too large. Please try to upload a smaller file.
+ The uploaded file was too large. Please try to upload a smaller file.
+
+
+ The CSRF token is invalid. Please try to resubmit the form.
+ The CSRF token is invalid. Please try to resubmit the form.
+
+
+ This value is not a valid HTML5 color.
+ This value is not a valid HTML5 color.
+
+
+ Please enter a valid birthdate.
+ Please enter a valid birthdate.
+
+
+ The selected choice is invalid.
+ The selected choice is invalid.
+
+
+ The collection is invalid.
+ The collection is invalid.
+
+
+ Please select a valid color.
+ Please select a valid color.
+
+
+ Please select a valid country.
+ Please select a valid country.
+
+
+ Please select a valid currency.
+ Please select a valid currency.
+
+
+ Please choose a valid date interval.
+ Please choose a valid date interval.
+
+
+ Please enter a valid date and time.
+ Please enter a valid date and time.
+
+
+ Please enter a valid date.
+ Please enter a valid date.
+
+
+ Please select a valid file.
+ Please select a valid file.
+
+
+ The hidden field is invalid.
+ The hidden field is invalid.
+
+
+ Please enter an integer.
+ Please enter an integer.
+
+
+ Please select a valid language.
+ Please select a valid language.
+
+
+ Please select a valid locale.
+ Please select a valid locale.
+
+
+ Please enter a valid money amount.
+ Please enter a valid money amount.
+
+
+ Please enter a number.
+ Please enter a number.
+
+
+ The password is invalid.
+ The password is invalid.
+
+
+ Please enter a percentage value.
+ Please enter a percentage value.
+
+
+ The values do not match.
+ The values do not match.
+
+
+ Please enter a valid time.
+ Please enter a valid time.
+
+
+ Please select a valid timezone.
+ Please select a valid timezone.
+
+
+ Please enter a valid URL.
+ Please enter a valid URL.
+
+
+ Please enter a valid search term.
+ Please enter a valid search term.
+
+
+ Please provide a valid phone number.
+ Please provide a valid phone number.
+
+
+ The checkbox has an invalid value.
+ The checkbox has an invalid value.
+
+
+ Please enter a valid email address.
+ Please enter a valid email address.
+
+
+ Please select a valid option.
+ Please select a valid option.
+
+
+ Please select a valid range.
+ Please select a valid range.
+
+
+ Please enter a valid week.
+ Please enter a valid week.
+
+
+
+
diff --git a/src/Domain/Configuration/Service/Provider/ConfigProvider.php b/src/Domain/Configuration/Service/Provider/ConfigProvider.php
index d07728b4..ce00f9b7 100644
--- a/src/Domain/Configuration/Service/Provider/ConfigProvider.php
+++ b/src/Domain/Configuration/Service/Provider/ConfigProvider.php
@@ -29,13 +29,17 @@ public function isEnabled(ConfigOption $key): bool
}
$config = $this->configRepository->findOneBy(['item' => $key->value]);
- return $config?->getValue() === '1';
+ if ($config !== null) {
+ $config->getValue() === '1';
+ }
+
+ return DefaultConfigProvider::has($key->value) && DefaultConfigProvider::get($key->value) === '1';
}
/**
- * Get configuration value by its key
+ * Get configuration value by its key, from settings or default configs or default value (if provided)
*/
- public function getValue(ConfigOption $key, ?string $default = null): ?string
+ public function getValue(ConfigOption $key): ?string
{
if (in_array($key, $this->booleanValues)) {
throw new InvalidArgumentException('Key is a boolean value, use isEnabled instead');
@@ -47,10 +51,14 @@ public function getValue(ConfigOption $key, ?string $default = null): ?string
$this->cache->set($cacheKey, $value, $this->ttlSeconds);
}
- return $value ?? $default;
+ if ($value !== null) {
+ return $value;
+ }
+
+ return DefaultConfigProvider::has($key->value) ? DefaultConfigProvider::get($key->value) : null;
}
- public function getValueWithNamespace(ConfigOption $key, ?string $default = null): ?string
+ public function getValueWithNamespace(ConfigOption $key): ?string
{
$full = $this->getValue($key);
if ($full !== null && $full !== '') {
@@ -61,9 +69,9 @@ public function getValueWithNamespace(ConfigOption $key, ?string $default = null
[$parent] = explode(':', $key->value, 2);
$parentKey = ConfigOption::from($parent);
- return $this->getValue($parentKey, $default);
+ return $this->getValue($parentKey);
}
- return $default;
+ return null;
}
}
diff --git a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
index e35a124a..299d97e4 100644
--- a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
+++ b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
@@ -4,6 +4,8 @@
namespace PhpList\Core\Domain\Configuration\Service\Provider;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
class DefaultConfigProvider
{
/**
@@ -12,271 +14,280 @@ class DefaultConfigProvider
*/
private static array $defaults = [];
+ private static TranslatorInterface $translator;
+
+ public static function setTranslator(TranslatorInterface $translator): void
+ {
+ self::$translator = $translator;
+ }
+
private static function init(): void
{
if (!empty(self::$defaults)) {
return;
}
- self::$defaults = array(
- 'admin_address' => array(
+ $publicSchema = 'http';
+ $pageRoot = '/api/v2';
+
+ self::$defaults = [
+ 'admin_address' => [
'value' => 'webmaster@[DOMAIN]',
- 'description' => s('Person in charge of this system (one email address)'),
+ 'description' => self::$translator->trans('Person in charge of this system (one email address)'),
'type' => 'email',
'allowempty' => false,
'category' => 'general',
- ),
- 'organisation_name' => array(
+ ],
+ 'organisation_name' => [
'value' => '',
- 'description' => s('Name of the organisation'),
+ 'description' => self::$translator->trans('Name of the organisation'),
'type' => 'text',
'allowempty' => true,
'allowtags' => '
',
'allowJS' => false,
'category' => 'general',
- ),
- 'organisation_logo' => array(
+ ],
+ 'organisation_logo' => [
'value' => '',
- 'description' => s('Logo of the organisation'),
+ 'description' => self::$translator->trans('Logo of the organisation'),
'infoicon' => true,
'type' => 'image',
'allowempty' => true,
'category' => 'general',
- ),
- 'date_format' => array(
+ ],
+ 'date_format' => [
'value' => 'j F Y',
- 'description' => s('Date format'),
+ 'description' => self::$translator->trans('Date format'),
'infoicon' => true,
'type' => 'text',
'allowempty' => false,
'category' => 'general',
- ),
- 'rc_notification' => array(
+ ],
+ 'rc_notification' => [
'value' => 0,
- 'description' => s('Show notification for Release Candidates'),
+ 'description' => self::$translator->trans('Show notification for Release Candidates'),
'type' => 'boolean',
'allowempty' => true,
'category' => 'security',
- ),
- 'remote_processing_secret' => array(
+ ],
+ 'remote_processing_secret' => [
'value' => bin2hex(random_bytes(10)),
- 'description' => s('Secret for remote processing'),
+ 'description' => self::$translator->trans('Secret for remote processing'),
'type' => 'text',
'category' => 'security',
- ),
- 'notify_admin_login' => array(
+ ],
+ 'notify_admin_login' => [
'value' => 1,
- 'description' => s('Notify admin on login from new location'),
+ 'description' => self::$translator->trans('Notify admin on login from new location'),
'type' => 'boolean',
'category' => 'security',
'allowempty' => true,
- ),
- 'admin_addresses' => array(
+ ],
+ 'admin_addresses' => [
'value' => '',
- 'description' => s('List of email addresses to CC in system messages (separate by commas)'),
+ 'description' => self::$translator->trans('List of email addresses to CC in system messages (separate by commas)'),
'type' => 'emaillist',
'allowempty' => true,
'category' => 'reporting',
- ),
- 'campaignfrom_default' => array(
+ ],
+ 'campaignfrom_default' => [
'value' => '',
- 'description' => s("Default for 'From:' in a campaign"),
+ 'description' => self::$translator->trans("Default for 'From:' in a campaign"),
'type' => 'text',
'allowempty' => true,
'category' => 'campaign',
- ),
- 'notifystart_default' => array(
+ ],
+ 'notifystart_default' => [
'value' => '',
- 'description' => s("Default for 'address to alert when sending starts'"),
+ 'description' => self::$translator->trans("Default for 'address to alert when sending starts'"),
'type' => 'email',
'allowempty' => true,
'category' => 'campaign',
- ),
- 'notifyend_default' => array(
+ ],
+ 'notifyend_default' => [
'value' => '',
- 'description' => s("Default for 'address to alert when sending finishes'"),
+ 'description' => self::$translator->trans("Default for 'address to alert when sending finishes'"),
'type' => 'email',
'allowempty' => true,
'category' => 'campaign',
- ),
- 'always_add_googletracking' => array(
+ ],
+ 'always_add_googletracking' => [
'value' => '0',
- 'description' => s('Always add analytics tracking code to campaigns'),
+ 'description' => self::$translator->trans('Always add analytics tracking code to campaigns'),
'type' => 'boolean',
'allowempty' => true,
'category' => 'campaign',
- ),
- 'analytic_tracker' => array(
+ ],
+ 'analytic_tracker' => [
'values' => array('google' => 'Google Analytics', 'matomo' => 'Matomo'),
'value' => 'google',
- 'description' => s('Analytics tracking code to add to campaign URLs'),
+ 'description' => self::$translator->trans('Analytics tracking code to add to campaign URLs'),
'type' => 'select',
'allowempty' => false,
'category' => 'campaign',
- ),
- 'report_address' => array(
+ ],
+ 'report_address' => [
'value' => 'listreports@[DOMAIN]',
- 'description' => s('Who gets the reports (email address, separate multiple emails with a comma)'),
+ 'description' => self::$translator->trans('Who gets the reports (email address, separate multiple emails with a comma)'),
'type' => 'emaillist',
'allowempty' => true,
'category' => 'reporting',
- ),
- 'message_from_address' => array(
+ ],
+ 'message_from_address' => [
'value' => 'noreply@[DOMAIN]',
- 'description' => s('From email address for system messages'),
+ 'description' => self::$translator->trans('From email address for system messages'),
'type' => 'email',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'message_from_name' => array(
- 'value' => s('Webmaster'),
- 'description' => s('Name for system messages'),
+ ],
+ 'message_from_name' => [
+ 'value' => self::$translator->trans('Webmaster'),
+ 'description' => self::$translator->trans('Name for system messages'),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'message_replyto_address' => array(
+ ],
+ 'message_replyto_address' => [
'value' => 'noreply@[DOMAIN]',
- 'description' => s('Reply-to email address for system messages'),
+ 'description' => self::$translator->trans('Reply-to email address for system messages'),
'type' => 'email',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'hide_single_list' => array(
+ ],
+ 'hide_single_list' => [
'value' => '1',
- 'description' => s('If there is only one visible list, should it be hidden in the page and automatically subscribe users who sign up'),
+ 'description' => self::$translator->trans('If there is only one visible list, should it be hidden in the page and automatically subscribe users who sign up'),
'type' => 'boolean',
'allowempty' => true,
'category' => 'subscription-ui',
- ),
- 'list_categories' => array(
+ ],
+ 'list_categories' => [
'value' => '',
- 'description' => s('Categories for lists. Separate with commas.'),
+ 'description' => self::$translator->trans('Categories for lists. Separate with commas.'),
'infoicon' => true,
'type' => 'text',
'allowempty' => true,
'category' => 'list-organisation',
- ),
-
- 'displaycategories' => array(
+ ],
+ 'displaycategories' => [
'value' => 0,
- 'description' => s('Display list categories on subscribe page'),
+ 'description' => self::$translator->trans('Display list categories on subscribe page'),
'type' => 'boolean',
'allowempty' => false,
'category' => 'list-organisation',
- ),
- 'textline_width' => array(
+ ],
+ 'textline_width' => [
'value' => '40',
- 'description' => s('Width of a textline field (numerical)'),
+ 'description' => self::$translator->trans('Width of a textline field (numerical)'),
'type' => 'integer',
'min' => 20,
'max' => 150,
'category' => 'subscription-ui',
- ),
- 'textarea_dimensions' => array(
+ ],
+ 'textarea_dimensions' => [
'value' => '10,40',
- 'description' => s('Dimensions of a textarea field (rows,columns)'),
+ 'description' => self::$translator->trans('Dimensions of a textarea field (rows,columns)'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription-ui',
- ),
- 'send_admin_copies' => array(
+ ],
+ 'send_admin_copies' => [
'value' => '0',
- 'description' => s('Send notifications about subscribe, update and unsubscribe'),
+ 'description' => self::$translator->trans('Send notifications about subscribe, update and unsubscribe'),
'type' => 'boolean',
'allowempty' => true,
'category' => 'reporting',
- ),
- 'defaultsubscribepage' => array(
+ ],
+ 'defaultsubscribepage' => [
'value' => 1,
- 'description' => s('The default subscribe page when there are multiple'),
+ 'description' => self::$translator->trans('The default subscribe page when there are multiple'),
'type' => 'integer',
'min' => 1,
'max' => 999,
'allowempty' => true,
'category' => 'subscription',
- ),
- 'defaultmessagetemplate' => array(
+ ],
+ 'defaultmessagetemplate' => [
'value' => 0,
- 'description' => s('The default HTML template to use when sending a message'),
+ 'description' => self::$translator->trans('The default HTML template to use when sending a message'),
'type' => 'text',
'allowempty' => true,
'category' => 'campaign',
- ),
- 'systemmessagetemplate' => array(
+ ],
+ 'systemmessagetemplate' => [
'value' => 0,
- 'description' => s('The HTML wrapper template for system messages'),
+ 'description' => self::$translator->trans('The HTML wrapper template for system messages'),
'type' => 'integer',
'min' => 0,
'max' => 999, // or max(id) from template
'allowempty' => true,
'category' => 'transactional',
- ),
- 'subscribeurl' => array(
- 'value' => $GLOBALS['public_scheme']."://[WEBSITE]$pageroot/?p=subscribe",
- 'description' => s('URL where subscribers can sign up'),
+ ],
+ 'subscribeurl' => [
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/subscribe",
+ 'description' => self::$translator->trans('URL where subscribers can sign up'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
- ),
- 'unsubscribeurl' => array(
- 'value' => $GLOBALS['public_scheme']."://[WEBSITE]$pageroot/?p=unsubscribe",
- 'description' => s('URL where subscribers can unsubscribe'),
+ ],
+ 'unsubscribeurl' => [
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/unsubscribe",
+ 'description' => self::$translator->trans('URL where subscribers can unsubscribe'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
- ),
- 'blacklisturl' => array(
- 'value' => $GLOBALS['public_scheme']."://[WEBSITE]$pageroot/?p=donotsend",
- 'description' => s('URL where unknown users can unsubscribe (do-not-send-list)'),
+ ],
+ 'blacklisturl' => [
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/donotsend",
+ 'description' => self::$translator->trans('URL where unknown users can unsubscribe (do-not-send-list)'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
- ),
- 'confirmationurl' => array(
- 'value' => $GLOBALS['public_scheme']."://[WEBSITE]$pageroot/?p=confirm",
- 'description' => s('URL where subscribers have to confirm their subscription'),
+ ],
+ 'confirmationurl' => [
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/confirm",
+ 'description' => self::$translator->trans('URL where subscribers have to confirm their subscription'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
- ),
- 'preferencesurl' => array(
- 'value' => $GLOBALS['public_scheme']."://[WEBSITE]$pageroot/?p=preferences",
- 'description' => s('URL where subscribers can update their details'),
+ ],
+ 'preferencesurl' => [
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/preferences",
+ 'description' => self::$translator->trans('URL where subscribers can update their details'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
- ),
- 'forwardurl' => array(
- 'value' => $GLOBALS['public_scheme']."://[WEBSITE]$pageroot/?p=forward",
- 'description' => s('URL for forwarding messages'),
+ ],
+ 'forwardurl' => [
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/forward",
+ 'description' => self::$translator->trans('URL for forwarding messages'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
- ),
- 'vcardurl' => array(
- 'value' => $GLOBALS['public_scheme']."://[WEBSITE]$pageroot/?p=vcard",
- 'description' => s('URL for downloading vcf card'),
+ ],
+ 'vcardurl' => [
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/vcard",
+ 'description' => self::$translator->trans('URL for downloading vcf card'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
- ),
- 'ajax_subscribeconfirmation' => array(
- 'value' => s('
Thanks, you have been added to our newsletter
You will receive an email to confirm your subscription. Please click the link in the email to confirm
'),
- 'description' => s('Text to display when subscription with an AJAX request was successful'),
+ ],
+ 'ajax_subscribeconfirmation' => [
+ 'value' => self::$translator->trans('
Thanks, you have been added to our newsletter
You will receive an email to confirm your subscription. Please click the link in the email to confirm
'),
+ 'description' => self::$translator->trans('Text to display when subscription with an AJAX request was successful'),
'type' => 'textarea',
'allowempty' => true,
'category' => 'subscription',
- ),
- 'subscribesubject' => array(
- 'value' => s('Request for confirmation'),
- 'description' => s('Subject of the message subscribers receive when they sign up'),
+ ],
+ 'subscribesubject' => [
+ 'value' => self::$translator->trans('Request for confirmation'),
+ 'description' => self::$translator->trans('Subject of the message subscribers receive when they sign up'),
'infoicon' => true,
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'subscribemessage' => array(
+ ],
+ 'subscribemessage' => [
'value' =>
' You have been subscribed to the following newsletters:
@@ -297,19 +308,19 @@ private static function init(): void
If this is not correct, or you do not agree, simply take no action and delete this message.'
,
- 'description' => s('Message subscribers receive when they sign up'),
+ 'description' => self::$translator->trans('Message subscribers receive when they sign up'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'unsubscribesubject' => array(
- 'value' => s('Goodbye from our Newsletter'),
- 'description' => s('Subject of the message subscribers receive when they unsubscribe'),
+ ],
+ 'unsubscribesubject' => [
+ 'value' => self::$translator->trans('Goodbye from our Newsletter'),
+ 'description' => self::$translator->trans('Subject of the message subscribers receive when they unsubscribe'),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'unsubscribemessage' => array(
+ ],
+ 'unsubscribemessage' => [
'value' =>
'Goodbye from our Newsletter, sorry to see you go.
@@ -323,19 +334,19 @@ private static function init(): void
Thank you'
,
- 'description' => s('Message subscribers receive when they unsubscribe'),
+ 'description' => self::$translator->trans('Message subscribers receive when they unsubscribe'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'confirmationsubject' => array(
- 'value' => s('Welcome to our Newsletter'),
- 'description' => s('Subject of the message subscribers receive after confirming their email address'),
+ ],
+ 'confirmationsubject' => [
+ 'value' => self::$translator->trans('Welcome to our Newsletter'),
+ 'description' => self::$translator->trans('Subject of the message subscribers receive after confirming their email address'),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'confirmationmessage' => array(
+ ],
+ 'confirmationmessage' => [
'value' =>
'Welcome to our Newsletter
@@ -349,23 +360,23 @@ private static function init(): void
Thank you'
,
- 'description' => s('Message subscribers receive after confirming their email address'),
+ 'description' => self::$translator->trans('Message subscribers receive after confirming their email address'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'updatesubject' => array(
- 'value' => s('[notify] Change of List-Membership details'),
- 'description' => s('Subject of the message subscribers receive when they have changed their details'),
+ ],
+ 'updatesubject' => [
+ 'value' => self::$translator->trans('[notify] Change of List-Membership details'),
+ 'description' => self::$translator->trans('Subject of the message subscribers receive when they have changed their details'),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
- ),
+ ],
// the message that is sent when a user updates their information.
// just to make sure they approve of it.
// confirmationinfo is replaced by one of the options below
// userdata is replaced by the information in the database
- 'updatemessage' => array(
+ 'updatemessage' => [
'value' =>
'This message is to inform you of a change of your details on our newsletter database
@@ -385,15 +396,15 @@ private static function init(): void
Thank you'
,
- 'description' => s('Message subscribers receive when they have changed their details'),
+ 'description' => self::$translator->trans('Message subscribers receive when they have changed their details'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
- ),
+ ],
// this is the text that is placed in the [!-- confirmation --] location of the above
// message, in case the email is sent to their new email address and they have changed
// their email address
- 'emailchanged_text' => array(
+ 'emailchanged_text' => [
'value' => '
When updating your details, your email address has changed.
Please confirm your new email address by visiting this webpage:
@@ -401,15 +412,15 @@ private static function init(): void
[CONFIRMATIONURL]
',
- 'description' => s('Part of the message that is sent to their new email address when subscribers change their information, and the email address has changed'),
+ 'description' => self::$translator->trans('Part of the message that is sent to their new email address when subscribers change their information, and the email address has changed'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
- ),
+ ],
// this is the text that is placed in the [!-- confirmation --] location of the above
// message, in case the email is sent to their old email address and they have changed
// their email address
- 'emailchanged_text_oldaddress' => array(
+ 'emailchanged_text_oldaddress' => [
'value' =>
'Please Note: when updating your details, your email address has changed.
@@ -417,19 +428,19 @@ private static function init(): void
to confirm this change. Please visit this website to activate
your membership.'
,
- 'description' => s('Part of the message that is sent to their old email address when subscribers change their information, and the email address has changed'),
+ 'description' => self::$translator->trans('Part of the message that is sent to their old email address when subscribers change their information, and the email address has changed'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'personallocation_subject' => array(
- 'value' => s('Your personal location'),
- 'description' => s('Subject of message when subscribers request their personal location'),
+ ],
+ 'personallocation_subject' => [
+ 'value' => self::$translator->trans('Your personal location'),
+ 'description' => self::$translator->trans('Subject of message when subscribers request their personal location'),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'messagefooter' => array(
+ ],
+ 'messagefooter' => [
'value' => '--
',
- 'description' => s('Default footer for sending a campaign'),
+ 'description' => self::$translator->trans('Default footer for sending a campaign'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'campaign',
- ),
- 'forwardfooter' => array(
+ ],
+ 'forwardfooter' => [
'value' => '
',
- 'description' => s('Footer used when a message has been forwarded'),
+ 'description' => self::$translator->trans('Footer used when a message has been forwarded'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'campaign',
- ),
- 'personallocation_message' => array(
+ ],
+ 'personallocation_message' => [
'value' =>
-
'You have requested your personal location to update your details from our website.
The location is below. Please make sure that you use the full line as mentioned below.
Sometimes email programmes can wrap the line into multiple lines.
@@ -471,80 +481,80 @@ private static function init(): void
Thank you.'
,
- 'description' => s('Message to send when they request their personal location'),
+ 'description' => self::$translator->trans('Message to send when they request their personal location'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
- ),
- 'remoteurl_append' => array(
+ ],
+ 'remoteurl_append' => [
'value' => '',
- 'description' => s('String to always append to remote URL when using send-a-webpage'),
+ 'description' => self::$translator->trans('String to always append to remote URL when using send-a-webpage'),
'type' => 'text',
'allowempty' => true,
'category' => 'campaign',
- ),
- 'wordwrap' => array(
+ ],
+ 'wordwrap' => [
'value' => '75',
- 'description' => s('Width for Wordwrap of Text messages'),
+ 'description' => self::$translator->trans('Width for Wordwrap of Text messages'),
'type' => 'text',
'allowempty' => true,
'category' => 'campaign',
- ),
- 'html_email_style' => array(
+ ],
+ 'html_email_style' => [
'value' => '',
- 'description' => s('CSS for HTML messages without a template'),
+ 'description' => self::$translator->trans('CSS for HTML messages without a template'),
'type' => 'textarea',
'allowempty' => true,
'category' => 'campaign',
- ),
- 'alwayssendtextto' => array(
+ ],
+ 'alwayssendtextto' => [
'value' => '',
- 'description' => s('Domains that only accept text emails, one per line'),
+ 'description' => self::$translator->trans('Domains that only accept text emails, one per line'),
'type' => 'textarea',
'allowempty' => true,
'category' => 'campaign',
- ),
- 'tld_last_sync' => array(
+ ],
+ 'tld_last_sync' => [
'value' => '0',
- 'description' => s('last time TLDs were fetched'),
+ 'description' => self::$translator->trans('last time TLDs were fetched'),
'type' => 'text',
'allowempty' => true,
'category' => 'system',
'hidden' => true,
- ),
- 'internet_tlds' => array(
+ ],
+ 'internet_tlds' => [
'value' => '',
- 'description' => s('Top level domains'),
+ 'description' => self::$translator->trans('Top level domains'),
'type' => 'textarea',
'allowempty' => true,
'category' => 'system',
'hidden' => true,
- ),
- 'pageheader' => array(
+ ],
+ 'pageheader' => [
'value' => '
Welcome
',
- 'description' => s('Header of public pages.'),
+ 'description' => self::$translator->trans('Header of public pages.'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'subscription-ui',
- ),
- 'pagefooter' => array(
+ ],
+ 'pagefooter' => [
'value' => '
Footer text
',
- 'description' => s('Footer of public pages'),
+ 'description' => self::$translator->trans('Footer of public pages'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'subscription-ui',
- ),
- );
+ ],
+ ];
}
/**
* Get a single default config item by key
*
* @param string $key
- * @param mixed $default
+ * @param mixed|null $default
* @return mixed
*/
- public static function get(string $key, $default = null)
+ public static function get(string $key, mixed $default = null)
{
self::init();
return self::$defaults[$key] ?? $default;
From 6a9946316e530c24028f9a3bfbed7652fe21f000 Mon Sep 17 00:00:00 2001
From: Tatevik
Date: Fri, 3 Oct 2025 12:12:56 +0400
Subject: [PATCH 10/16] Email with messageHandler
---
config/parameters.yml.dist | 4 +-
config/services/messenger.yml | 6 ++
config/services/services.yml | 9 ++-
.../Service/LegacyUrlBuilder.php | 30 ++++++++
.../Service/PlaceholderResolver.php | 31 +++++++++
.../Provider/DefaultConfigProvider.php | 14 ++--
.../Service/UserPersonalizer.php | 68 +++++++++++++++++++
.../SubscriptionConfirmationMessage.php | 51 ++++++++++++++
...SubscriptionConfirmationMessageHandler.php | 57 ++++++++++++++++
.../SubscriberAttributeValueRepository.php | 12 ++++
.../Resolver/AttributeValueResolver.php | 7 +-
.../Service/SubscriberCsvImporter.php | 49 ++++---------
.../SubscriberCsvImportManagerTest.php | 10 +--
13 files changed, 295 insertions(+), 53 deletions(-)
create mode 100644 src/Domain/Configuration/Service/LegacyUrlBuilder.php
create mode 100644 src/Domain/Configuration/Service/PlaceholderResolver.php
create mode 100644 src/Domain/Configuration/Service/UserPersonalizer.php
create mode 100644 src/Domain/Messaging/Message/SubscriptionConfirmationMessage.php
create mode 100644 src/Domain/Messaging/MessageHandler/SubscriptionConfirmationMessageHandler.php
diff --git a/config/parameters.yml.dist b/config/parameters.yml.dist
index e34a7d2b..fb2ce8ee 100644
--- a/config/parameters.yml.dist
+++ b/config/parameters.yml.dist
@@ -28,7 +28,9 @@ parameters:
app.mailer_dsn: '%%env(MAILER_DSN)%%'
env(MAILER_DSN): 'null://null'
app.confirmation_url: '%%env(CONFIRMATION_URL)%%'
- env(CONFIRMATION_URL): 'https://example.com/confirm/'
+ env(CONFIRMATION_URL): 'https://example.com/subscriber/confirm/'
+ app.subscription_confirmation_url: '%%env(SUBSCRIPTION_CONFIRMATION_URL)%%'
+ env(SUBSCRIPTION_CONFIRMATION_URL): 'https://example.com/subscription/confirm/'
app.password_reset_url: '%%env(PASSWORD_RESET_URL)%%'
env(PASSWORD_RESET_URL): 'https://example.com/reset/'
diff --git a/config/services/messenger.yml b/config/services/messenger.yml
index 3d1e59b2..80f893f4 100644
--- a/config/services/messenger.yml
+++ b/config/services/messenger.yml
@@ -22,3 +22,9 @@ services:
tags: [ 'messenger.message_handler' ]
arguments:
$passwordResetUrl: '%app.password_reset_url%'
+
+ PhpList\Core\Domain\Messaging\MessageHandler\SubscriptionConfirmationMessageHandler:
+ autowire: true
+ autoconfigure: true
+ tags: [ 'messenger.message_handler' ]
+
diff --git a/config/services/services.yml b/config/services/services.yml
index fac384b9..d33ddd2c 100644
--- a/config/services/services.yml
+++ b/config/services/services.yml
@@ -120,8 +120,15 @@ services:
arguments:
$maxSeconds: '%messaging.max_process_time%'
-
PhpList\Core\Domain\Identity\Service\PermissionChecker:
autowire: true
autoconfigure: true
public: true
+
+ PhpList\Core\Domain\Configuration\Service\UserPersonalizer:
+ autowire: true
+ autoconfigure: true
+
+ PhpList\Core\Domain\Configuration\Service\LegacyUrlBuilder:
+ autowire: true
+ autoconfigure: true
diff --git a/src/Domain/Configuration/Service/LegacyUrlBuilder.php b/src/Domain/Configuration/Service/LegacyUrlBuilder.php
new file mode 100644
index 00000000..107f236c
--- /dev/null
+++ b/src/Domain/Configuration/Service/LegacyUrlBuilder.php
@@ -0,0 +1,30 @@
+ */
+ private array $providers = [];
+
+ public function register(string $token, callable $provider): void
+ {
+ // tokens like [UNSUBSCRIBEURL] (case-insensitive)
+ $this->providers[strtoupper($token)] = $provider;
+ }
+
+ public function resolve(?string $input): ?string
+ {
+ if ($input === null || $input === '') return $input;
+
+ // Replace [TOKEN] (case-insensitive)
+ return preg_replace_callback('/\[(\w+)\]/i', function ($m) {
+ $key = strtoupper($m[1]);
+ if (!isset($this->providers[$key])) {
+ return $m[0];
+ }
+ return (string) ($this->providers[$key])();
+ }, $input);
+ }
+}
diff --git a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
index 299d97e4..bbb796ce 100644
--- a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
+++ b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
@@ -224,49 +224,49 @@ private static function init(): void
'category' => 'transactional',
],
'subscribeurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/subscribe",
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=subscribe",
'description' => self::$translator->trans('URL where subscribers can sign up'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
],
'unsubscribeurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/unsubscribe",
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=unsubscribe",
'description' => self::$translator->trans('URL where subscribers can unsubscribe'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
],
'blacklisturl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/donotsend",
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=donotsend",
'description' => self::$translator->trans('URL where unknown users can unsubscribe (do-not-send-list)'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
],
'confirmationurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/confirm",
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=confirm",
'description' => self::$translator->trans('URL where subscribers have to confirm their subscription'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'preferencesurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/preferences",
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=preferences",
'description' => self::$translator->trans('URL where subscribers can update their details'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'forwardurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/forward",
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=forward",
'description' => self::$translator->trans('URL for forwarding messages'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'vcardurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/vcard",
+ 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=vcard",
'description' => self::$translator->trans('URL for downloading vcf card'),
'type' => 'text',
'allowempty' => 0,
diff --git a/src/Domain/Configuration/Service/UserPersonalizer.php b/src/Domain/Configuration/Service/UserPersonalizer.php
new file mode 100644
index 00000000..c7f55d4f
--- /dev/null
+++ b/src/Domain/Configuration/Service/UserPersonalizer.php
@@ -0,0 +1,68 @@
+subscriberRepository->findOneByEmail($email);
+ if (!$user) {
+ return $value;
+ }
+
+ $resolver = new PlaceholderResolver();
+ $resolver->register('EMAIL', fn() => $user->getEmail());
+
+ $resolver->register('UNSUBSCRIBEURL', function () use ($user) {
+ $base = $this->config->getValue(ConfigOption::UnsubscribeUrl) ?? '';
+ return $this->urlBuilder->withUid($base, $user->getUniqueId()) . self::PHP_SPACE;
+ });
+
+ $resolver->register('CONFIRMATIONURL', function () use ($user) {
+ $base = $this->config->getValue(ConfigOption::ConfirmationUrl) ?? '';
+ return $this->urlBuilder->withUid($base, $user->getUniqueId()) . self::PHP_SPACE;
+ });
+ $resolver->register('PREFERENCESURL', function () use ($user) {
+ $base = $this->config->getValue(ConfigOption::PreferencesUrl) ?? '';
+ return $this->urlBuilder->withUid($base, $user->getUniqueId()) . self::PHP_SPACE;
+ });
+
+ $resolver->register(
+ 'SUBSCRIBEURL',
+ fn() => ($this->config->getValue(ConfigOption::SubscribeUrl) ?? '') . self::PHP_SPACE
+ );
+ $resolver->register('DOMAIN', fn() => $this->config->getValue(ConfigOption::Domain) ?? '');
+ $resolver->register('WEBSITE', fn() => $this->config->getValue(ConfigOption::Website) ?? '');
+
+ $userAttributes = $this->attributesRepository->getForSubscriber($user);
+ foreach ($userAttributes as $userAttribute) {
+ $resolver->register(
+ strtoupper($userAttribute->getAttributeDefinition()->getName()),
+ fn() => $this->attributeValueResolver->resolve($userAttribute)
+ );
+ }
+
+ $out = $resolver->resolve($value);
+
+ return (string) $out;
+ }
+}
diff --git a/src/Domain/Messaging/Message/SubscriptionConfirmationMessage.php b/src/Domain/Messaging/Message/SubscriptionConfirmationMessage.php
new file mode 100644
index 00000000..22515145
--- /dev/null
+++ b/src/Domain/Messaging/Message/SubscriptionConfirmationMessage.php
@@ -0,0 +1,51 @@
+email = $email;
+ $this->uniqueId = $uniqueId;
+ $this->listIds = $listIds;
+ $this->htmlEmail = $htmlEmail;
+ }
+
+ public function getEmail(): string
+ {
+ return $this->email;
+ }
+
+ public function getUniqueId(): string
+ {
+ return $this->uniqueId;
+ }
+
+ public function getListIds(): array
+ {
+ return $this->listIds;
+ }
+
+ public function hasHtmlEmail(): bool
+ {
+ return $this->htmlEmail;
+ }
+}
diff --git a/src/Domain/Messaging/MessageHandler/SubscriptionConfirmationMessageHandler.php b/src/Domain/Messaging/MessageHandler/SubscriptionConfirmationMessageHandler.php
new file mode 100644
index 00000000..51514627
--- /dev/null
+++ b/src/Domain/Messaging/MessageHandler/SubscriptionConfirmationMessageHandler.php
@@ -0,0 +1,57 @@
+emailService = $emailService;
+ $this->configProvider = $configProvider;
+ $this->logger = $logger;
+ $this->userPersonalizer = $userPersonalizer;
+ }
+
+ /**
+ * Process a subscription confirmation message by sending the confirmation email
+ */
+ public function __invoke(SubscriberConfirmationMessage $message): void
+ {
+ $subject = $this->configProvider->getValue(ConfigOption::SubscribeEmailSubject);
+ $textContent = $this->configProvider->getValue(ConfigOption::SubscribeMessage);
+ $replacedTextContent = $this->userPersonalizer->personalize($textContent, $message->getUniqueId());
+
+ $email = (new Email())
+ ->to($message->getEmail())
+ ->subject($subject)
+ ->text($replacedTextContent);
+
+ $this->emailService->sendEmail($email);
+
+ $this->logger->info('Subscription confirmation email sent to {email}', ['email' => $message->getEmail()]);
+ }
+}
diff --git a/src/Domain/Subscription/Repository/SubscriberAttributeValueRepository.php b/src/Domain/Subscription/Repository/SubscriberAttributeValueRepository.php
index d29d56ff..6da037fd 100644
--- a/src/Domain/Subscription/Repository/SubscriberAttributeValueRepository.php
+++ b/src/Domain/Subscription/Repository/SubscriberAttributeValueRepository.php
@@ -64,4 +64,16 @@ public function getFilteredAfterId(int $lastId, int $limit, ?FilterRequestInterf
->getQuery()
->getResult();
}
+
+ /** @return SubscriberAttributeValue[] */
+ public function getForSubscriber(Subscriber $subscriber): array
+ {
+ return $this->createQueryBuilder('sa')
+ ->join('sa.subscriber', 's')
+ ->join('sa.attributeDefinition', 'ad')
+ ->where('s = :subscriber')
+ ->setParameter('subscriber', $subscriber)
+ ->getQuery()
+ ->getResult();
+ }
}
diff --git a/src/Domain/Subscription/Service/Resolver/AttributeValueResolver.php b/src/Domain/Subscription/Service/Resolver/AttributeValueResolver.php
index 4b294c14..4edf42d1 100644
--- a/src/Domain/Subscription/Service/Resolver/AttributeValueResolver.php
+++ b/src/Domain/Subscription/Service/Resolver/AttributeValueResolver.php
@@ -4,7 +4,6 @@
namespace PhpList\Core\Domain\Subscription\Service\Resolver;
-use PhpList\Core\Domain\Subscription\Model\SubscriberAttributeDefinition;
use PhpList\Core\Domain\Subscription\Model\SubscriberAttributeValue;
use PhpList\Core\Domain\Subscription\Service\Provider\AttributeValueProvider;
@@ -13,11 +12,11 @@ class AttributeValueResolver
/** @param iterable $providers */
public function __construct(private readonly iterable $providers) {}
- public function resolve(SubscriberAttributeDefinition $attribute, SubscriberAttributeValue $userAttr): string
+ public function resolve(SubscriberAttributeValue $userAttr): string
{
foreach ($this->providers as $provider) {
- if ($provider->supports($attribute)) {
- return $provider->getValue($attribute, $userAttr);
+ if ($provider->supports($userAttr->getAttributeDefinition())) {
+ return $provider->getValue($userAttr->getAttributeDefinition(), $userAttr);
}
}
return '';
diff --git a/src/Domain/Subscription/Service/SubscriberCsvImporter.php b/src/Domain/Subscription/Service/SubscriberCsvImporter.php
index 350c502c..1e7c9217 100644
--- a/src/Domain/Subscription/Service/SubscriberCsvImporter.php
+++ b/src/Domain/Subscription/Service/SubscriberCsvImporter.php
@@ -5,21 +5,18 @@
namespace PhpList\Core\Domain\Subscription\Service;
use Doctrine\ORM\EntityManagerInterface;
-use PhpList\Core\Domain\Configuration\Model\ConfigOption;
-use PhpList\Core\Domain\Configuration\Service\Provider\ConfigProvider;
-use PhpList\Core\Domain\Messaging\Service\EmailService;
+use PhpList\Core\Domain\Messaging\Message\SubscriptionConfirmationMessage;
use PhpList\Core\Domain\Subscription\Exception\CouldNotReadUploadedFileException;
use PhpList\Core\Domain\Subscription\Model\Dto\ImportSubscriberDto;
use PhpList\Core\Domain\Subscription\Model\Dto\SubscriberImportOptions;
use PhpList\Core\Domain\Subscription\Model\Subscriber;
use PhpList\Core\Domain\Subscription\Repository\SubscriberAttributeDefinitionRepository;
-use PhpList\Core\Domain\Subscription\Repository\SubscriberListRepository;
use PhpList\Core\Domain\Subscription\Repository\SubscriberRepository;
use PhpList\Core\Domain\Subscription\Service\Manager\SubscriberAttributeManager;
use PhpList\Core\Domain\Subscription\Service\Manager\SubscriberManager;
use PhpList\Core\Domain\Subscription\Service\Manager\SubscriptionManager;
use Symfony\Component\HttpFoundation\File\UploadedFile;
-use Symfony\Component\Mime\Email;
+use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Throwable;
@@ -37,9 +34,7 @@ class SubscriberCsvImporter
private SubscriberAttributeDefinitionRepository $attrDefinitionRepository;
private EntityManagerInterface $entityManager;
private TranslatorInterface $translator;
- private EmailService $emailService;
- private ConfigProvider $configProvider;
- private SubscriberListRepository $subscriberListRepository;
+ private MessageBusInterface $messageBus;
public function __construct(
SubscriberManager $subscriberManager,
@@ -50,9 +45,7 @@ public function __construct(
SubscriberAttributeDefinitionRepository $attrDefinitionRepository,
EntityManagerInterface $entityManager,
TranslatorInterface $translator,
- EmailService $emailService,
- ConfigProvider $configProvider,
- SubscriberListRepository $subscriberListRepository,
+ MessageBusInterface $messageBus,
) {
$this->subscriberManager = $subscriberManager;
$this->attributeManager = $attributeManager;
@@ -62,9 +55,7 @@ public function __construct(
$this->attrDefinitionRepository = $attrDefinitionRepository;
$this->entityManager = $entityManager;
$this->translator = $translator;
- $this->emailService = $emailService;
- $this->configProvider = $configProvider;
- $this->subscriberListRepository = $subscriberListRepository;
+ $this->messageBus = $messageBus;
}
/**
@@ -198,33 +189,21 @@ private function processRow(
if (!$options->dryRun) {
$this->entityManager->flush();
if ($options->notifySubscribers && $addedNewSubscriberToList) {
- $this->sendSubscribeEmail($dto->email, $options->listIds);
+ $this->sendSubscribeEmail($subscriber, $options->listIds);
}
}
}
- private function sendSubscribeEmail(string $subscriberEmail, array $listIds): void
+ private function sendSubscribeEmail(Subscriber $subscriber, array $listIds): void
{
- $listNames = [];
- foreach ($listIds as $id) {
- $list = $this->subscriberListRepository->find($id);
- if ($list) {
- $listNames[] = $list->getName();
- }
- }
- $listOfLists = implode(', ', $listNames);
-
- $subject = $this->configProvider->getValue('subscribesubject', 'Subscription');
- $message = $this->configProvider->getValue('subscribemessage', 'You have been subscribed to: [LISTS]');
- $message = str_replace('[LISTS]', $listOfLists, (string)$message);
-
- $email = (new Email())
- ->to($subscriberEmail)
- ->subject((string)$subject)
- ->text($message)
- ->html(nl2br(htmlentities($message)));
+ $message = new SubscriptionConfirmationMessage(
+ email: $subscriber->getEmail(),
+ uniqueId: $subscriber->getUniqueId(),
+ listIds: $listIds,
+ htmlEmail: $subscriber->hasHtmlEmail(),
+ );
- $this->emailService->sendEmail($email);
+ $this->messageBus->dispatch($message);
}
/**
diff --git a/tests/Integration/Domain/Subscription/Service/SubscriberCsvImportManagerTest.php b/tests/Integration/Domain/Subscription/Service/SubscriberCsvImportManagerTest.php
index 0e84fdec..77a1f61d 100644
--- a/tests/Integration/Domain/Subscription/Service/SubscriberCsvImportManagerTest.php
+++ b/tests/Integration/Domain/Subscription/Service/SubscriberCsvImportManagerTest.php
@@ -49,11 +49,11 @@ public function testImportFromCsvCreatesNewSubscribers(): void
file_put_contents($tempFile, $csvContent);
$uploadedFile = new UploadedFile(
- $tempFile,
- 'subscribers.csv',
- 'text/csv',
- null,
- true
+ path: $tempFile,
+ originalName: 'subscribers.csv',
+ mimeType: 'text/csv',
+ error: null,
+ test: true
);
$subscriberCountBefore = count($this->subscriberRepository->findAll());
From fc6ba926336a1f581e966acf7b75e46d78ac19bd Mon Sep 17 00:00:00 2001
From: Tatevik
Date: Fri, 3 Oct 2025 13:47:10 +0400
Subject: [PATCH 11/16] Style fix
---
.../Service/PlaceholderResolver.php | 6 +--
.../Service/Provider/ConfigProvider.php | 3 ++
.../Provider/DefaultConfigProvider.php | 2 +
.../Model/Dto/SubscriberImportOptions.php | 1 -
.../Repository/DynamicListAttrRepository.php | 12 ++---
.../Provider/CheckboxGroupValueProvider.php | 2 +-
.../Service/SubscriberCsvImporter.php | 44 ++++++++++++++-----
.../Command/ProcessQueueCommandTest.php | 4 +-
.../Service/SubscriberCsvImporterTest.php | 13 +-----
9 files changed, 53 insertions(+), 34 deletions(-)
diff --git a/src/Domain/Configuration/Service/PlaceholderResolver.php b/src/Domain/Configuration/Service/PlaceholderResolver.php
index bb269f00..e2f4c562 100644
--- a/src/Domain/Configuration/Service/PlaceholderResolver.php
+++ b/src/Domain/Configuration/Service/PlaceholderResolver.php
@@ -20,10 +20,10 @@ public function resolve(?string $input): ?string
if ($input === null || $input === '') return $input;
// Replace [TOKEN] (case-insensitive)
- return preg_replace_callback('/\[(\w+)\]/i', function ($m) {
- $key = strtoupper($m[1]);
+ return preg_replace_callback('/\[(\w+)\]/i', function ($map) {
+ $key = strtoupper($map[1]);
if (!isset($this->providers[$key])) {
- return $m[0];
+ return $map[0];
}
return (string) ($this->providers[$key])();
}, $input);
diff --git a/src/Domain/Configuration/Service/Provider/ConfigProvider.php b/src/Domain/Configuration/Service/Provider/ConfigProvider.php
index ce00f9b7..eef01788 100644
--- a/src/Domain/Configuration/Service/Provider/ConfigProvider.php
+++ b/src/Domain/Configuration/Service/Provider/ConfigProvider.php
@@ -22,6 +22,7 @@ public function __construct(
) {
}
+ /** @SuppressWarnings(PHPMD.StaticAccess) */
public function isEnabled(ConfigOption $key): bool
{
if (!in_array($key, $this->booleanValues)) {
@@ -38,6 +39,7 @@ public function isEnabled(ConfigOption $key): bool
/**
* Get configuration value by its key, from settings or default configs or default value (if provided)
+ * @SuppressWarnings(PHPMD.StaticAccess)
*/
public function getValue(ConfigOption $key): ?string
{
@@ -58,6 +60,7 @@ public function getValue(ConfigOption $key): ?string
return DefaultConfigProvider::has($key->value) ? DefaultConfigProvider::get($key->value) : null;
}
+ /** @SuppressWarnings(PHPMD.StaticAccess) */
public function getValueWithNamespace(ConfigOption $key): ?string
{
$full = $this->getValue($key);
diff --git a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
index bbb796ce..81d86e85 100644
--- a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
+++ b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
@@ -6,6 +6,7 @@
use Symfony\Contracts\Translation\TranslatorInterface;
+/** @SuppressWarnings(PHPMD.StaticAccess) */
class DefaultConfigProvider
{
/**
@@ -21,6 +22,7 @@ public static function setTranslator(TranslatorInterface $translator): void
self::$translator = $translator;
}
+ /** @SuppressWarnings(PHPMD.ExcessiveMethodLength) */
private static function init(): void
{
if (!empty(self::$defaults)) {
diff --git a/src/Domain/Subscription/Model/Dto/SubscriberImportOptions.php b/src/Domain/Subscription/Model/Dto/SubscriberImportOptions.php
index d181d757..8a180e03 100644
--- a/src/Domain/Subscription/Model/Dto/SubscriberImportOptions.php
+++ b/src/Domain/Subscription/Model/Dto/SubscriberImportOptions.php
@@ -14,7 +14,6 @@ public function __construct(
public readonly array $listIds = [],
public readonly bool $dryRun = false,
public readonly bool $skipInvalidEmail = true,
- public readonly bool $notifySubscribers = false,
) {
}
}
diff --git a/src/Domain/Subscription/Repository/DynamicListAttrRepository.php b/src/Domain/Subscription/Repository/DynamicListAttrRepository.php
index c951d5a3..1c1d23d1 100644
--- a/src/Domain/Subscription/Repository/DynamicListAttrRepository.php
+++ b/src/Domain/Subscription/Repository/DynamicListAttrRepository.php
@@ -30,13 +30,13 @@ public function fetchOptionNames(string $listTable, array $ids): array
$table = $this->prefix . 'listattr_' . $listTable;
- $qb = $this->connection->createQueryBuilder();
- $qb->select('name')
+ $queryBuilder = $this->connection->createQueryBuilder();
+ $queryBuilder->select('name')
->from($table)
->where('id IN (:ids)')
->setParameter('ids', array_map('intval', $ids), ArrayParameterType::INTEGER);
- return $qb->executeQuery()->fetchFirstColumn();
+ return $queryBuilder->executeQuery()->fetchFirstColumn();
}
public function fetchSingleOptionName(string $listTable, int $id): ?string
@@ -47,13 +47,13 @@ public function fetchSingleOptionName(string $listTable, int $id): ?string
$table = $this->prefix . 'listattr_' . $listTable;
- $qb = $this->connection->createQueryBuilder();
- $qb->select('name')
+ $queryBuilder = $this->connection->createQueryBuilder();
+ $queryBuilder->select('name')
->from($table)
->where('id = :id')
->setParameter('id', $id);
- $val = $qb->executeQuery()->fetchOne();
+ $val = $queryBuilder->executeQuery()->fetchOne();
return $val === false ? null : (string) $val;
}
diff --git a/src/Domain/Subscription/Service/Provider/CheckboxGroupValueProvider.php b/src/Domain/Subscription/Service/Provider/CheckboxGroupValueProvider.php
index 098e384e..8b2d571a 100644
--- a/src/Domain/Subscription/Service/Provider/CheckboxGroupValueProvider.php
+++ b/src/Domain/Subscription/Service/Provider/CheckboxGroupValueProvider.php
@@ -26,7 +26,7 @@ public function getValue(SubscriberAttributeDefinition $attribute, SubscriberAtt
}
$ids = array_values(array_filter(array_map(
- fn($v) => ($i = (int)trim($v)) > 0 ? $i : null,
+ fn($value) => ($index = (int)trim($value)) > 0 ? $index : null,
explode(',', $csv)
)));
diff --git a/src/Domain/Subscription/Service/SubscriberCsvImporter.php b/src/Domain/Subscription/Service/SubscriberCsvImporter.php
index 1e7c9217..bd35db3a 100644
--- a/src/Domain/Subscription/Service/SubscriberCsvImporter.php
+++ b/src/Domain/Subscription/Service/SubscriberCsvImporter.php
@@ -151,21 +151,17 @@ private function processRow(
SubscriberImportOptions $options,
array &$stats,
): void {
- if (!filter_var($dto->email, FILTER_VALIDATE_EMAIL)) {
- if ($options->skipInvalidEmail) {
- $stats['skipped']++;
- return;
- } else {
- $dto->email = 'invalid_' . $dto->email;
- $dto->sendConfirmation = false;
- }
+ if ($this->handleInvalidEmail($dto, $options, $stats)) {
+ return;
}
- $subscriber = $this->subscriberRepository->findOneByEmail($dto->email);
+ $subscriber = $this->subscriberRepository->findOneByEmail($dto->email);
if ($subscriber && !$options->updateExisting) {
$stats['skipped']++;
+
return;
}
+
if ($subscriber) {
$this->subscriberManager->updateFromImport($subscriber, $dto);
$stats['updated']++;
@@ -186,9 +182,37 @@ private function processRow(
}
}
+ $this->handleFlushAndEmail($subscriber, $options,$dto, $addedNewSubscriberToList);
+ }
+
+ private function handleInvalidEmail(
+ ImportSubscriberDto $dto,
+ SubscriberImportOptions $options,
+ array &$stats
+ ): bool {
+ if (!filter_var($dto->email, FILTER_VALIDATE_EMAIL)) {
+ if ($options->skipInvalidEmail) {
+ $stats['skipped']++;
+
+ return true;
+ }
+ // todo: check
+ $dto->email = 'invalid_' . $dto->email;
+ $dto->sendConfirmation = false;
+ }
+
+ return false;
+ }
+
+ private function handleFlushAndEmail(
+ Subscriber $subscriber,
+ SubscriberImportOptions $options,
+ ImportSubscriberDto $dto,
+ bool $addedNewSubscriberToList
+ ): void {
if (!$options->dryRun) {
$this->entityManager->flush();
- if ($options->notifySubscribers && $addedNewSubscriberToList) {
+ if ($dto->sendConfirmation && $addedNewSubscriberToList) {
$this->sendSubscribeEmail($subscriber, $options->listIds);
}
}
diff --git a/tests/Unit/Domain/Messaging/Command/ProcessQueueCommandTest.php b/tests/Unit/Domain/Messaging/Command/ProcessQueueCommandTest.php
index d8e837ba..5cd84c5e 100644
--- a/tests/Unit/Domain/Messaging/Command/ProcessQueueCommandTest.php
+++ b/tests/Unit/Domain/Messaging/Command/ProcessQueueCommandTest.php
@@ -5,7 +5,7 @@
namespace PhpList\Core\Tests\Unit\Domain\Messaging\Command;
use Exception;
-use PhpList\Core\Domain\Configuration\Service\Manager\ConfigManager;
+use PhpList\Core\Domain\Configuration\Service\Provider\ConfigProvider;
use PhpList\Core\Domain\Messaging\Command\ProcessQueueCommand;
use PhpList\Core\Domain\Messaging\Model\Message;
use PhpList\Core\Domain\Messaging\Repository\MessageRepository;
@@ -46,7 +46,7 @@ protected function setUp(): void
lockFactory: $lockFactory,
messagePreparator: $this->messageProcessingPreparator,
campaignProcessor: $this->campaignProcessor,
- configManager: $this->createMock(ConfigManager::class),
+ configProvider: $this->createMock(ConfigProvider::class),
translator: $this->translator,
);
diff --git a/tests/Unit/Domain/Subscription/Service/SubscriberCsvImporterTest.php b/tests/Unit/Domain/Subscription/Service/SubscriberCsvImporterTest.php
index af387ce9..1453cfa2 100644
--- a/tests/Unit/Domain/Subscription/Service/SubscriberCsvImporterTest.php
+++ b/tests/Unit/Domain/Subscription/Service/SubscriberCsvImporterTest.php
@@ -11,10 +11,6 @@
use PhpList\Core\Domain\Subscription\Model\SubscriberAttributeDefinition;
use PhpList\Core\Domain\Subscription\Repository\SubscriberAttributeDefinitionRepository;
use PhpList\Core\Domain\Subscription\Repository\SubscriberRepository;
-use PhpList\Core\Domain\Configuration\Model\ConfigOption;
-use PhpList\Core\Domain\Configuration\Service\Provider\ConfigProvider;
-use PhpList\Core\Domain\Messaging\Service\EmailService;
-use PhpList\Core\Domain\Subscription\Repository\SubscriberListRepository;
use PhpList\Core\Domain\Subscription\Service\CsvImporter;
use PhpList\Core\Domain\Subscription\Service\Manager\SubscriberAttributeManager;
use PhpList\Core\Domain\Subscription\Service\Manager\SubscriberManager;
@@ -23,6 +19,7 @@
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\File\UploadedFile;
+use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Translation\Translator;
class SubscriberCsvImporterTest extends TestCase
@@ -43,10 +40,6 @@ protected function setUp(): void
$this->csvImporterMock = $this->createMock(CsvImporter::class);
$this->attributeDefinitionRepositoryMock = $this->createMock(SubscriberAttributeDefinitionRepository::class);
$entityManager = $this->createMock(EntityManagerInterface::class);
- $configProvider = $this->createMock(ConfigProvider::class);
- $emailService = $this->createMock(EmailService::class);
- $subscriberListRepository = $this->createMock(SubscriberListRepository::class);
- $configProvider->method('isEnabled')->with(ConfigOption::SendSubscribeMessage)->willReturn(false);
$this->subject = new SubscriberCsvImporter(
subscriberManager: $this->subscriberManagerMock,
@@ -57,9 +50,7 @@ protected function setUp(): void
attrDefinitionRepository: $this->attributeDefinitionRepositoryMock,
entityManager: $entityManager,
translator: new Translator('en'),
- emailService: $emailService,
- configProvider: $configProvider,
- subscriberListRepository: $subscriberListRepository,
+ messageBus: $this->createMock(MessageBusInterface::class),
);
}
From f9a7a3ca20d6cbe68211ad42d0575984dd7fe1ba Mon Sep 17 00:00:00 2001
From: Tatevik
Date: Mon, 6 Oct 2025 09:55:36 +0400
Subject: [PATCH 12/16] PhpCs fix
---
.../Service/LegacyUrlBuilder.php | 15 ++--
.../Service/PlaceholderResolver.php | 4 +-
.../Service/Provider/ConfigProvider.php | 6 +-
.../Provider/DefaultConfigProvider.php | 77 +++++++++++--------
.../Service/UserPersonalizer.php | 3 +-
.../Repository/DynamicListAttrRepository.php | 10 ++-
.../Provider/CheckboxGroupValueProvider.php | 19 +++--
.../Provider/SelectOrRadioValueProvider.php | 8 +-
.../Resolver/AttributeValueResolver.php | 4 +-
.../Service/SubscriberCsvImporter.php | 5 +-
10 files changed, 94 insertions(+), 57 deletions(-)
diff --git a/src/Domain/Configuration/Service/LegacyUrlBuilder.php b/src/Domain/Configuration/Service/LegacyUrlBuilder.php
index 107f236c..4bc6366f 100644
--- a/src/Domain/Configuration/Service/LegacyUrlBuilder.php
+++ b/src/Domain/Configuration/Service/LegacyUrlBuilder.php
@@ -17,14 +17,13 @@ public function withUid(string $baseUrl, string $uid): string
$parts['query'] = http_build_query($query);
- // rebuild url
- $scheme = $parts['scheme'] ?? 'https';
- $host = $parts['host'] ?? '';
- $port = isset($parts['port']) ? ':'.$parts['port'] : '';
- $path = $parts['path'] ?? '';
- $queryStr = $parts['query'] ? '?'.$parts['query'] : '';
- $frag = isset($parts['fragment']) ? '#'.$parts['fragment'] : '';
+ $scheme = $parts['scheme'] ?? 'https';
+ $host = $parts['host'] ?? '';
+ $port = isset($parts['port']) ? ':' . $parts['port'] : '';
+ $path = $parts['path'] ?? '';
+ $queryStr = $parts['query'] ? '?' . $parts['query'] : '';
+ $frag = isset($parts['fragment']) ? '#' . $parts['fragment'] : '';
- return "{$scheme}://{$host}{$port}{$path}{$queryStr}{$frag}";
+ return $scheme . '://' . $host . $port . $path . $queryStr . $frag;
}
}
diff --git a/src/Domain/Configuration/Service/PlaceholderResolver.php b/src/Domain/Configuration/Service/PlaceholderResolver.php
index e2f4c562..3a0a3464 100644
--- a/src/Domain/Configuration/Service/PlaceholderResolver.php
+++ b/src/Domain/Configuration/Service/PlaceholderResolver.php
@@ -17,7 +17,9 @@ public function register(string $token, callable $provider): void
public function resolve(?string $input): ?string
{
- if ($input === null || $input === '') return $input;
+ if ($input === null || $input === '') {
+ return $input;
+ }
// Replace [TOKEN] (case-insensitive)
return preg_replace_callback('/\[(\w+)\]/i', function ($map) {
diff --git a/src/Domain/Configuration/Service/Provider/ConfigProvider.php b/src/Domain/Configuration/Service/Provider/ConfigProvider.php
index eef01788..4a97b784 100644
--- a/src/Domain/Configuration/Service/Provider/ConfigProvider.php
+++ b/src/Domain/Configuration/Service/Provider/ConfigProvider.php
@@ -22,7 +22,10 @@ public function __construct(
) {
}
- /** @SuppressWarnings(PHPMD.StaticAccess) */
+ /**
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ * @throws InvalidArgumentException
+ */
public function isEnabled(ConfigOption $key): bool
{
if (!in_array($key, $this->booleanValues)) {
@@ -40,6 +43,7 @@ public function isEnabled(ConfigOption $key): bool
/**
* Get configuration value by its key, from settings or default configs or default value (if provided)
* @SuppressWarnings(PHPMD.StaticAccess)
+ * @throws InvalidArgumentException
*/
public function getValue(ConfigOption $key): ?string
{
diff --git a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
index 81d86e85..ca11617f 100644
--- a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
+++ b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
@@ -6,6 +6,7 @@
use Symfony\Contracts\Translation\TranslatorInterface;
+// phpcs:disable Generic.Files.LineLength
/** @SuppressWarnings(PHPMD.StaticAccess) */
class DefaultConfigProvider
{
@@ -87,7 +88,9 @@ private static function init(): void
],
'admin_addresses' => [
'value' => '',
- 'description' => self::$translator->trans('List of email addresses to CC in system messages (separate by commas)'),
+ 'description' => self::$translator->trans(
+ 'List of email addresses to CC in system messages (separate by commas)'
+ ),
'type' => 'emaillist',
'allowempty' => true,
'category' => 'reporting',
@@ -121,7 +124,7 @@ private static function init(): void
'category' => 'campaign',
],
'analytic_tracker' => [
- 'values' => array('google' => 'Google Analytics', 'matomo' => 'Matomo'),
+ 'values' => ['google' => 'Google Analytics', 'matomo' => 'Matomo'],
'value' => 'google',
'description' => self::$translator->trans('Analytics tracking code to add to campaign URLs'),
'type' => 'select',
@@ -130,7 +133,9 @@ private static function init(): void
],
'report_address' => [
'value' => 'listreports@[DOMAIN]',
- 'description' => self::$translator->trans('Who gets the reports (email address, separate multiple emails with a comma)'),
+ 'description' => self::$translator->trans(
+ 'Who gets the reports (email address, separate multiple emails with a comma)'
+ ),
'type' => 'emaillist',
'allowempty' => true,
'category' => 'reporting',
@@ -221,54 +226,54 @@ private static function init(): void
'description' => self::$translator->trans('The HTML wrapper template for system messages'),
'type' => 'integer',
'min' => 0,
- 'max' => 999, // or max(id) from template
+ 'max' => 999,
'allowempty' => true,
'category' => 'transactional',
],
'subscribeurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=subscribe",
+ 'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=subscribe',
'description' => self::$translator->trans('URL where subscribers can sign up'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
],
'unsubscribeurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=unsubscribe",
+ 'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=unsubscribe',
'description' => self::$translator->trans('URL where subscribers can unsubscribe'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
],
'blacklisturl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=donotsend",
+ 'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=donotsend',
'description' => self::$translator->trans('URL where unknown users can unsubscribe (do-not-send-list)'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
],
'confirmationurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=confirm",
+ 'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=confirm',
'description' => self::$translator->trans('URL where subscribers have to confirm their subscription'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'preferencesurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=preferences",
+ 'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=preferences',
'description' => self::$translator->trans('URL where subscribers can update their details'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'forwardurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=forward",
+ 'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=forward',
'description' => self::$translator->trans('URL for forwarding messages'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'vcardurl' => [
- 'value' => $publicSchema."://[WEBSITE]$pageRoot/?p=vcard",
+ 'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=vcard',
'description' => self::$translator->trans('URL for downloading vcf card'),
'type' => 'text',
'allowempty' => 0,
@@ -283,15 +288,16 @@ private static function init(): void
],
'subscribesubject' => [
'value' => self::$translator->trans('Request for confirmation'),
- 'description' => self::$translator->trans('Subject of the message subscribers receive when they sign up'),
+ 'description' => self::$translator->trans(
+ 'Subject of the message subscribers receive when they sign up'
+ ),
'infoicon' => true,
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
],
'subscribemessage' => [
- 'value' =>
- ' You have been subscribed to the following newsletters:
+ 'value' => ' You have been subscribed to the following newsletters:
[LISTS]
@@ -317,14 +323,15 @@ private static function init(): void
],
'unsubscribesubject' => [
'value' => self::$translator->trans('Goodbye from our Newsletter'),
- 'description' => self::$translator->trans('Subject of the message subscribers receive when they unsubscribe'),
+ 'description' => self::$translator->trans(
+ 'Subject of the message subscribers receive when they unsubscribe'
+ ),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
],
'unsubscribemessage' => [
- 'value' =>
- 'Goodbye from our Newsletter, sorry to see you go.
+ 'value' => 'Goodbye from our Newsletter, sorry to see you go.
You have been unsubscribed from our newsletters.
@@ -343,14 +350,15 @@ private static function init(): void
],
'confirmationsubject' => [
'value' => self::$translator->trans('Welcome to our Newsletter'),
- 'description' => self::$translator->trans('Subject of the message subscribers receive after confirming their email address'),
+ 'description' => self::$translator->trans(
+ 'Subject of the message subscribers receive after confirming their email address'
+ ),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
],
'confirmationmessage' => [
- 'value' =>
- 'Welcome to our Newsletter
+ 'value' => 'Welcome to our Newsletter
Please keep this message for later reference.
@@ -362,14 +370,18 @@ private static function init(): void
Thank you'
,
- 'description' => self::$translator->trans('Message subscribers receive after confirming their email address'),
+ 'description' => self::$translator->trans(
+ 'Message subscribers receive after confirming their email address'
+ ),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
],
'updatesubject' => [
'value' => self::$translator->trans('[notify] Change of List-Membership details'),
- 'description' => self::$translator->trans('Subject of the message subscribers receive when they have changed their details'),
+ 'description' => self::$translator->trans(
+ 'Subject of the message subscribers receive when they have changed their details'
+ ),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
@@ -379,8 +391,7 @@ private static function init(): void
// confirmationinfo is replaced by one of the options below
// userdata is replaced by the information in the database
'updatemessage' => [
- 'value' =>
- 'This message is to inform you of a change of your details on our newsletter database
+ 'value' => 'This message is to inform you of a change of your details on our newsletter database
You are currently member of the following newsletters:
@@ -398,7 +409,9 @@ private static function init(): void
Thank you'
,
- 'description' => self::$translator->trans('Message subscribers receive when they have changed their details'),
+ 'description' => self::$translator->trans(
+ 'Message subscribers receive when they have changed their details'
+ ),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
@@ -423,8 +436,7 @@ private static function init(): void
// message, in case the email is sent to their old email address and they have changed
// their email address
'emailchanged_text_oldaddress' => [
- 'value' =>
- 'Please Note: when updating your details, your email address has changed.
+ 'value' => 'Please Note: when updating your details, your email address has changed.
A message has been sent to your new email address with a URL
to confirm this change. Please visit this website to activate
@@ -437,7 +449,9 @@ private static function init(): void
],
'personallocation_subject' => [
'value' => self::$translator->trans('Your personal location'),
- 'description' => self::$translator->trans('Subject of message when subscribers request their personal location'),
+ 'description' => self::$translator->trans(
+ 'Subject of message when subscribers request their personal location'
+ ),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
@@ -473,8 +487,7 @@ private static function init(): void
'category' => 'campaign',
],
'personallocation_message' => [
- 'value' =>
- 'You have requested your personal location to update your details from our website.
+ 'value' => 'You have requested your personal location to update your details from our website.
The location is below. Please make sure that you use the full line as mentioned below.
Sometimes email programmes can wrap the line into multiple lines.
@@ -490,7 +503,9 @@ private static function init(): void
],
'remoteurl_append' => [
'value' => '',
- 'description' => self::$translator->trans('String to always append to remote URL when using send-a-webpage'),
+ 'description' => self::$translator->trans(
+ 'String to always append to remote URL when using send-a-webpage'
+ ),
'type' => 'text',
'allowempty' => true,
'category' => 'campaign',
diff --git a/src/Domain/Configuration/Service/UserPersonalizer.php b/src/Domain/Configuration/Service/UserPersonalizer.php
index c7f55d4f..7aedf1d8 100644
--- a/src/Domain/Configuration/Service/UserPersonalizer.php
+++ b/src/Domain/Configuration/Service/UserPersonalizer.php
@@ -20,7 +20,8 @@ public function __construct(
private readonly SubscriberRepository $subscriberRepository,
private readonly SubscriberAttributeValueRepository $attributesRepository,
private readonly AttributeValueResolver $attributeValueResolver
- ) {}
+ ) {
+ }
public function personalize(string $value, string $email): string
{
diff --git a/src/Domain/Subscription/Repository/DynamicListAttrRepository.php b/src/Domain/Subscription/Repository/DynamicListAttrRepository.php
index 1c1d23d1..d01ab916 100644
--- a/src/Domain/Subscription/Repository/DynamicListAttrRepository.php
+++ b/src/Domain/Subscription/Repository/DynamicListAttrRepository.php
@@ -8,21 +8,25 @@
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use InvalidArgumentException;
+use PhpList\Core\Domain\Common\Model\Interfaces\DomainModel;
class DynamicListAttrRepository
{
public function __construct(
private readonly Connection $connection,
private readonly string $prefix = 'phplist_'
- ) {}
+ ) {
+ }
/**
* @return list
- * @throws Exception
+ * @throws InvalidArgumentException
*/
public function fetchOptionNames(string $listTable, array $ids): array
{
- if (empty($ids)) return [];
+ if (empty($ids)) {
+ return [];
+ }
if (!preg_match('/^[A-Za-z0-9_]+$/', $listTable)) {
throw new InvalidArgumentException('Invalid list table');
diff --git a/src/Domain/Subscription/Service/Provider/CheckboxGroupValueProvider.php b/src/Domain/Subscription/Service/Provider/CheckboxGroupValueProvider.php
index 8b2d571a..3b33f629 100644
--- a/src/Domain/Subscription/Service/Provider/CheckboxGroupValueProvider.php
+++ b/src/Domain/Subscription/Service/Provider/CheckboxGroupValueProvider.php
@@ -10,11 +10,14 @@
class CheckboxGroupValueProvider implements AttributeValueProvider
{
- public function __construct(private DynamicListAttrRepository $repo) {}
+ public function __construct(private readonly DynamicListAttrRepository $repo)
+ {
+ }
public function supports(SubscriberAttributeDefinition $attribute): bool
{
- // todo: check what real types exist in the database
+ // phpcs:ignore Generic.Commenting.Todo
+ // @todo: check what real types exist in the database
return $attribute->getType() === 'checkboxgroup';
}
@@ -25,12 +28,14 @@ public function getValue(SubscriberAttributeDefinition $attribute, SubscriberAtt
return '';
}
- $ids = array_values(array_filter(array_map(
- fn($value) => ($index = (int)trim($value)) > 0 ? $index : null,
- explode(',', $csv)
- )));
+ $ids = array_values(array_filter(array_map(function ($value) {
+ $index = (int) trim($value);
+ return $index > 0 ? $index : null;
+ }, explode(',', $csv))));
- if (empty($ids) || !$attribute->getTableName()) return '';
+ if (empty($ids) || !$attribute->getTableName()) {
+ return '';
+ }
$names = $this->repo->fetchOptionNames($attribute->getTableName(), $ids);
diff --git a/src/Domain/Subscription/Service/Provider/SelectOrRadioValueProvider.php b/src/Domain/Subscription/Service/Provider/SelectOrRadioValueProvider.php
index 7e4d8fc0..22b3ab4e 100644
--- a/src/Domain/Subscription/Service/Provider/SelectOrRadioValueProvider.php
+++ b/src/Domain/Subscription/Service/Provider/SelectOrRadioValueProvider.php
@@ -10,7 +10,9 @@
class SelectOrRadioValueProvider implements AttributeValueProvider
{
- public function __construct(private readonly DynamicListAttrRepository $repo) {}
+ public function __construct(private readonly DynamicListAttrRepository $repo)
+ {
+ }
public function supports(SubscriberAttributeDefinition $attribute): bool
{
@@ -19,7 +21,9 @@ public function supports(SubscriberAttributeDefinition $attribute): bool
public function getValue(SubscriberAttributeDefinition $attribute, SubscriberAttributeValue $userValue): string
{
- if (!$attribute->getTableName()) return '';
+ if (!$attribute->getTableName()) {
+ return '';
+ }
$id = (int)($userValue->getValue() ?? 0);
if ($id <= 0) {
diff --git a/src/Domain/Subscription/Service/Resolver/AttributeValueResolver.php b/src/Domain/Subscription/Service/Resolver/AttributeValueResolver.php
index 4edf42d1..c63b7f8c 100644
--- a/src/Domain/Subscription/Service/Resolver/AttributeValueResolver.php
+++ b/src/Domain/Subscription/Service/Resolver/AttributeValueResolver.php
@@ -10,7 +10,9 @@
class AttributeValueResolver
{
/** @param iterable $providers */
- public function __construct(private readonly iterable $providers) {}
+ public function __construct(private readonly iterable $providers)
+ {
+ }
public function resolve(SubscriberAttributeValue $userAttr): string
{
diff --git a/src/Domain/Subscription/Service/SubscriberCsvImporter.php b/src/Domain/Subscription/Service/SubscriberCsvImporter.php
index bd35db3a..f5d9e535 100644
--- a/src/Domain/Subscription/Service/SubscriberCsvImporter.php
+++ b/src/Domain/Subscription/Service/SubscriberCsvImporter.php
@@ -182,7 +182,7 @@ private function processRow(
}
}
- $this->handleFlushAndEmail($subscriber, $options,$dto, $addedNewSubscriberToList);
+ $this->handleFlushAndEmail($subscriber, $options, $dto, $addedNewSubscriberToList);
}
private function handleInvalidEmail(
@@ -196,7 +196,8 @@ private function handleInvalidEmail(
return true;
}
- // todo: check
+ // phpcs:ignore Generic.Commenting.Todo
+ // @todo: check
$dto->email = 'invalid_' . $dto->email;
$dto->sendConfirmation = false;
}
From b0caf80b0827200c4d4356801c3ad8e515a36816 Mon Sep 17 00:00:00 2001
From: Tatevik
Date: Mon, 6 Oct 2025 10:53:38 +0400
Subject: [PATCH 13/16] Fix configs
---
config/parameters.yml.dist | 2 +
config/services/providers.yml | 15 +-
config/services/repositories.yml | 3 +-
config/services/services.yml | 6 +
.../Repository/ConfigRepository.php | 2 +-
.../Service/Provider/ConfigProvider.php | 7 +-
.../Provider/DefaultConfigProvider.php | 157 +++++++++---------
.../Repository/DynamicListAttrRepository.php | 2 -
.../SubscriberCsvImportManagerTest.php | 6 +-
9 files changed, 108 insertions(+), 92 deletions(-)
diff --git a/config/parameters.yml.dist b/config/parameters.yml.dist
index fb2ce8ee..4e9e0cff 100644
--- a/config/parameters.yml.dist
+++ b/config/parameters.yml.dist
@@ -21,6 +21,8 @@ parameters:
env(PHPLIST_DATABASE_USER): 'phplist'
database_password: '%%env(PHPLIST_DATABASE_PASSWORD)%%'
env(PHPLIST_DATABASE_PASSWORD): 'phplist'
+ database_prefix: '%%env(DATABASE_PREFIX)%%'
+ env(DATABASE_PREFIX): 'phplist_'
# Email configuration
app.mailer_from: '%%env(MAILER_FROM)%%'
diff --git a/config/services/providers.yml b/config/services/providers.yml
index 45436651..f4f06010 100644
--- a/config/services/providers.yml
+++ b/config/services/providers.yml
@@ -13,12 +13,17 @@ services:
arguments:
$confPath: '%app.phplist_isp_conf_path%'
- PhpList\Core\Domain\Subscription\Service\Provider\CheckboxGroupValueProvider: ~
- PhpList\Core\Domain\Subscription\Service\Provider\SelectOrRadioValueProvider: ~
- PhpList\Core\Domain\Subscription\Service\Provider\ScalarValueProvider: ~
+ PhpList\Core\Domain\Subscription\Service\Provider\CheckboxGroupValueProvider:
+ autowire: true
+ PhpList\Core\Domain\Subscription\Service\Provider\SelectOrRadioValueProvider:
+ autowire: true
+ PhpList\Core\Domain\Subscription\Service\Provider\ScalarValueProvider:
+ autowire: true
PhpList\Core\Domain\Configuration\Service\Provider\DefaultConfigProvider:
- calls:
- - [ setTranslator, [ '@translator' ] ]
+ autowire: true
PhpList\Core\Domain\Configuration\Service\Provider\ConfigProvider:
+ autowire: true
+ arguments:
+ $cache: '@Psr\SimpleCache\CacheInterface'
diff --git a/config/services/repositories.yml b/config/services/repositories.yml
index ac5b50a9..e9d4d8c6 100644
--- a/config/services/repositories.yml
+++ b/config/services/repositories.yml
@@ -68,8 +68,9 @@ services:
arguments:
- PhpList\Core\Domain\Subscription\Model\Subscription
PhpList\Core\Domain\Subscription\Repository\DynamicListAttrRepository:
+ autowire: true
arguments:
- $prefix: '%env(default:phplist_ DATABASE_PREFIX)%'
+ $prefix: '%database_prefix%'
PhpList\Core\Domain\Subscription\Repository\SubscriberHistoryRepository:
parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
arguments:
diff --git a/config/services/services.yml b/config/services/services.yml
index d33ddd2c..bc236399 100644
--- a/config/services/services.yml
+++ b/config/services/services.yml
@@ -132,3 +132,9 @@ services:
PhpList\Core\Domain\Configuration\Service\LegacyUrlBuilder:
autowire: true
autoconfigure: true
+
+ cache.app.simple:
+ class: Symfony\Component\Cache\Psr16Cache
+ arguments: [ '@cache.app' ]
+
+ Psr\SimpleCache\CacheInterface: '@cache.app.simple'
diff --git a/src/Domain/Configuration/Repository/ConfigRepository.php b/src/Domain/Configuration/Repository/ConfigRepository.php
index 960b14f3..ea4a0680 100644
--- a/src/Domain/Configuration/Repository/ConfigRepository.php
+++ b/src/Domain/Configuration/Repository/ConfigRepository.php
@@ -10,6 +10,6 @@ class ConfigRepository extends AbstractRepository
{
public function findValueByItem(string $name): ?string
{
- return $this->findOneBy(['item' => $name])?->getValue();
+ return $this->findOneBy(['key' => $name])?->getValue();
}
}
diff --git a/src/Domain/Configuration/Service/Provider/ConfigProvider.php b/src/Domain/Configuration/Service/Provider/ConfigProvider.php
index 4a97b784..c47da111 100644
--- a/src/Domain/Configuration/Service/Provider/ConfigProvider.php
+++ b/src/Domain/Configuration/Service/Provider/ConfigProvider.php
@@ -18,7 +18,8 @@ class ConfigProvider
public function __construct(
private readonly ConfigRepository $configRepository,
private readonly CacheInterface $cache,
- private readonly int $ttlSeconds = 300
+ private readonly DefaultConfigProvider $defaultConfigs,
+ private readonly ?int $ttlSeconds = 300
) {
}
@@ -37,7 +38,7 @@ public function isEnabled(ConfigOption $key): bool
$config->getValue() === '1';
}
- return DefaultConfigProvider::has($key->value) && DefaultConfigProvider::get($key->value) === '1';
+ return $this->defaultConfigs->has($key->value) && $this->defaultConfigs->get($key->value)['value'] === '1';
}
/**
@@ -61,7 +62,7 @@ public function getValue(ConfigOption $key): ?string
return $value;
}
- return DefaultConfigProvider::has($key->value) ? DefaultConfigProvider::get($key->value) : null;
+ return $this->defaultConfigs->has($key->value) ? $this->defaultConfigs->get($key->value)['value'] : null;
}
/** @SuppressWarnings(PHPMD.StaticAccess) */
diff --git a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
index ca11617f..28035d0a 100644
--- a/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
+++ b/src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
@@ -14,36 +14,33 @@ class DefaultConfigProvider
* Holds all default configuration values
* @var array
*/
- private static array $defaults = [];
+ private array $defaults = [];
- private static TranslatorInterface $translator;
-
- public static function setTranslator(TranslatorInterface $translator): void
+ public function __construct(private readonly TranslatorInterface $translator)
{
- self::$translator = $translator;
}
/** @SuppressWarnings(PHPMD.ExcessiveMethodLength) */
- private static function init(): void
+ private function init(): void
{
- if (!empty(self::$defaults)) {
+ if (!empty($this->defaults)) {
return;
}
$publicSchema = 'http';
$pageRoot = '/api/v2';
- self::$defaults = [
+ $this->defaults = [
'admin_address' => [
'value' => 'webmaster@[DOMAIN]',
- 'description' => self::$translator->trans('Person in charge of this system (one email address)'),
+ 'description' => $this->translator->trans('Person in charge of this system (one email address)'),
'type' => 'email',
'allowempty' => false,
'category' => 'general',
],
'organisation_name' => [
'value' => '',
- 'description' => self::$translator->trans('Name of the organisation'),
+ 'description' => $this->translator->trans('Name of the organisation'),
'type' => 'text',
'allowempty' => true,
'allowtags' => '
',
@@ -52,7 +49,7 @@ private static function init(): void
],
'organisation_logo' => [
'value' => '',
- 'description' => self::$translator->trans('Logo of the organisation'),
+ 'description' => $this->translator->trans('Logo of the organisation'),
'infoicon' => true,
'type' => 'image',
'allowempty' => true,
@@ -60,7 +57,7 @@ private static function init(): void
],
'date_format' => [
'value' => 'j F Y',
- 'description' => self::$translator->trans('Date format'),
+ 'description' => $this->translator->trans('Date format'),
'infoicon' => true,
'type' => 'text',
'allowempty' => false,
@@ -68,27 +65,27 @@ private static function init(): void
],
'rc_notification' => [
'value' => 0,
- 'description' => self::$translator->trans('Show notification for Release Candidates'),
+ 'description' => $this->translator->trans('Show notification for Release Candidates'),
'type' => 'boolean',
'allowempty' => true,
'category' => 'security',
],
'remote_processing_secret' => [
'value' => bin2hex(random_bytes(10)),
- 'description' => self::$translator->trans('Secret for remote processing'),
+ 'description' => $this->translator->trans('Secret for remote processing'),
'type' => 'text',
'category' => 'security',
],
'notify_admin_login' => [
'value' => 1,
- 'description' => self::$translator->trans('Notify admin on login from new location'),
+ 'description' => $this->translator->trans('Notify admin on login from new location'),
'type' => 'boolean',
'category' => 'security',
'allowempty' => true,
],
'admin_addresses' => [
'value' => '',
- 'description' => self::$translator->trans(
+ 'description' => $this->translator->trans(
'List of email addresses to CC in system messages (separate by commas)'
),
'type' => 'emaillist',
@@ -97,28 +94,28 @@ private static function init(): void
],
'campaignfrom_default' => [
'value' => '',
- 'description' => self::$translator->trans("Default for 'From:' in a campaign"),
+ 'description' => $this->translator->trans("Default for 'From:' in a campaign"),
'type' => 'text',
'allowempty' => true,
'category' => 'campaign',
],
'notifystart_default' => [
'value' => '',
- 'description' => self::$translator->trans("Default for 'address to alert when sending starts'"),
+ 'description' => $this->translator->trans("Default for 'address to alert when sending starts'"),
'type' => 'email',
'allowempty' => true,
'category' => 'campaign',
],
'notifyend_default' => [
'value' => '',
- 'description' => self::$translator->trans("Default for 'address to alert when sending finishes'"),
+ 'description' => $this->translator->trans("Default for 'address to alert when sending finishes'"),
'type' => 'email',
'allowempty' => true,
'category' => 'campaign',
],
'always_add_googletracking' => [
'value' => '0',
- 'description' => self::$translator->trans('Always add analytics tracking code to campaigns'),
+ 'description' => $this->translator->trans('Always add analytics tracking code to campaigns'),
'type' => 'boolean',
'allowempty' => true,
'category' => 'campaign',
@@ -126,14 +123,14 @@ private static function init(): void
'analytic_tracker' => [
'values' => ['google' => 'Google Analytics', 'matomo' => 'Matomo'],
'value' => 'google',
- 'description' => self::$translator->trans('Analytics tracking code to add to campaign URLs'),
+ 'description' => $this->translator->trans('Analytics tracking code to add to campaign URLs'),
'type' => 'select',
'allowempty' => false,
'category' => 'campaign',
],
'report_address' => [
'value' => 'listreports@[DOMAIN]',
- 'description' => self::$translator->trans(
+ 'description' => $this->translator->trans(
'Who gets the reports (email address, separate multiple emails with a comma)'
),
'type' => 'emaillist',
@@ -142,35 +139,35 @@ private static function init(): void
],
'message_from_address' => [
'value' => 'noreply@[DOMAIN]',
- 'description' => self::$translator->trans('From email address for system messages'),
+ 'description' => $this->translator->trans('From email address for system messages'),
'type' => 'email',
'allowempty' => 0,
'category' => 'transactional',
],
'message_from_name' => [
- 'value' => self::$translator->trans('Webmaster'),
- 'description' => self::$translator->trans('Name for system messages'),
+ 'value' => $this->translator->trans('Webmaster'),
+ 'description' => $this->translator->trans('Name for system messages'),
'type' => 'text',
'allowempty' => 0,
'category' => 'transactional',
],
'message_replyto_address' => [
'value' => 'noreply@[DOMAIN]',
- 'description' => self::$translator->trans('Reply-to email address for system messages'),
+ 'description' => $this->translator->trans('Reply-to email address for system messages'),
'type' => 'email',
'allowempty' => 0,
'category' => 'transactional',
],
'hide_single_list' => [
'value' => '1',
- 'description' => self::$translator->trans('If there is only one visible list, should it be hidden in the page and automatically subscribe users who sign up'),
+ 'description' => $this->translator->trans('If there is only one visible list, should it be hidden in the page and automatically subscribe users who sign up'),
'type' => 'boolean',
'allowempty' => true,
'category' => 'subscription-ui',
],
'list_categories' => [
'value' => '',
- 'description' => self::$translator->trans('Categories for lists. Separate with commas.'),
+ 'description' => $this->translator->trans('Categories for lists. Separate with commas.'),
'infoicon' => true,
'type' => 'text',
'allowempty' => true,
@@ -178,14 +175,14 @@ private static function init(): void
],
'displaycategories' => [
'value' => 0,
- 'description' => self::$translator->trans('Display list categories on subscribe page'),
+ 'description' => $this->translator->trans('Display list categories on subscribe page'),
'type' => 'boolean',
'allowempty' => false,
'category' => 'list-organisation',
],
'textline_width' => [
'value' => '40',
- 'description' => self::$translator->trans('Width of a textline field (numerical)'),
+ 'description' => $this->translator->trans('Width of a textline field (numerical)'),
'type' => 'integer',
'min' => 20,
'max' => 150,
@@ -193,21 +190,21 @@ private static function init(): void
],
'textarea_dimensions' => [
'value' => '10,40',
- 'description' => self::$translator->trans('Dimensions of a textarea field (rows,columns)'),
+ 'description' => $this->translator->trans('Dimensions of a textarea field (rows,columns)'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription-ui',
],
'send_admin_copies' => [
'value' => '0',
- 'description' => self::$translator->trans('Send notifications about subscribe, update and unsubscribe'),
+ 'description' => $this->translator->trans('Send notifications about subscribe, update and unsubscribe'),
'type' => 'boolean',
'allowempty' => true,
'category' => 'reporting',
],
'defaultsubscribepage' => [
'value' => 1,
- 'description' => self::$translator->trans('The default subscribe page when there are multiple'),
+ 'description' => $this->translator->trans('The default subscribe page when there are multiple'),
'type' => 'integer',
'min' => 1,
'max' => 999,
@@ -216,14 +213,14 @@ private static function init(): void
],
'defaultmessagetemplate' => [
'value' => 0,
- 'description' => self::$translator->trans('The default HTML template to use when sending a message'),
+ 'description' => $this->translator->trans('The default HTML template to use when sending a message'),
'type' => 'text',
'allowempty' => true,
'category' => 'campaign',
],
'systemmessagetemplate' => [
'value' => 0,
- 'description' => self::$translator->trans('The HTML wrapper template for system messages'),
+ 'description' => $this->translator->trans('The HTML wrapper template for system messages'),
'type' => 'integer',
'min' => 0,
'max' => 999,
@@ -232,63 +229,63 @@ private static function init(): void
],
'subscribeurl' => [
'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=subscribe',
- 'description' => self::$translator->trans('URL where subscribers can sign up'),
+ 'description' => $this->translator->trans('URL where subscribers can sign up'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
],
'unsubscribeurl' => [
'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=unsubscribe',
- 'description' => self::$translator->trans('URL where subscribers can unsubscribe'),
+ 'description' => $this->translator->trans('URL where subscribers can unsubscribe'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
],
'blacklisturl' => [
'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=donotsend',
- 'description' => self::$translator->trans('URL where unknown users can unsubscribe (do-not-send-list)'),
+ 'description' => $this->translator->trans('URL where unknown users can unsubscribe (do-not-send-list)'),
'type' => 'url',
'allowempty' => 0,
'category' => 'subscription',
],
'confirmationurl' => [
'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=confirm',
- 'description' => self::$translator->trans('URL where subscribers have to confirm their subscription'),
+ 'description' => $this->translator->trans('URL where subscribers have to confirm their subscription'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'preferencesurl' => [
'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=preferences',
- 'description' => self::$translator->trans('URL where subscribers can update their details'),
+ 'description' => $this->translator->trans('URL where subscribers can update their details'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'forwardurl' => [
'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=forward',
- 'description' => self::$translator->trans('URL for forwarding messages'),
+ 'description' => $this->translator->trans('URL for forwarding messages'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'vcardurl' => [
'value' => $publicSchema . '://[WEBSITE]' . $pageRoot . '/?p=vcard',
- 'description' => self::$translator->trans('URL for downloading vcf card'),
+ 'description' => $this->translator->trans('URL for downloading vcf card'),
'type' => 'text',
'allowempty' => 0,
'category' => 'subscription',
],
'ajax_subscribeconfirmation' => [
- 'value' => self::$translator->trans('
Thanks, you have been added to our newsletter
You will receive an email to confirm your subscription. Please click the link in the email to confirm
'),
- 'description' => self::$translator->trans('Text to display when subscription with an AJAX request was successful'),
+ 'value' => $this->translator->trans('
Thanks, you have been added to our newsletter
You will receive an email to confirm your subscription. Please click the link in the email to confirm
'),
+ 'description' => $this->translator->trans('Text to display when subscription with an AJAX request was successful'),
'type' => 'textarea',
'allowempty' => true,
'category' => 'subscription',
],
'subscribesubject' => [
- 'value' => self::$translator->trans('Request for confirmation'),
- 'description' => self::$translator->trans(
+ 'value' => $this->translator->trans('Request for confirmation'),
+ 'description' => $this->translator->trans(
'Subject of the message subscribers receive when they sign up'
),
'infoicon' => true,
@@ -316,14 +313,14 @@ private static function init(): void
If this is not correct, or you do not agree, simply take no action and delete this message.'
,
- 'description' => self::$translator->trans('Message subscribers receive when they sign up'),
+ 'description' => $this->translator->trans('Message subscribers receive when they sign up'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
],
'unsubscribesubject' => [
- 'value' => self::$translator->trans('Goodbye from our Newsletter'),
- 'description' => self::$translator->trans(
+ 'value' => $this->translator->trans('Goodbye from our Newsletter'),
+ 'description' => $this->translator->trans(
'Subject of the message subscribers receive when they unsubscribe'
),
'type' => 'text',
@@ -343,14 +340,14 @@ private static function init(): void
Thank you'
,
- 'description' => self::$translator->trans('Message subscribers receive when they unsubscribe'),
+ 'description' => $this->translator->trans('Message subscribers receive when they unsubscribe'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
],
'confirmationsubject' => [
- 'value' => self::$translator->trans('Welcome to our Newsletter'),
- 'description' => self::$translator->trans(
+ 'value' => $this->translator->trans('Welcome to our Newsletter'),
+ 'description' => $this->translator->trans(
'Subject of the message subscribers receive after confirming their email address'
),
'type' => 'text',
@@ -370,7 +367,7 @@ private static function init(): void
Thank you'
,
- 'description' => self::$translator->trans(
+ 'description' => $this->translator->trans(
'Message subscribers receive after confirming their email address'
),
'type' => 'textarea',
@@ -378,8 +375,8 @@ private static function init(): void
'category' => 'transactional',
],
'updatesubject' => [
- 'value' => self::$translator->trans('[notify] Change of List-Membership details'),
- 'description' => self::$translator->trans(
+ 'value' => $this->translator->trans('[notify] Change of List-Membership details'),
+ 'description' => $this->translator->trans(
'Subject of the message subscribers receive when they have changed their details'
),
'type' => 'text',
@@ -409,7 +406,7 @@ private static function init(): void
Thank you'
,
- 'description' => self::$translator->trans(
+ 'description' => $this->translator->trans(
'Message subscribers receive when they have changed their details'
),
'type' => 'textarea',
@@ -427,7 +424,7 @@ private static function init(): void
[CONFIRMATIONURL]
',
- 'description' => self::$translator->trans('Part of the message that is sent to their new email address when subscribers change their information, and the email address has changed'),
+ 'description' => $this->translator->trans('Part of the message that is sent to their new email address when subscribers change their information, and the email address has changed'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
@@ -442,14 +439,14 @@ private static function init(): void
to confirm this change. Please visit this website to activate
your membership.'
,
- 'description' => self::$translator->trans('Part of the message that is sent to their old email address when subscribers change their information, and the email address has changed'),
+ 'description' => $this->translator->trans('Part of the message that is sent to their old email address when subscribers change their information, and the email address has changed'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
],
'personallocation_subject' => [
- 'value' => self::$translator->trans('Your personal location'),
- 'description' => self::$translator->trans(
+ 'value' => $this->translator->trans('Your personal location'),
+ 'description' => $this->translator->trans(
'Subject of message when subscribers request their personal location'
),
'type' => 'text',
@@ -467,7 +464,7 @@ private static function init(): void
',
- 'description' => self::$translator->trans('Default footer for sending a campaign'),
+ 'description' => $this->translator->trans('Default footer for sending a campaign'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'campaign',
@@ -481,7 +478,7 @@ private static function init(): void
You can also opt out completely from receiving any further email from our newsletter application, phpList.
',
- 'description' => self::$translator->trans('Footer used when a message has been forwarded'),
+ 'description' => $this->translator->trans('Footer used when a message has been forwarded'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'campaign',
@@ -496,14 +493,14 @@ private static function init(): void
Thank you.'
,
- 'description' => self::$translator->trans('Message to send when they request their personal location'),
+ 'description' => $this->translator->trans('Message to send when they request their personal location'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'transactional',
],
'remoteurl_append' => [
'value' => '',
- 'description' => self::$translator->trans(
+ 'description' => $this->translator->trans(
'String to always append to remote URL when using send-a-webpage'
),
'type' => 'text',
@@ -512,28 +509,28 @@ private static function init(): void
],
'wordwrap' => [
'value' => '75',
- 'description' => self::$translator->trans('Width for Wordwrap of Text messages'),
+ 'description' => $this->translator->trans('Width for Wordwrap of Text messages'),
'type' => 'text',
'allowempty' => true,
'category' => 'campaign',
],
'html_email_style' => [
'value' => '',
- 'description' => self::$translator->trans('CSS for HTML messages without a template'),
+ 'description' => $this->translator->trans('CSS for HTML messages without a template'),
'type' => 'textarea',
'allowempty' => true,
'category' => 'campaign',
],
'alwayssendtextto' => [
'value' => '',
- 'description' => self::$translator->trans('Domains that only accept text emails, one per line'),
+ 'description' => $this->translator->trans('Domains that only accept text emails, one per line'),
'type' => 'textarea',
'allowempty' => true,
'category' => 'campaign',
],
'tld_last_sync' => [
'value' => '0',
- 'description' => self::$translator->trans('last time TLDs were fetched'),
+ 'description' => $this->translator->trans('last time TLDs were fetched'),
'type' => 'text',
'allowempty' => true,
'category' => 'system',
@@ -541,7 +538,7 @@ private static function init(): void
],
'internet_tlds' => [
'value' => '',
- 'description' => self::$translator->trans('Top level domains'),
+ 'description' => $this->translator->trans('Top level domains'),
'type' => 'textarea',
'allowempty' => true,
'category' => 'system',
@@ -549,14 +546,14 @@ private static function init(): void
],
'pageheader' => [
'value' => '
Welcome
',
- 'description' => self::$translator->trans('Header of public pages.'),
+ 'description' => $this->translator->trans('Header of public pages.'),
'type' => 'textarea',
'allowempty' => 0,
'category' => 'subscription-ui',
],
'pagefooter' => [
'value' => '