$settings ? 'sendtim-forms-settings' : 'sendtim-forms', 'notice' => $notice, 'edit' => $id ?: false ), admin_url( 'admin.php' ) ) ); exit;
}
private static function start( $title, $description ) {
$notice = Sendtim_Forms::input( $_GET, 'notice' );
$messages = array( 'saved' => 'Saved. Your form is ready to place on your website.', 'deleted' => 'Form deleted.', 'connected' => 'Settings saved. Connection verified.', 'settings_saved' => 'Settings saved.', 'error' => 'Could not save. Check your connection, required fields and list selection.', 'connection_error' => 'Connection failed. Check your API key and network access.', 'crypto_error' => 'The API key could not be encrypted. OpenSSL is required.' );
echo '
';
echo '';
if ( isset( $messages[ $notice ] ) ) { echo '
' . esc_html( $messages[ $notice ] ) . '
'; }
if ( '' === Sendtim_Signup_Settings::api_key() ) { echo '
' . esc_html__( 'Start by connecting your account in Sendtim → Settings.', 'sendtim-signup-forms' ) . '
'; }
}
public static function save_settings() {
self::guard( 'sendtim_forms_settings' );
$result = Sendtim_Signup_Settings::set_api_key( Sendtim_Forms::input( $_POST, 'api_key' ), ! empty( $_POST['remove_key'] ) );
if ( is_wp_error( $result ) ) { self::redirect( 'crypto_error', 0, true ); }
update_option( Sendtim_Forms::OPTIONS, array( 'popups' => ! empty( $_POST['popups'] ), 'double_opt_in' => ! empty( $_POST['double_opt_in'] ) ), false );
if ( '' === Sendtim_Signup_Settings::api_key() ) { self::redirect( 'settings_saved', 0, true ); }
$test = ( new Sendtim_Signup_Api() )->me();
self::redirect( is_wp_error( $test ) ? 'connection_error' : 'connected', 0, true );
}
public static function settings() {
if ( ! current_user_can( 'manage_options' ) ) { return; }
$s = Sendtim_Forms::settings();
self::start( __( 'A home for your growing audience.', 'sendtim-signup-forms' ), __( 'Connect once. Choose how your website welcomes new subscribers.', 'sendtim-signup-forms' ) );
?>
'; return; }
$posts = Sendtim_Forms::posts();
$form_count_label = sprintf(
// translators: %d: Number of signup forms.
__( 'Your signup forms (%d)', 'sendtim-signup-forms' ),
count( $posts )
);
?>
ID, Sendtim_Forms::META, true ); ?>
[sendtim_form id="ID ); ?>"]ID . '"]' ); ?>">
post_type ) ) { echo 'Form not found.
'; return; }
$form = $id ? get_post_meta( $id, Sendtim_Forms::META, true ) : array();
$form = is_array( $form ) ? $form : array();
$d = $form['definition'] ?? array();
$remote = Sendtim_Forms::remote();
$lists_result = Sendtim_Signup_Settings::api_key() ? ( new Sendtim_Signup_Api() )->lists() : array();
$lists = ! is_wp_error( $lists_result ) ? ( $lists_result['data'] ?? array() ) : array();
if ( is_wp_error( $remote ) ) { echo '' . esc_html__( 'Account forms could not be loaded. Verify your API key or try again later. You can still create a custom form when your lists are available.', 'sendtim-signup-forms' ) . '
'; }
$type = ! empty( $form['remote_id'] ) ? 'remote' : 'custom';
?>
%2$s ', esc_attr( $name ), esc_html( $label ), esc_attr( $value ), 'button' === $name ? 60 : 500 );
}
private static function field_row( $index, $row ) {
$prefix = 'extra[' . $index . ']';
echo 'Label Type ';
foreach ( array( 'text' => 'Text', 'textarea' => 'Paragraph', 'phone' => 'Phone', 'number' => 'Number', 'select' => 'Dropdown', 'checkbox' => 'Checkbox' ) as $key => $label ) { printf( '%s ', esc_attr( $key ), selected( $row['type'] ?? 'text', $key, false ), esc_html( $label ) ); }
echo ' Save to ';
foreach ( array( 'first_name' => 'First name', 'last_name' => 'Last name', 'company' => 'Company', 'job_title' => 'Job title', 'phone' => 'Phone', 'country' => 'Country', 'city' => 'City', 'custom' => 'Custom property' ) as $key => $label ) { printf( '%s ', esc_attr( $key ), selected( $row['mapping'] ?? 'first_name', $key, false ), esc_html( $label ) ); }
echo ' Custom property key Dropdown choices (one per line) RequiredRemove field
';
}
public static function save() {
self::guard( 'sendtim_forms_save' );
$id = absint( Sendtim_Forms::input( $_POST, 'id' ) );
$post = $id ? get_post( $id ) : null;
if ( $id && ( ! $post || Sendtim_Forms::TYPE !== $post->post_type ) ) { self::redirect( 'error' ); }
$title = Sendtim_Forms::input( $_POST, 'title' );
if ( '' === $title || strlen( $title ) > 150 ) { self::redirect( 'error', $id ); }
if ( 'remote' === Sendtim_Forms::input( $_POST, 'type' ) ) {
$remote_id = Sendtim_Forms::input( $_POST, 'remote_id' );
$remote = Sendtim_Forms::remote_form( $remote_id, true );
if ( is_wp_error( $remote ) || 'inline' !== ( $remote['definition']['settings']['display']['mode'] ?? '' ) ) { self::redirect( 'error', $id ); }
$form = array( 'remote_id' => $remote_id, 'account_hash' => hash( 'sha256', Sendtim_Signup_Settings::api_key() ) );
} else {
$form = self::custom( $_POST );
if ( is_wp_error( $form ) ) { self::redirect( 'error', $id ); }
}
$saved = wp_insert_post( wp_slash( array( 'ID' => $id, 'post_type' => Sendtim_Forms::TYPE, 'post_status' => 'publish', 'post_title' => $title ) ), true );
if ( is_wp_error( $saved ) ) { self::redirect( 'error', $id ); }
$form['account_hash'] = hash( 'sha256', Sendtim_Signup_Settings::api_key() );
update_post_meta( $saved, Sendtim_Forms::META, wp_slash( $form ) );
self::redirect( 'saved', $saved );
}
private static function custom( $input ) {
$api_lists = ( new Sendtim_Signup_Api() )->lists();
if ( is_wp_error( $api_lists ) ) { return $api_lists; }
$lists = $api_lists['data'] ?? array();
$list_id = Sendtim_Forms::input( $input, 'list_id' );
if ( ! in_array( $list_id, array_column( $lists, 'id' ), true ) ) { return new WP_Error( 'list', 'Choose a list.' ); }
$fields = array( array( 'type' => 'email', 'id' => 'email01', 'label' => 'Email address', 'required' => true ) );
$editor = array();
$extra = isset( $input['extra'] ) && is_array( $input['extra'] ) ? array_slice( $input['extra'], 0, 20 ) : array();
$mapped = array();
foreach ( $extra as $row ) {
if ( ! is_array( $row ) ) { continue; }
$label = Sendtim_Forms::input( $row, 'label' );
if ( '' === $label ) { continue; }
$type = Sendtim_Forms::input( $row, 'type' );
$map = Sendtim_Forms::input( $row, 'mapping' );
$key = 'custom' === $map ? Sendtim_Forms::input( $row, 'key' ) : $map;
if ( ! in_array( $type, array( 'text', 'textarea', 'number', 'select', 'phone', 'checkbox' ), true ) || ! in_array( $map, array( 'first_name', 'last_name', 'company', 'job_title', 'phone', 'country', 'city', 'custom' ), true ) || ! preg_match( '/^[a-z][a-z0-9_]{0,63}$/', $key ) || strlen( $label ) > 120 || isset( $mapped[ $map . ':' . $key ] ) ) { return new WP_Error( 'field', 'Invalid field.' ); }
$mapped[ $map . ':' . $key ] = true;
$field = array( 'type' => $type, 'id' => sprintf( 'field%02d', count( $fields ) ), 'label' => $label, 'required' => ! empty( $row['required'] ), 'mapping' => array( 'kind' => 'custom' === $map ? 'custom_property' : 'contact_field', 'key' => $key ) );
$options = isset( $row['options'] ) && is_string( $row['options'] ) ? sanitize_textarea_field( wp_unslash( $row['options'] ) ) : '';
if ( 'select' === $type ) {
$choices = array_values( array_unique( array_filter( array_map( 'trim', explode( "\n", $options ) ) ) ) );
if ( ! $choices || count( $choices ) > 50 ) { return new WP_Error( 'choices', 'Invalid choices.' ); }
$field['options'] = array();
foreach ( $choices as $choice ) { if ( strlen( $choice ) > 100 ) { return new WP_Error( 'choices', 'Choice too long.' ); } $field['options'][] = array( 'value' => $choice, 'label' => $choice ); }
}
$fields[] = $field;
$editor[] = array( 'label' => $label, 'type' => $type, 'mapping' => $map, 'key' => 'custom' === $map ? $key : '', 'options' => $options, 'required' => ! empty( $row['required'] ) );
}
$consent = Sendtim_Forms::input( $input, 'consent' );
$button = Sendtim_Forms::input( $input, 'button' );
$success = Sendtim_Forms::input( $input, 'success' );
if ( '' === $consent || strlen( $consent ) > 500 || '' === $button || strlen( $button ) > 60 || '' === $success || strlen( $success ) > 500 ) { return new WP_Error( 'copy', 'Invalid form text.' ); }
$fields[] = array( 'type' => 'consent', 'id' => 'consent01', 'label' => $consent, 'required' => true );
$interests = array();
$chosen = isset( $input['interests'] ) && is_array( $input['interests'] ) ? $input['interests'] : array();
foreach ( $lists as $list ) { if ( $list['id'] !== $list_id && in_array( $list['id'], $chosen, true ) ) { $interests[] = array( 'id' => $list['id'], 'label' => $list['name'] ); } }
return array( 'heading' => substr( Sendtim_Forms::input( $input, 'heading' ), 0, 500 ), 'description' => substr( Sendtim_Forms::input( $input, 'description' ), 0, 500 ), 'list_id' => $list_id, 'interests' => $interests, 'editor_fields' => $editor, 'definition' => array(
'fields' => $fields,
'style' => array( 'accentColor' => sanitize_hex_color( Sendtim_Forms::input( $input, 'accent' ) ) ?: '#4f46e5', 'borderRadius' => 12, 'width' => 480, 'buttonLabel' => $button, 'layout' => 'inline' === Sendtim_Forms::input( $input, 'layout' ) ? 'inline' : 'stacked' ),
'settings' => array( 'successBehavior' => array( 'kind' => 'message', 'text' => $success ) ),
) );
}
public static function delete() {
$id = absint( Sendtim_Forms::input( $_POST, 'id' ) );
self::guard( 'sendtim_forms_delete_' . $id );
$post = get_post( $id );
if ( ! $post || Sendtim_Forms::TYPE !== $post->post_type ) { self::redirect( 'error' ); }
wp_delete_post( $id, true );
self::redirect( 'deleted' );
}
}