print_settings_result( (int) $result['settings'] );
} else {
$this->print_result( $result );
}
}
Admin_Ui::card_open( __( 'Import phone numbers', 'aslansheed-login' ), __( 'Link phone numbers stored by a previous login plugin to the existing users, so they can sign in with a code. Run a preview first. Numbers already used by another account and users that already have a phone are skipped.', 'aslansheed-login' ) );
echo '
';
Admin_Ui::card_close();
Admin_Ui::card_open( __( 'Settings backup', 'aslansheed-login' ), __( 'Download the general settings as a JSON file, or restore them on another site. Gateway keys, channel and captcha settings are not included, so no secret ever leaves this site.', 'aslansheed-login' ) );
echo '';
echo '';
echo '
';
Admin_Ui::card_close();
}
/**
* Sends the settings as a JSON download.
*
* @return void
*/
public function handle_export_settings() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to do this.', 'aslansheed-login' ), '', array( 'response' => 403 ) );
}
check_admin_referer( self::NONCE_ACTION );
nocache_headers();
header( 'Content-Type: application/json; charset=utf-8' );
header( 'Content-Disposition: attachment; filename="aslansheed-login-settings.json"' );
echo wp_json_encode( self::export_payload(), JSON_PRETTY_PRINT ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON download, not HTML.
exit;
}
/**
* Restores settings from an uploaded JSON file.
*
* @return void
*/
public function handle_import_settings() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to do this.', 'aslansheed-login' ), '', array( 'response' => 403 ) );
}
check_admin_referer( self::NONCE_ACTION );
// phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce checked above; the file is read and validated below.
$tmp = isset( $_FILES['settings_file']['tmp_name'] ) && is_uploaded_file( $_FILES['settings_file']['tmp_name'] ) ? $_FILES['settings_file']['tmp_name'] : '';
$raw = '' !== $tmp && filesize( $tmp ) < 100000 ? file_get_contents( $tmp ) : ''; // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Reading an uploaded temp file.
$applied = self::import_payload( (string) $raw );
set_transient(
'aslansheed_import_' . get_current_user_id(),
array(
'settings' => $applied,
),
120
);
wp_safe_redirect(
add_query_arg(
array(
'page' => Settings_Page::PAGE_SLUG,
'tab' => 'tools',
),
admin_url( 'admin.php' )
)
);
exit;
}
/**
* Builds the export document.
*
* @return array
*/
public static function export_payload() {
return array(
'plugin' => 'aslansheed-otp',
'version' => ASLANSHEED_OTP_VERSION,
'settings' => Options::all(),
);
}
/**
* Validates and applies an export document.
*
* @param string $json File contents.
* @return int Number of settings applied, 0 when the file is not valid.
*/
public static function import_payload( $json ) {
$data = json_decode( $json, true );
if ( ! is_array( $data ) || ! isset( $data['plugin'], $data['settings'] ) || 'aslansheed-otp' !== $data['plugin'] || ! is_array( $data['settings'] ) ) {
return 0;
}
$input = array();
$applied = 0;
foreach ( Options::schema() as $key => $definition ) {
if ( array_key_exists( $key, $data['settings'] ) && ! is_array( $data['settings'][ $key ] ) ) {
$input[ str_replace( '.', '__', $key ) ] = is_bool( $data['settings'][ $key ] ) ? ( $data['settings'][ $key ] ? '1' : '0' ) : $data['settings'][ $key ];
++$applied;
}
}
update_option( Options::OPTION_NAME, Options::sanitize_input( $input ) );
Options::flush_cache();
return $applied;
}
/**
* Runs a preview or an import.
*
* @return void
*/
public function handle_import() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to do this.', 'aslansheed-login' ), '', array( 'response' => 403 ) );
}
check_admin_referer( self::NONCE_ACTION );
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce checked above.
$source = isset( $_POST['source'] ) && Importer::SOURCE_META === $_POST['source'] ? Importer::SOURCE_META : Importer::SOURCE_DIGITS;
$meta = isset( $_POST['meta_key'] ) ? sanitize_key( wp_unslash( $_POST['meta_key'] ) ) : '';
$dry_run = ! ( isset( $_POST['mode'] ) && 'import' === $_POST['mode'] );
// phpcs:enable
$result = Importer::run( $source, $meta, $dry_run );
$result['dry_run'] = $dry_run;
if ( ! $dry_run ) {
Audit_Log::log(
'phones_imported',
array(
'user_id' => get_current_user_id(),
'context' => array(
'source' => $source,
'imported' => $result['imported'],
),
)
);
}
set_transient( 'aslansheed_import_' . get_current_user_id(), $result, 120 );
wp_safe_redirect(
add_query_arg(
array(
'page' => Settings_Page::PAGE_SLUG,
'tab' => 'tools',
),
admin_url( 'admin.php' )
)
);
exit;
}
/**
* Shows the linked phone number on a profile screen.
*
* @param \WP_User $user Profile owner.
* @return void
*/
public function profile_section( $user ) {
if ( ! current_user_can( 'edit_user', $user->ID ) ) {
return;
}
$phone = Account_Phone::get( (int) $user->ID );
echo '' . esc_html__( 'Aslansheed Login', 'aslansheed-login' ) . '
';
echo '';
}
/**
* Prints the outcome of a settings restore.
*
* @param int $applied Number of settings applied.
* @return void
*/
private function print_settings_result( $applied ) {
if ( $applied > 0 ) {
/* translators: %d: number of settings. */
echo '' . esc_html( sprintf( __( 'Settings restored: %d values.', 'aslansheed-login' ), $applied ) ) . '
';
return;
}
echo '' . esc_html__( 'The file is not a valid settings export.', 'aslansheed-login' ) . '
';
}
/**
* Prints the outcome of a preview or import.
*
* @param array $result Importer result plus dry_run.
* @return void
*/
private function print_result( array $result ) {
$title = ! empty( $result['dry_run'] ) ? __( 'Preview: nothing was changed.', 'aslansheed-login' ) : __( 'Import finished.', 'aslansheed-login' );
echo '' . esc_html( $title ) . '
';
/* translators: %d: number of users. */
echo '- ' . esc_html( sprintf( __( 'Users scanned: %d', 'aslansheed-login' ), $result['scanned'] ) ) . '
';
/* translators: %d: number of phone numbers. */
echo '- ' . esc_html( sprintf( __( 'Phone numbers to link or linked: %d', 'aslansheed-login' ), $result['imported'] ) ) . '
';
/* translators: %d: number of values. */
echo '- ' . esc_html( sprintf( __( 'Skipped, not a valid number: %d', 'aslansheed-login' ), $result['skipped_invalid'] ) ) . '
';
/* translators: %d: number of values. */
echo '- ' . esc_html( sprintf( __( 'Skipped, used by another account: %d', 'aslansheed-login' ), $result['skipped_taken'] ) ) . '
';
/* translators: %d: number of users. */
echo '- ' . esc_html( sprintf( __( 'Skipped, user already has a phone: %d', 'aslansheed-login' ), $result['skipped_existing'] ) ) . '
';
echo '
';
}
}