! empty( $saved['enabled'] ),
'form' => isset( $saved['form'] ) ? (string) $saved['form'] : '',
'label' => isset( $saved['label'] ) ? (string) $saved['label'] : '',
);
}
/** On, with a 404 Emails form to join. */
public static function is_on() {
$settings = self::get();
return $settings['enabled'] && '' !== $settings['form'];
}
/** The box's wording: the site's own, or the standard one in the site's language. */
public static function label() {
$label = trim( self::get()['label'] );
return '' !== $label ? $label : __( 'Send me news and offers by email', '404-emails' );
}
/**
* @param mixed $raw The posted section.
* @param string[] $known_ids The workspace's 404 Emails forms.
*/
public static function save( $raw, array $known_ids ) {
$raw = is_array( $raw ) ? $raw : array();
$form = isset( $raw['form'] ) ? sanitize_text_field( (string) $raw['form'] ) : '';
$label = isset( $raw['label'] ) ? trim( sanitize_text_field( (string) $raw['label'] ) ) : '';
if ( function_exists( 'mb_substr' ) ) {
$label = mb_substr( $label, 0, self::LABEL_MAX );
}
update_option(
self::OPTION,
array(
'enabled' => ! empty( $raw['enabled'] ),
'form' => in_array( $form, $known_ids, true ) ? $form : '',
'label' => $label,
),
false
);
}
/**
* @param string $content The widget's HTML.
* @param object $widget Elementor's widget.
*/
public static function filter_widget_content( $content, $widget ) {
if ( ! is_string( $content ) || ! is_object( $widget ) || ! method_exists( $widget, 'get_name' ) || 'form' !== $widget->get_name() ) {
return $content;
}
if ( ! self::is_on() || ! function_exists( 'is_singular' ) || ! is_singular( self::EVENT_POST_TYPE ) ) {
return $content;
}
$id = method_exists( $widget, 'get_id' ) ? (string) $widget->get_id() : '';
return self::add_checkbox( $content, $id, self::label() );
}
/**
* The form's HTML with the box added: after its last tick-box, or before
* its button. Unchanged when it isn't an Elementor form or already has it.
*/
public static function add_checkbox( $html, $widget_id, $label ) {
if ( false === strpos( $html, '
]*\bclass="[^"]*\b' . preg_quote( $class, '/' ) . '\b[^"]*"/', $html, $matches, PREG_OFFSET_CAPTURE ) ) {
return null;
}
$last = end( $matches[0] );
return $last[1];
}
/** Where the
starting at $start closes (just after its
). */
private static function element_end( $html, $start ) {
$depth = 0;
if ( ! preg_match_all( '/
/i', $html, $tags, PREG_OFFSET_CAPTURE, $start ) ) {
return null;
}
foreach ( $tags[0] as $tag ) {
$depth += '' === substr( $tag[0], 0, 2 ) ? -1 : 1;
if ( 0 === $depth ) {
return $tag[1] + strlen( $tag[0] );
}
}
return null;
}
/**
* @param object $record ElementorPro\Modules\Forms\Classes\Form_Record.
* @param object $handler The Ajax handler (not used).
*/
public static function handle_record( $record, $handler = null ) {
if ( ! self::is_on() || ! Settings::is_connected() || ! is_object( $record ) || ! method_exists( $record, 'get' ) ) {
return;
}
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Elementor has already checked and accepted this submission; only the page and our own box are read.
$event_id = isset( $_POST['queried_id'] ) ? absint( wp_unslash( $_POST['queried_id'] ) ) : 0;
$ticked = isset( $_POST['form_fields'][ self::FIELD ] ) ? sanitize_text_field( wp_unslash( $_POST['form_fields'][ self::FIELD ] ) ) : '';
// phpcs:enable WordPress.Security.NonceVerification.Missing
if ( ! $event_id || self::EVENT_POST_TYPE !== get_post_type( $event_id ) ) {
return;
}
$settings = $record->get( 'form_settings' );
$form_id = is_array( $settings ) && ! empty( $settings['id'] ) ? sanitize_key( (string) $settings['id'] ) : '';
if ( '' !== $form_id && null !== Form_Connections::get( 'elementor', $form_id ) ) {
return; // Connected on its own - sent through that connection.
}
$fields = $record->get( 'fields' );
$dto = self::signup(
is_array( $fields ) ? $fields : array(),
$ticked,
$event_id,
(string) get_the_title( $event_id ),
self::get()['form'],
self::label(),
wp_generate_uuid4()
);
if ( null !== $dto ) {
Form_Connections::send( $dto, self::SOURCE_SLUG );
}
}
/**
* The sign-up to send, or null: not ticked, or no valid email.
*
* @param array $fields Elementor's submitted fields: id => {id, type, title, value}.
* @param string $ticked What our box sent ("on" when ticked).
* @param int $event_id The event page.
* @param string $title The event's title.
* @param string $target The 404 Emails form to join.
* @param string $label The box's wording.
* @param string $entity_id Unique to this submission.
* @return Signup_Dto|null
*/
public static function signup( array $fields, $ticked, $event_id, $title, $target, $label, $entity_id ) {
$form = array(
'id' => 'event-' . (int) $event_id,
'title' => $title,
'fields' => array(
array(
'key' => self::FIELD,
'label' => $label,
'kind' => Form_Connections::KIND_CONSENT,
),
),
);
$values = array( self::FIELD => $ticked );
foreach ( $fields as $id => $field ) {
if ( ! is_array( $field ) ) {
continue;
}
$key = (string) $id;
$type = isset( $field['type'] ) ? (string) $field['type'] : 'text';
$label_text = isset( $field['title'] ) ? (string) $field['title'] : '';
if ( 'email' === $type ) {
$kind = Form_Connections::KIND_EMAIL;
} elseif ( 'text' === $type ) {
$kind = Form_Connections::kind_from_words( $key, $label_text );
} else {
continue;
}
$form['fields'][] = array(
'key' => $key,
'label' => $label_text,
'kind' => $kind,
);
$values[ $key ] = isset( $field['value'] ) ? $field['value'] : '';
}
return Form_Connections::build_signup(
self::SOURCE_SLUG,
$form,
$values,
array(
'form' => $target,
'consent' => self::FIELD,
),
$entity_id,
''
);
}
}