: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
import { Component, unmountComponentAtNode } from '@wordpress/element';
import PropTypes from 'prop-types';
import { __ } from '@wordpress/i18n';
} from '@wordpress/components';
export class TriggerEmailActionComponent extends Component {
this.setStateNewValue = this.setStateNewValue.bind(this);
this.setModalOpen = this.setModalOpen.bind( this )
this.setProcessing = this.setProcessing.bind( this );
this.setSent = this.setSent.bind( this );
this.setNotSent = this.setNotSent.bind( this );
this.setEmailProcessed = this.setEmailProcessed.bind( this );
this.cancelComp = this.cancelComp.bind( this );
this.resetProcessing = this.resetProcessing.bind( this );
this.abortFetch = this.abortFetch.bind(this);
this.triggerEmailAction = this.triggerEmailAction.bind(this);
//gather props from screen
selectScreenData( this.setStateNewValue, this.props );
//Catch when all submissions have been processed to set a new process state
//Check process state to catch end of fetch tasks and display data
if ( this.state.processing ) {
typeof this.state.processing !== 'undefined' &&
this.state.emailsProcessed === this.state.submissionIds.length
//Set Process state to false without resetting data yet to have it displayed
this.setProcessing( false );
//Prepare component to cancel all subscribtions before unmounting
//Make sure all jobs are stopped
//Global state setter for states with new explicit value
setStateNewValue( stateName, newValue ) {
this.setState( { [stateName]: newValue } );
//Use a setter with an explicit name for the processing state
setProcessing( newValue ) {
this.setState( { processing: newValue } );
setModalOpen( newValue ) {
this.setState( { isModalOpen: newValue } );
// Store number of emails sent
//Check if reset process or increment
if( value == "undefined" && value === 0 ){
this.setState( { sent: -1 } );
this.setState( ( prev ) => {
return { sent: prev.sent + 1 }
//Store IDs of unsent emails
setNotSent(submissionId) {
//Check if reset process or array push
this.setState( { notSent: [] } );
const newNotSent = this.state.notSent.concat(submissionId);
this.setState( { notSent: newNotSent } );
//Store number of emails processed ( sent or not )
setEmailProcessed( value ) {
//Check if reset process or increment
if( typeof value !== "undefined" && value === 0 ){
this.setState( { emailsProcessed: 0 } );
this.setState( ( prev ) => {
return { emailsProcessed: prev.emailsProcessed + 1 }
//Reset all state to default start of resending task
this.setProcessing( false );
this.setEmailProcessed( 0 );
this.setNotSent( false );
this.props.fetchController.abort();
this.setState( { fetchAborted: true });
//Cancel emails or Remove Component via cancel button
if(this.state.processing){
this.setStateNewValue( "isModalOpen", false );
this.setProcessing( false );
document.getElementById( 'nf-trigger-emails-container' )
async triggerEmailAction() {
//Init spinner, remove button and start the proces state management
this.setProcessing( true );
//Define data needed to Fetch request
const { state, props } = this;
const restUrl = props.globalParams.restUrl;
const formID = form.formID;
const signal = props.fetchController.signal;
setNotSent: this.setNotSent,
setEmailProcessed: this.setEmailProcessed,
//Loop over each submission to trigger the email action
for ( const [ key, value ] of Object.entries( submissionIds ) ) {
await sendEmail( actionProps, value )
console.log( 'Email cancelled: ' + e.message );
this.setNotSent( value );
setAction={ this.setStateNewValue }
{ __( 'Action Selected: ', 'ninja-forms' ) }
<DisplayActionSettings value={ action } />
'No Email Action Selected',
onClick={ () => this.cancelComp() }
{ __( 'Reopen to allow resending process', 'ninja-forms' ) }
{action && !processing && !fetchAborted && (
this.triggerEmailAction()
style={ { marginRight: '1rem' } }
{ __( 'Resend ', 'ninja-forms' ) +
__( ' emails', 'ninja-forms' ) }
onClick={ () => this.setModalOpen( true ) }
{ __( 'Cancel', 'ninja-forms' ) }
action={ this.cancelComp }
actionText={ __( 'Yes', 'ninja-forms' ) }
cancel={ this.setModalOpen }
cancelText={ __( 'No', 'ninja-forms' ) }
{ processing && <Spinner /> }
{ notSent.length > 0 && (
'Emails failed to be sent for: ',
) + Object.values( notSent )
__( ' emails sent', 'ninja-forms' )
TriggerEmailActionComponent.propTypes = {
globalParams: PropTypes.object.isRequired,
triggerEmailActionsParams: PropTypes.object.isRequired,
fetchController: PropTypes.object.isRequired