From fa2baa5d1b96a45d39a2b10c605810b5abc9d9dd Mon Sep 17 00:00:00 2001 From: Ravinder Kumar Date: Wed, 11 May 2022 23:02:52 +0530 Subject: [PATCH 01/53] Fix: prevent WordPress database error notice on fresh install (#6403) * fix: do not install table if already exist * fix: install migration table on fresh install * doc: add unreleased tag * doc: add unreleased tag * doc: add throws tag * refaxtor: create database tavle only if not exist --- includes/install.php | 789 +++++++++--------- .../Migrations/CreateMigrationsTable.php | 10 +- 2 files changed, 397 insertions(+), 402 deletions(-) diff --git a/includes/install.php b/includes/install.php index 7488047588..e1fdae9e6b 100644 --- a/includes/install.php +++ b/includes/install.php @@ -1,22 +1,24 @@ get_col( "SELECT blog_id FROM $wpdb->blogs LIMIT 100" ) as $blog_id ) { - - switch_to_blog( $blog_id ); - give_run_install(); - restore_current_blog(); - - } - } else { - - give_run_install(); - - } - +function give_install($network_wide = false) +{ + global $wpdb; + + if (is_multisite() && $network_wide) { + foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs LIMIT 100") as $blog_id) { + switch_to_blog($blog_id); + give_run_install(); + restore_current_blog(); + } + } else { + give_run_install(); + } } /** @@ -60,128 +56,128 @@ function give_install( $network_wide = false ) { * @since 1.5 * @return void */ -function give_run_install() { - $give_options = give_get_settings(); - - // Setup the Give Custom Post Types. - give_setup_post_types(); - - // Add Upgraded From Option. - $current_version = get_option( 'give_version' ); - if ( $current_version ) { - update_option( 'give_version_upgraded_from', $current_version, false ); - } - - // Setup some default options. - $options = []; - - // Fresh Install? Setup Test Mode, Base Country (US), Test Gateway, Currency. - if ( empty( $current_version ) ) { - $options = array_merge( $options, give_get_default_settings() ); - } else { - // Otherwise, disable the Onboarding experience - $options = [ - 'setup_page_enabled' => 'disabled', - ]; - } - - // Populate the default values. - update_option( 'give_settings', array_merge( $give_options, $options ), false ); - - // Create Give roles. - $roles = new Give_Roles(); - $roles->add_roles(); - $roles->add_caps(); - - // Set api version, end point and refresh permalink. - $api = new Give_API(); - $api->add_endpoint(); - update_option( 'give_default_api_version', 'v' . $api->get_version(), false ); - - // Create databases. - __give_register_tables(); - - // Add a temporary option to note that Give pages have been created. - Give_Cache::set( '_give_installed', $options, 30, true ); - - /** - * Run plugin upgrades. - * - * @since 1.8 - */ - do_action( 'give_upgrades' ); - - if ( GIVE_VERSION !== get_option( 'give_version' ) ) { - update_option( 'give_version', GIVE_VERSION, false ); - } - - if ( ! $current_version ) { - - require_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/upgrade-functions.php'; - - // When new upgrade routines are added, mark them as complete on fresh install. - $upgrade_routines = [ - 'upgrade_give_user_caps_cleanup', - 'upgrade_give_payment_customer_id', - 'upgrade_give_offline_status', - 'v18_upgrades_core_setting', - 'v18_upgrades_form_metadata', - 'v189_upgrades_levels_post_meta', - 'v1812_update_amount_values', - 'v1812_update_donor_purchase_values', - 'v1813_update_user_roles', - 'v1813_update_donor_user_roles', - 'v1817_update_donation_iranian_currency_code', - 'v1817_cleanup_user_roles', - 'v1818_assign_custom_amount_set_donation', - 'v1818_give_worker_role_cleanup', - 'v20_upgrades_form_metadata', - 'v20_logs_upgrades', - 'v20_move_metadata_into_new_table', - 'v20_rename_donor_tables', - 'v20_upgrades_donor_name', - 'v20_upgrades_user_address', - 'v20_upgrades_payment_metadata', - 'v201_upgrades_payment_metadata', - 'v201_add_missing_donors', - 'v201_move_metadata_into_new_table', - 'v201_logs_upgrades', - 'v210_verify_form_status_upgrades', - 'v213_delete_donation_meta', - 'v215_update_donor_user_roles', - 'v220_rename_donation_meta_type', - 'v224_update_donor_meta', - 'v224_update_donor_meta_forms_id', - 'v230_move_donor_note', - 'v230_move_donation_note', - 'v230_delete_donor_wall_related_donor_data', - 'v230_delete_donor_wall_related_comment_data', - 'v240_update_form_goal_progress', - 'v241_remove_sale_logs', - 'v270_store_stripe_account_for_donation', - AddPastDonationsToRevenueTable::id(), - MigrateExistingLogs::id() - ]; - - foreach ( $upgrade_routines as $upgrade ) { - give_set_upgrade_complete( $upgrade ); - } - } - - // Bail if activating from network, or bulk. - if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) { - return; - } - - // Setup embed form route on fresh install or plugin activation. - Give()->routeForm->setBasePrefix(); - Give()->routeForm->addRule(); - - // Flush rewrite rules. - flush_rewrite_rules(); - - // Add the transient to redirect. - Give_Cache::set( '_give_activation_redirect', true, 30, true ); +function give_run_install() +{ + $give_options = give_get_settings(); + + // Setup the Give Custom Post Types. + give_setup_post_types(); + + // Add Upgraded From Option. + $current_version = get_option('give_version'); + if ($current_version) { + update_option('give_version_upgraded_from', $current_version, false); + } + + // Setup some default options. + $options = []; + + // Fresh Install? Setup Test Mode, Base Country (US), Test Gateway, Currency. + if (empty($current_version)) { + $options = array_merge($options, give_get_default_settings()); + } else { + // Otherwise, disable the Onboarding experience + $options = [ + 'setup_page_enabled' => 'disabled', + ]; + } + + // Populate the default values. + update_option('give_settings', array_merge($give_options, $options), false); + + // Create Give roles. + $roles = new Give_Roles(); + $roles->add_roles(); + $roles->add_caps(); + + // Set api version, end point and refresh permalink. + $api = new Give_API(); + $api->add_endpoint(); + update_option('give_default_api_version', 'v' . $api->get_version(), false); + + // Create databases. + __give_register_tables(); + + // Add a temporary option to note that Give pages have been created. + Give_Cache::set('_give_installed', $options, 30, true); + + /** + * Run plugin upgrades. + * + * @since 1.8 + */ + do_action('give_upgrades'); + + if (GIVE_VERSION !== get_option('give_version')) { + update_option('give_version', GIVE_VERSION, false); + } + + if (!$current_version) { + require_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/upgrade-functions.php'; + + // When new upgrade routines are added, mark them as complete on fresh install. + $upgrade_routines = [ + 'upgrade_give_user_caps_cleanup', + 'upgrade_give_payment_customer_id', + 'upgrade_give_offline_status', + 'v18_upgrades_core_setting', + 'v18_upgrades_form_metadata', + 'v189_upgrades_levels_post_meta', + 'v1812_update_amount_values', + 'v1812_update_donor_purchase_values', + 'v1813_update_user_roles', + 'v1813_update_donor_user_roles', + 'v1817_update_donation_iranian_currency_code', + 'v1817_cleanup_user_roles', + 'v1818_assign_custom_amount_set_donation', + 'v1818_give_worker_role_cleanup', + 'v20_upgrades_form_metadata', + 'v20_logs_upgrades', + 'v20_move_metadata_into_new_table', + 'v20_rename_donor_tables', + 'v20_upgrades_donor_name', + 'v20_upgrades_user_address', + 'v20_upgrades_payment_metadata', + 'v201_upgrades_payment_metadata', + 'v201_add_missing_donors', + 'v201_move_metadata_into_new_table', + 'v201_logs_upgrades', + 'v210_verify_form_status_upgrades', + 'v213_delete_donation_meta', + 'v215_update_donor_user_roles', + 'v220_rename_donation_meta_type', + 'v224_update_donor_meta', + 'v224_update_donor_meta_forms_id', + 'v230_move_donor_note', + 'v230_move_donation_note', + 'v230_delete_donor_wall_related_donor_data', + 'v230_delete_donor_wall_related_comment_data', + 'v240_update_form_goal_progress', + 'v241_remove_sale_logs', + 'v270_store_stripe_account_for_donation', + AddPastDonationsToRevenueTable::id(), + MigrateExistingLogs::id() + ]; + + foreach ($upgrade_routines as $upgrade) { + give_set_upgrade_complete($upgrade); + } + } + + // Bail if activating from network, or bulk. + if (is_network_admin() || isset($_GET['activate-multi'])) { + return; + } + + // Setup embed form route on fresh install or plugin activation. + Give()->routeForm->setBasePrefix(); + Give()->routeForm->addRule(); + + // Flush rewrite rules. + flush_rewrite_rules(); + + // Add the transient to redirect. + Give_Cache::set('_give_activation_redirect', true, 30, true); } /** @@ -192,26 +188,23 @@ function give_run_install() { * * @since 1.3.5 * - * @param int $blog_id The Blog ID created. - * @param int $user_id The User ID set as the admin. - * @param string $domain The URL. - * @param string $path Site Path. - * @param int $site_id The Site ID. - * @param array $meta Blog Meta. + * @param int $blog_id The Blog ID created. + * @param int $user_id The User ID set as the admin. + * @param string $domain The URL. + * @param string $path Site Path. + * @param int $site_id The Site ID. + * @param array $meta Blog Meta. */ -function give_on_create_blog( $blog_id, $user_id, $domain, $path, $site_id, $meta ) { - - if ( is_plugin_active_for_network( GIVE_PLUGIN_BASENAME ) ) { - - switch_to_blog( $blog_id ); - give_install(); - restore_current_blog(); - - } - +function give_on_create_blog($blog_id, $user_id, $domain, $path, $site_id, $meta) +{ + if (is_plugin_active_for_network(GIVE_PLUGIN_BASENAME)) { + switch_to_blog($blog_id); + give_install(); + restore_current_blog(); + } } -add_action( 'wpmu_new_blog', 'give_on_create_blog', 10, 6 ); +add_action('wpmu_new_blog', 'give_on_create_blog', 10, 6); /** @@ -219,30 +212,29 @@ function give_on_create_blog( $blog_id, $user_id, $domain, $path, $site_id, $met * * @since 1.4.3 * - * @param array $tables The tables to drop. - * @param int $blog_id The Blog ID being deleted. + * @param array $tables The tables to drop. + * @param int $blog_id The Blog ID being deleted. * * @return array The tables to drop. */ -function give_wpmu_drop_tables( $tables, $blog_id ) { - - switch_to_blog( $blog_id ); - $custom_tables = __give_get_tables(); - - /* @var Give_DB $table */ - foreach ( $custom_tables as $table ) { - if ( $table->installed() ) { - $tables[] = $table->table_name; - } - } +function give_wpmu_drop_tables($tables, $blog_id) +{ + switch_to_blog($blog_id); + $custom_tables = __give_get_tables(); - restore_current_blog(); + /* @var Give_DB $table */ + foreach ($custom_tables as $table) { + if ($table->installed()) { + $tables[] = $table->table_name; + } + } - return $tables; + restore_current_blog(); + return $tables; } -add_filter( 'wpmu_drop_tables', 'give_wpmu_drop_tables', 10, 2 ); +add_filter('wpmu_drop_tables', 'give_wpmu_drop_tables', 10, 2); /** * Post-installation @@ -252,51 +244,47 @@ function give_wpmu_drop_tables( $tables, $blog_id ) { * @since 1.0 * @return void */ -function give_after_install() { - - if ( ! is_admin() ) { - return; - } - - $give_options = Give_Cache::get( '_give_installed', true ); - $give_table_check = get_option( '_give_table_check', false ); - - if ( false === $give_table_check || current_time( 'timestamp' ) > $give_table_check ) { - - if ( ! @Give()->donor_meta->installed() ) { - - // Create the donor meta database. - // (this ensures it creates it on multisite instances where it is network activated). - @Give()->donor_meta->create_table(); - - } - - if ( ! @Give()->donors->installed() ) { - // Create the donor database. - // (this ensures it creates it on multisite instances where it is network activated). - @Give()->donors->create_table(); - } - - /** - * Fires after plugin installation. - * - * @since 1.0 - * - * @param array $give_options Give plugin options. - */ - do_action( 'give_after_install', $give_options ); - - update_option( '_give_table_check', ( current_time( 'timestamp' ) + WEEK_IN_SECONDS ), false ); - } - - // Delete the transient - if ( false !== $give_options ) { - Give_Cache::delete( Give_Cache::get_key( '_give_installed' ) ); - } - +function give_after_install() +{ + if (!is_admin()) { + return; + } + + $give_options = Give_Cache::get('_give_installed', true); + $give_table_check = get_option('_give_table_check', false); + + if (false === $give_table_check || current_time('timestamp') > $give_table_check) { + if (!@Give()->donor_meta->installed()) { + // Create the donor meta database. + // (this ensures it creates it on multisite instances where it is network activated). + @Give()->donor_meta->create_table(); + } + + if (!@Give()->donors->installed()) { + // Create the donor database. + // (this ensures it creates it on multisite instances where it is network activated). + @Give()->donors->create_table(); + } + + /** + * Fires after plugin installation. + * + * @since 1.0 + * + * @param array $give_options Give plugin options. + */ + do_action('give_after_install', $give_options); + + update_option('_give_table_check', (current_time('timestamp') + WEEK_IN_SECONDS), false); + } + + // Delete the transient + if (false !== $give_options) { + Give_Cache::delete(Give_Cache::get_key('_give_installed')); + } } -add_action( 'admin_init', 'give_after_install' ); +add_action('admin_init', 'give_after_install'); /** @@ -307,26 +295,23 @@ function give_after_install() { * @since 1.0 * @return void */ -function give_install_roles_on_network() { - - global $wp_roles; - - if ( ! is_object( $wp_roles ) ) { - return; - } - - if ( ! array_key_exists( 'give_manager', $wp_roles->roles ) ) { - - // Create Give plugin roles - $roles = new Give_Roles(); - $roles->add_roles(); - $roles->add_caps(); - - } - +function give_install_roles_on_network() +{ + global $wp_roles; + + if (!is_object($wp_roles)) { + return; + } + + if (!array_key_exists('give_manager', $wp_roles->roles)) { + // Create Give plugin roles + $roles = new Give_Roles(); + $roles->add_roles(); + $roles->add_caps(); + } } -add_action( 'admin_init', 'give_install_roles_on_network' ); +add_action('admin_init', 'give_install_roles_on_network'); /** * Default core setting values. @@ -334,88 +319,88 @@ function give_install_roles_on_network() { * @since 1.8 * @return array */ -function give_get_default_settings() { - - $options = [ - // General. - 'base_country' => 'US', - 'test_mode' => 'enabled', - 'currency' => 'USD', - 'currency_position' => 'before', - 'session_lifetime' => '604800', - 'email_access' => 'enabled', - 'thousands_separator' => ',', - 'decimal_separator' => '.', - 'number_decimals' => 2, - 'sequential-ordering_status' => 'enabled', - - // Display options. - 'css' => 'enabled', - 'floatlabels' => 'disabled', - 'company_field' => 'disabled', - 'name_title_prefix' => 'disabled', - 'forms_singular' => 'enabled', - 'forms_archives' => 'enabled', - 'forms_excerpt' => 'enabled', - 'form_featured_img' => 'enabled', - 'form_sidebar' => 'enabled', - 'categories' => 'disabled', - 'tags' => 'disabled', - 'terms' => 'disabled', - 'admin_notices' => 'enabled', - 'cache' => 'enabled', - 'uninstall_on_delete' => 'disabled', - 'the_content_filter' => 'enabled', - 'scripts_footer' => 'disabled', - 'agree_to_terms_label' => __( 'Agree to Terms?', 'give' ), - 'agreement_text' => give_get_default_agreement_text(), - 'babel_polyfill_script' => 'enabled', - - // Default is manual gateway. - 'gateways' => [ - 'manual' => 1, - 'offline' => 1, - ], - 'default_gateway' => 'manual', - - // Offline gateway setup. - 'global_offline_donation_content' => give_get_default_offline_donation_content(), - 'global_offline_donation_email' => give_get_default_offline_donation_content(), - - // Billing address. - 'give_offline_donation_enable_billing_fields' => 'disabled', - - // Default donation notification email. - 'donation_notification' => give_get_default_donation_notification_email(), - - // Default email receipt message. - 'donation_receipt' => give_get_default_donation_receipt_email(), - - 'donor_default_user_role' => 'give_donor', - Give()->routeForm->getOptionName() => 'give', - - // Stripe accounts. - '_give_stripe_get_all_accounts' => [], - - // Onboarding - 'setup_page_enabled' => 'enabled', - - // Advanced settings - 'usage_tracking' => 'disabled', - ]; - - return $options; +function give_get_default_settings() +{ + $options = [ + // General. + 'base_country' => 'US', + 'test_mode' => 'enabled', + 'currency' => 'USD', + 'currency_position' => 'before', + 'session_lifetime' => '604800', + 'email_access' => 'enabled', + 'thousands_separator' => ',', + 'decimal_separator' => '.', + 'number_decimals' => 2, + 'sequential-ordering_status' => 'enabled', + + // Display options. + 'css' => 'enabled', + 'floatlabels' => 'disabled', + 'company_field' => 'disabled', + 'name_title_prefix' => 'disabled', + 'forms_singular' => 'enabled', + 'forms_archives' => 'enabled', + 'forms_excerpt' => 'enabled', + 'form_featured_img' => 'enabled', + 'form_sidebar' => 'enabled', + 'categories' => 'disabled', + 'tags' => 'disabled', + 'terms' => 'disabled', + 'admin_notices' => 'enabled', + 'cache' => 'enabled', + 'uninstall_on_delete' => 'disabled', + 'the_content_filter' => 'enabled', + 'scripts_footer' => 'disabled', + 'agree_to_terms_label' => __('Agree to Terms?', 'give'), + 'agreement_text' => give_get_default_agreement_text(), + 'babel_polyfill_script' => 'enabled', + + // Default is manual gateway. + 'gateways' => [ + 'manual' => 1, + 'offline' => 1, + ], + 'default_gateway' => 'manual', + + // Offline gateway setup. + 'global_offline_donation_content' => give_get_default_offline_donation_content(), + 'global_offline_donation_email' => give_get_default_offline_donation_content(), + + // Billing address. + 'give_offline_donation_enable_billing_fields' => 'disabled', + + // Default donation notification email. + 'donation_notification' => give_get_default_donation_notification_email(), + + // Default email receipt message. + 'donation_receipt' => give_get_default_donation_receipt_email(), + + 'donor_default_user_role' => 'give_donor', + Give()->routeForm->getOptionName() => 'give', + + // Stripe accounts. + '_give_stripe_get_all_accounts' => [], + + // Onboarding + 'setup_page_enabled' => 'enabled', + + // Advanced settings + 'usage_tracking' => 'disabled', + ]; + + return $options; } /** * Default terms and conditions. */ -function give_get_default_agreement_text() { +function give_get_default_agreement_text() +{ + $org_name = get_bloginfo('name'); - $org_name = get_bloginfo( 'name' ); - - $agreement = sprintf( - '

Acceptance of any contribution, gift or grant is at the discretion of the %1$s. The %1$s will not accept any gift unless it can be used or expended consistently with the purpose and mission of the %1$s.

+ $agreement = sprintf( + '

Acceptance of any contribution, gift or grant is at the discretion of the %1$s. The %1$s will not accept any gift unless it can be used or expended consistently with the purpose and mission of the %1$s.

No irrevocable gift, whether outright or life-income in character, will be accepted if under any reasonable set of circumstances the gift would jeopardize the donor’s financial security.

The %1$s will refrain from providing advice about the tax or other treatment of gifts and will encourage donors to seek guidance from their own professional advisers to assist them in the process of making their donation.

The %1$s will accept donations of cash or publicly traded securities. Gifts of in-kind services will be accepted at the discretion of the %1$s.

@@ -423,10 +408,10 @@ function give_get_default_agreement_text() {

The %1$s will provide acknowledgments to donors meeting tax requirements for property received by the charity as a gift. However, except for gifts of cash and publicly traded securities, no value shall be ascribed to any receipt or other form of substantiation of a gift received by %1$s.

The %1$s will respect the intent of the donor relating to gifts for restricted purposes and those relating to the desire to remain anonymous. With respect to anonymous gifts, the %1$s will restrict information about the donor to only those staff members with a need to know.

The %1$s will not compensate, whether through commissions, finders\' fees, or other means, any third party for directing a gift or a donor to the %1$s.

', - $org_name - ); + $org_name + ); - return apply_filters( 'give_get_default_agreement_text', $agreement, $org_name ); + return apply_filters('give_get_default_agreement_text', $agreement, $org_name); } @@ -437,62 +422,63 @@ function give_get_default_agreement_text() { * * @return void */ -function give_create_pages() { - - // Bailout if pages already created. - if ( Give_Cache_Setting::get_option( 'give_install_pages_created' ) ) { - return; - } - - $options = []; - - // Checks if the Success Page option exists AND that the page exists. - if ( ! get_post( give_get_option( 'success_page' ) ) ) { - - // Donation Confirmation (Success) Page - $success = wp_insert_post( - [ - 'post_title' => esc_html__( 'Donation Confirmation', 'give' ), - 'post_content' => '[give_receipt]', - 'post_status' => 'publish', - 'post_author' => 1, - 'post_type' => 'page', - 'comment_status' => 'closed', - ] - ); - - // Store our page IDs - $options['success_page'] = $success; - } - - // Checks if the Failure Page option exists AND that the page exists. - if ( ! get_post( give_get_option( 'failure_page' ) ) ) { - - // Failed Donation Page - $failed = wp_insert_post( - [ - 'post_title' => esc_html__( 'Donation Failed', 'give' ), - 'post_content' => esc_html__( 'We\'re sorry, your donation failed to process. Please try again or contact site support.', 'give' ), - 'post_status' => 'publish', - 'post_author' => 1, - 'post_type' => 'page', - 'comment_status' => 'closed', - ] - ); - - $options['failure_page'] = $failed; - } - - if ( ! empty( $options ) ) { - update_option( 'give_settings', array_merge( give_get_settings(), $options ), false ); - } - - add_option( 'give_install_pages_created', 1, '', false ); +function give_create_pages() +{ + // Bailout if pages already created. + if (Give_Cache_Setting::get_option('give_install_pages_created')) { + return; + } + + $options = []; + + // Checks if the Success Page option exists AND that the page exists. + if (!get_post(give_get_option('success_page'))) { + // Donation Confirmation (Success) Page + $success = wp_insert_post( + [ + 'post_title' => esc_html__('Donation Confirmation', 'give'), + 'post_content' => '[give_receipt]', + 'post_status' => 'publish', + 'post_author' => 1, + 'post_type' => 'page', + 'comment_status' => 'closed', + ] + ); + + // Store our page IDs + $options['success_page'] = $success; + } + + // Checks if the Failure Page option exists AND that the page exists. + if (!get_post(give_get_option('failure_page'))) { + // Failed Donation Page + $failed = wp_insert_post( + [ + 'post_title' => esc_html__('Donation Failed', 'give'), + 'post_content' => esc_html__( + 'We\'re sorry, your donation failed to process. Please try again or contact site support.', + 'give' + ), + 'post_status' => 'publish', + 'post_author' => 1, + 'post_type' => 'page', + 'comment_status' => 'closed', + ] + ); + + $options['failure_page'] = $failed; + } + + if (!empty($options)) { + update_option('give_settings', array_merge(give_get_settings(), $options), false); + } + + add_option('give_install_pages_created', 1, '', false); } // @TODO we can add this hook only when plugin activate instead of every admin page load. // @see known issue https://github.com/impress-org/give/issues/1848 -add_action( 'admin_init', 'give_create_pages', - 1 ); +add_action('admin_init', 'give_create_pages', -1); /** @@ -503,12 +489,13 @@ function give_create_pages() { * * @param string $old_version */ -function give_install_tables_on_plugin_update( $old_version ) { - update_option( 'give_version_upgraded_from', $old_version, false ); - __give_register_tables(); +function give_install_tables_on_plugin_update($old_version) +{ + update_option('give_version_upgraded_from', $old_version, false); + __give_register_tables(); } -add_action( 'update_option_give_version', 'give_install_tables_on_plugin_update', 0, 2 ); +add_action('update_option_give_version', 'give_install_tables_on_plugin_update', 0, 2); /** @@ -518,34 +505,40 @@ function give_install_tables_on_plugin_update( $old_version ) { * * @sice 2.3.1 */ -function __give_get_tables() { - $tables = [ - 'donors_db' => new Give_DB_Donors(), - 'donor_meta_db' => new Give_DB_Donor_Meta(), - 'comment_db' => new Give_DB_Comments(), - 'comment_db_meta' => new Give_DB_Comment_Meta(), - 'give_session' => new Give_DB_Sessions(), - 'formmeta_db' => new Give_DB_Form_Meta(), - 'sequential_db' => new Give_DB_Sequential_Ordering(), - 'donation_meta' => new Give_DB_Payment_Meta(), - ]; - - return $tables; +function __give_get_tables() +{ + $tables = [ + 'donors_db' => new Give_DB_Donors(), + 'donor_meta_db' => new Give_DB_Donor_Meta(), + 'comment_db' => new Give_DB_Comments(), + 'comment_db_meta' => new Give_DB_Comment_Meta(), + 'give_session' => new Give_DB_Sessions(), + 'formmeta_db' => new Give_DB_Form_Meta(), + 'sequential_db' => new Give_DB_Sequential_Ordering(), + 'donation_meta' => new Give_DB_Payment_Meta(), + ]; + + return $tables; } /** * Register classes * Note: only for internal purpose use * - * @sice 2.3.1 + * @unreleased Install migration table on fresh install because this table is required to run migrations. + * @since 2.3.1 + * @throws DatabaseMigrationException */ -function __give_register_tables() { - $tables = __give_get_tables(); - - /* @var Give_DB $table */ - foreach ( $tables as $table ) { - if ( ! $table->installed() ) { - $table->register_table(); - } - } +function __give_register_tables() +{ + $tables = __give_get_tables(); + + /* @var Give_DB $table */ + foreach ($tables as $table) { + if (!$table->installed()) { + $table->register_table(); + } + } + + give(CreateMigrationsTable::class)->run(); } diff --git a/src/MigrationLog/Migrations/CreateMigrationsTable.php b/src/MigrationLog/Migrations/CreateMigrationsTable.php index d88feb1c13..cf78a5b731 100644 --- a/src/MigrationLog/Migrations/CreateMigrationsTable.php +++ b/src/MigrationLog/Migrations/CreateMigrationsTable.php @@ -43,14 +43,16 @@ public static function timestamp() return strtotime('1970-01-01 00:00'); } + /** + * @unreleased Add Check whether table installed before adding it to database. + * @throws DatabaseMigrationException + */ public function run() { - global $wpdb; - - $table = "{$wpdb->prefix}give_migrations"; + $table = DB::prefix('give_migrations'); $charset = DB::get_charset_collate(); - $sql = "CREATE TABLE {$table} ( + $sql = "CREATE TABLE IF NOT EXISTS {$table} ( id VARCHAR(180) NOT NULL, status VARCHAR(16) NOT NULL, error text NULL, From 64b04c07ae2b183afa1ad8447faded3538fc9f1e Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Wed, 11 May 2022 16:05:07 -0700 Subject: [PATCH 02/53] chore: correct release date --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index b9b140ec24..8b8f1805d3 100644 --- a/readme.txt +++ b/readme.txt @@ -250,7 +250,7 @@ The 2% fee on Stripe donations only applies to donations taken via our free Stri 8. GiveWP has a dedicated support team to help answer any questions you may have and help you through stumbling blocks. == Changelog == -= 2.20.0: April 27th, 2022 = += 2.20.0: May 11th, 2022 = * New: Refreshed the donor and donation list screens in the admin * New: Significant improvements to the donor wall and form grid blocks * Enhancement: Optimized deleting a donation and all of its meta From 6b97f434b47be473e8bb5ae1bb87254d329d59aa Mon Sep 17 00:00:00 2001 From: Ravinder Kumar Date: Thu, 12 May 2022 10:19:27 +0530 Subject: [PATCH 03/53] tests: make mock class function compatible with parent class --- .../Traits/HasRouteMethodTest.php | 16 ++++++++-------- .../PaymentGatewaysRegisterTest.php | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/unit/tests/Framework/PaymentGateways/Traits/HasRouteMethodTest.php b/tests/unit/tests/Framework/PaymentGateways/Traits/HasRouteMethodTest.php index 75a9e922ef..3b2b51b05c 100644 --- a/tests/unit/tests/Framework/PaymentGateways/Traits/HasRouteMethodTest.php +++ b/tests/unit/tests/Framework/PaymentGateways/Traits/HasRouteMethodTest.php @@ -72,32 +72,32 @@ class GatewayRouteTestGateway extends PaymentGateway { public $routeMethods = ['gatewaySimpleRouteMethod']; - protected function gatewaySimpleRouteMethod($queryParams) + protected function gatewaySimpleRouteMethod($queryParams): string { return __CLASS__ . __FUNCTION__; } - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup($formId, $args): string { return ''; } - public static function id() + public static function id(): string { return 'GatewayRouteTestGateway'; } - public function getId() + public function getId(): string { return self::id(); } - public function getName() + public function getName(): string { return self::id(); } - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return self::id(); } @@ -128,12 +128,12 @@ public function createSubscription( ) { } - protected function handleSimpleRoute($queryParams) + protected function handleSimpleRoute($queryParams): string { return __CLASS__ . __FUNCTION__; } - protected function handleSecureRoute($queryParams) + protected function handleSecureRoute($queryParams): string { return __CLASS__ . __FUNCTION__; } diff --git a/tests/unit/tests/PaymentGateways/PaymentGatewaysRegisterTest.php b/tests/unit/tests/PaymentGateways/PaymentGatewaysRegisterTest.php index d7b3c8d8f3..965fff7f5c 100644 --- a/tests/unit/tests/PaymentGateways/PaymentGatewaysRegisterTest.php +++ b/tests/unit/tests/PaymentGateways/PaymentGatewaysRegisterTest.php @@ -93,7 +93,7 @@ class MockStripe extends PaymentGateway /** * @return string */ - public static function id() + public static function id(): string { return 'mock-stripe'; } @@ -101,7 +101,7 @@ public static function id() /** * @inheritDoc */ - public function getId() + public function getId(): string { return self::id(); } @@ -109,7 +109,7 @@ public function getId() /** * @inheritDoc */ - public function getName() + public function getName(): string { return 'Stripe Payment Method'; } @@ -117,7 +117,7 @@ public function getName() /** * @inheritDoc */ - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return 'Credit Card'; } @@ -146,7 +146,7 @@ class MockPaypal extends PaymentGateway /** * @return string */ - public static function id() + public static function id(): string { return 'mock-paypal'; } @@ -154,7 +154,7 @@ public static function id() /** * @inheritDoc */ - public function getId() + public function getId(): string { return self::id(); } @@ -162,7 +162,7 @@ public function getId() /** * @inheritDoc */ - public function getName() + public function getName(): string { return 'PayPal Payment Method'; } @@ -170,7 +170,7 @@ public function getName() /** * @inheritDoc */ - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return 'PayPal'; } From 58b4bde978befb91a4c04585c0f857fb7bacb22c Mon Sep 17 00:00:00 2001 From: Ravinder Kumar Date: Thu, 12 May 2022 21:39:08 +0530 Subject: [PATCH 04/53] fix: show migration and log table in system info (#6412) --- .../tools/views/html-admin-page-system-info.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/includes/admin/tools/views/html-admin-page-system-info.php b/includes/admin/tools/views/html-admin-page-system-info.php index 9c5590acff..42d40769e0 100644 --- a/includes/admin/tools/views/html-admin-page-system-info.php +++ b/includes/admin/tools/views/html-admin-page-system-info.php @@ -565,6 +565,22 @@ class="dashicons dashicons-external"> Table::prefixTableName( 'give_revenue' ) ); + $isMigrationTableExist = Table::tableExists(Table::prefixTableName('give_migrations')); + $db_table_list .= sprintf( + '
  • %3$s
  • ', + $isMigrationTableExist ? 'yes' : 'error', + $isMigrationTableExist ? 'yes' : 'no-alt', + Table::prefixTableName('give_migrations') + ); + + $isLogTableExist = Table::tableExists(Table::prefixTableName('give_log')); + $db_table_list .= sprintf( + '
  • %3$s
  • ', + $isLogTableExist ? 'yes' : 'error', + $isLogTableExist ? 'yes' : 'no-alt', + Table::prefixTableName('give_log') + ); + echo "
      {$db_table_list}
    "; ?> From 307bc184a5a99885e7f2f109355c7b2981d1d83b Mon Sep 17 00:00:00 2001 From: Taylor Waldon <103544411+taylorfromteamgive@users.noreply.github.com> Date: Thu, 12 May 2022 11:48:47 -0700 Subject: [PATCH 05/53] Chore: Add Venmo to Readme (#6414) --- readme.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 8b8f1805d3..18bc121d77 100644 --- a/readme.txt +++ b/readme.txt @@ -83,12 +83,13 @@ For new users, we suggest reviewing our [Getting Started Guide](https://go.givew If you are a GiveWP customer with an active license of any of our popular add-ons, we'd love to hear from you and support you via our [Priority Support channel](https://go.givewp.com/support). -=== 💳 Accept Credit Card Donations === +=== 💳 Accept Credit Card Donations and More === GiveWP comes with several payment gateway options: * **Stripe Donations** -- Our Stripe integration allows you to accept credit card donations on your website. There is a small 2% fee associated with these donations. Want no additional fees? Upgrade to our Stripe Premium add-on to start accepting [Stripe Donations]](https://go.givewp.com/addon-stripe). * **PayPal Donations** -- Allow worldwide donations with PayPal Donations. No additional fees applied. +* **Venmo Donations** -- Give donors the option to pay through Venmo with their account balance or connected bank account. * **Offline Donations** -- Enable your donors to send checks or physical donations with an offline gateway with instructions. * **Test Gateway** -- use the Test Gateway to see exactly how your donors will walk through the donation process. * **And many more Gateways** - View additional payment gateways on our website. These include Authorize.net, Bitpay, Square, Razorpay, Paytm, and more. From b19fce14cd792f412075f7631838b78ee4dc68c4 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Fri, 13 May 2022 09:06:45 -0700 Subject: [PATCH 06/53] Improvement: update DatabaseQueryException to log when uncaught (#6416) --- src/Framework/Database/DB.php | 2 +- .../Exceptions/DatabaseQueryException.php | 50 +++++-------------- .../Contracts/LoggableException.php | 8 +-- src/Framework/Exceptions/Traits/Loggable.php | 8 +-- src/Revenue/Repositories/Revenue.php | 23 ++------- .../UncaughtExceptionLoggerTest.php | 4 +- 6 files changed, 25 insertions(+), 70 deletions(-) diff --git a/src/Framework/Database/DB.php b/src/Framework/Database/DB.php index 15ba26f919..d24c1da72e 100644 --- a/src/Framework/Database/DB.php +++ b/src/Framework/Database/DB.php @@ -239,7 +239,7 @@ private static function runQueryWithErrorChecking($queryCaller) $wpError = self::getQueryErrors($errorCount); if (!empty($wpError->errors)) { - throw DatabaseQueryException::create($wpError->get_error_messages()); + throw new DatabaseQueryException('Query Exception', $wpError->errors); } return $output; diff --git a/src/Framework/Database/Exceptions/DatabaseQueryException.php b/src/Framework/Database/Exceptions/DatabaseQueryException.php index 633a1ac7df..be011c39af 100644 --- a/src/Framework/Database/Exceptions/DatabaseQueryException.php +++ b/src/Framework/Database/Exceptions/DatabaseQueryException.php @@ -2,7 +2,8 @@ namespace Give\Framework\Database\Exceptions; -use Exception; +use Give\Framework\Exceptions\Primitives\Exception; +use Throwable; /** * Class DatabaseQueryException @@ -10,6 +11,7 @@ * An exception for when errors occurred within the database while performing a query, which stores the SQL errors the * database returned * + * @unreleased Use the GiveWP exception class * @since 2.9.2 */ class DatabaseQueryException extends Exception @@ -19,24 +21,11 @@ class DatabaseQueryException extends Exception */ private $queryErrors; - /** - * Creates a new instance wih the query errors - * - * @since 2.9.2 - * - * @param string|string[] $queryErrors - * @param string|null $message - * - * @return DatabaseQueryException - */ - public static function create($queryErrors, $message = null) + public function __construct(string $message, array $queryErrors, $code = 0, Throwable $previous = null) { - $error = new self(); + $this->queryErrors = $queryErrors; - $error->message = $message ?: 'Query failed in database'; - $error->queryErrors = (array)$queryErrors; - - return $error; + parent::__construct($message, $code, $previous); } /** @@ -46,32 +35,19 @@ public static function create($queryErrors, $message = null) * * @return string[] */ - public function getQueryErrors() + public function getQueryErrors(): array { return $this->queryErrors; } /** - * Returns a human readable form of the exception for logging - * - * @since 2.9.2 - * - * @return string + * @inheritDoc */ - public function getLogOutput() + public function getLogContext(): array { - $queryErrors = array_map( - function ($error) { - return " - {$error}"; - }, - $this->queryErrors - ); - - return " - Code: {$this->getCode()}\n - Message: {$this->getMessage()}\n - DB Errors: \n - {$queryErrors} - "; + return [ + 'category' => 'Uncaught database exception', + 'Query Errors' => $this->queryErrors, + ]; } } diff --git a/src/Framework/Exceptions/Contracts/LoggableException.php b/src/Framework/Exceptions/Contracts/LoggableException.php index 6a618138fe..ee25edf9ab 100644 --- a/src/Framework/Exceptions/Contracts/LoggableException.php +++ b/src/Framework/Exceptions/Contracts/LoggableException.php @@ -8,17 +8,13 @@ interface LoggableException * Returns the human-readable message for the log * * @since 2.11.1 - * - * @return string */ - public function getLogMessage(); + public function getLogMessage(): string; /** * Returns an associated array with additional context for the log * * @since 2.11.1 - * - * @return array */ - public function getLogContext(); + public function getLogContext(): array; } diff --git a/src/Framework/Exceptions/Traits/Loggable.php b/src/Framework/Exceptions/Traits/Loggable.php index 8f2b22de13..3f14882dfa 100644 --- a/src/Framework/Exceptions/Traits/Loggable.php +++ b/src/Framework/Exceptions/Traits/Loggable.php @@ -8,8 +8,6 @@ trait Loggable * Gets the Exception::getMessage() method * * @since 2.11.1 - * - * @return string */ abstract public function getMessage(); @@ -17,10 +15,8 @@ abstract public function getMessage(); * Returns the human-readable log message * * @since 2.11.1 - * - * @return string */ - public function getLogMessage() + public function getLogMessage(): string { return $this->getMessage(); } @@ -32,7 +28,7 @@ public function getLogMessage() * * @return array */ - public function getLogContext() + public function getLogContext(): array { return [ 'category' => 'Uncaught Exception', diff --git a/src/Revenue/Repositories/Revenue.php b/src/Revenue/Repositories/Revenue.php index 5d00b5bbed..c8f691d11b 100644 --- a/src/Revenue/Repositories/Revenue.php +++ b/src/Revenue/Repositories/Revenue.php @@ -3,7 +3,6 @@ namespace Give\Revenue\Repositories; use Give\Framework\Database\DB; -use Give\Framework\Database\Exceptions\DatabaseQueryException; use Give\Framework\Exceptions\Primitives\InvalidArgumentException; /** @@ -52,28 +51,16 @@ public function insert($revenueData) * @param $revenueId * * @return false|int - * @throws DatabaseQueryException */ public function deleteByDonationId($revenueId) { global $wpdb; - try { - return DB::delete( - $wpdb->give_revenue, - ['donation_id' => $revenueId], - ['%d'] - ); - } catch (DatabaseQueryException $exception) { - give_record_log( - 'Revenue delete by donation failed', - $exception->getLogOutput(), - 0, - 'database' - ); - - throw $exception; - } + return DB::delete( + $wpdb->give_revenue, + ['donation_id' => $revenueId], + ['%d'] + ); } /** diff --git a/tests/unit/tests/Framework/Exceptions/UncaughtExceptionLoggerTest.php b/tests/unit/tests/Framework/Exceptions/UncaughtExceptionLoggerTest.php index 7cc695eb06..bcc328c2da 100644 --- a/tests/unit/tests/Framework/Exceptions/UncaughtExceptionLoggerTest.php +++ b/tests/unit/tests/Framework/Exceptions/UncaughtExceptionLoggerTest.php @@ -27,11 +27,11 @@ public function testShouldLogException() } class ExceptionLogged extends Exception implements LoggableException { - public function getLogMessage() { + public function getLogMessage(): string { return ''; } - public function getLogContext() { + public function getLogContext(): array { return []; } } From ab405f99f57b8b7dee34e4f30b2bb4a891174bbc Mon Sep 17 00:00:00 2001 From: Ravinder Kumar Date: Fri, 13 May 2022 21:53:48 +0530 Subject: [PATCH 07/53] Log does not generate PHP warnings (#6411) * fix: use array_diff_key to prevent php wanring * doc: add unreleased tag --- src/Log/Log.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Log/Log.php b/src/Log/Log.php index 60f209b1f6..aad9c9a9b9 100644 --- a/src/Log/Log.php +++ b/src/Log/Log.php @@ -11,6 +11,7 @@ * * The static facade intended to be the primary way of logging within GiveWP to make life easier. * + * @unreleased Use array_diff_key to filter context data to prevent php wanring with multi-dimesion array * @since 2.20.0 add sensitive information redaction; store context as arrays for JSON serialization * @since 2.19.6 added debug * @since 2.10.0 @@ -82,7 +83,7 @@ function ($key) { ); // Additional context - $data['context'] = array_diff( + $data['context'] = array_diff_key( $context, $data ); From 72ca6dbb19e085b076778ae477ed8d55a8793bfd Mon Sep 17 00:00:00 2001 From: Jon Waldstein Date: Fri, 13 May 2022 14:34:52 -0400 Subject: [PATCH 08/53] Enhancement: Gateway api now uses models (#6306) Co-authored-by: Jon Waldstein Co-authored-by: Ravinder Kumar --- includes/donors/actions.php | 11 +- includes/forms/functions.php | 2 +- .../DataTransferObjects/DonationQueryData.php | 2 +- .../Factories/DonationNoteFactory.php | 21 ++ src/Donations/Models/Donation.php | 52 ++--- src/Donations/Models/DonationNote.php | 141 ++++++++++++ .../Repositories/DonationNotesRepository.php | 207 +++++++++++++++++ .../Repositories/DonationRepository.php | 60 +++-- src/Donations/ServiceProvider.php | 2 + src/Donors/Models/Donor.php | 40 ++-- src/Donors/Repositories/DonorRepository.php | 2 +- .../LegacyPaymentGatewayInterface.php | 4 +- src/Framework/Models/Model.php | 2 +- .../Actions/GenerateGatewayRouteUrl.php | 2 +- .../PaymentAbandonedHandler.php | 7 +- .../PaymentCompleteHandler.php | 7 +- .../CommandHandlers/PaymentHandler.php | 37 +-- .../PaymentProcessingHandler.php | 5 +- .../PaymentRefundedHandler.php | 7 +- .../RedirectOffsiteHandler.php | 5 +- .../RespondToBrowserHandler.php | 5 +- .../SubscriptionCompleteHandler.php | 64 ++---- .../Commands/PaymentCommand.php | 10 +- .../Commands/RedirectOffsite.php | 4 +- .../Commands/RespondToBrowser.php | 4 +- .../Commands/SubscriptionComplete.php | 5 +- .../Contracts/PaymentGatewayInterface.php | 21 +- .../Contracts/SubscriptionModuleInterface.php | 26 +-- .../PaymentGateways/DonationSummary.php | 55 ++--- .../PaymentGateways/PaymentGateway.php | 100 +++----- .../PaymentGateways/SubscriptionModule.php | 6 +- .../Adapters/LegacyPaymentGatewayAdapter.php | 164 +++++++++----- .../LegacyDonationData.php | 61 ----- .../includes/give-recurring-cache.php | 1 - .../includes/give-subscriptions-db.php | 105 +++++---- .../Actions/RegisterPaymentGateways.php | 5 +- .../DataTransferObjects/FormData.php | 80 ++----- .../GatewayPaymentData.php | 100 -------- .../GatewaySubscriptionData.php | 48 ---- .../DataTransferObjects/SubscriptionData.php | 18 +- .../CreatePayPalStandardPaymentURL.php | 59 ++--- .../PayPalStandard/PayPalStandard.php | 46 ++-- .../Views/PayPalStandardBillingFields.php | 4 +- .../Stripe/Actions/CreateCheckoutSession.php | 37 +-- .../Stripe/Actions/CreatePaymentIntent.php | 67 +++--- .../Actions/GetOrCreateStripeCustomer.php | 39 ++-- .../Actions/GetPaymentMethodFromRequest.php | 22 +- .../Stripe/Actions/SaveDonationSummary.php | 13 +- .../Gateways/Stripe/BECSGateway.php | 26 +-- .../Gateways/Stripe/CheckoutGateway.php | 50 ++-- .../Gateways/Stripe/CreditCardGateway.php | 26 +-- .../Gateways/Stripe/SEPAGateway.php | 53 +++-- .../Traits/HandlePaymentIntentStatus.php | 10 +- .../Stripe/Traits/SEPAMandateForm.php | 53 +++-- .../Gateways/TestGateway/TestGateway.php | 18 +- .../TestGateway/TestGatewayOffsite.php | 66 +++--- .../PayPalCommerce/PayPalCommerce.php | 22 +- src/Subscriptions/Models/Subscription.php | 21 +- .../Repositories/SubscriptionRepository.php | 10 +- .../tests/Donations/Models/TestDonation.php | 65 ++++-- .../Donations/Models/TestDonationNote.php | 75 ++++++ .../TestDonationNoteRepository.php | 213 ++++++++++++++++++ .../TestDonationRepository.php | 2 +- .../PaymentGateways/DonationSummaryTest.php | 74 +++--- .../Traits/HasRouteMethodTest.php | 13 +- .../Gateways/Stripe/CreditCardGatewayTest.php | 74 +++--- .../PaymentGatewaysRegisterTest.php | 8 +- 67 files changed, 1527 insertions(+), 1137 deletions(-) create mode 100644 src/Donations/Factories/DonationNoteFactory.php create mode 100644 src/Donations/Models/DonationNote.php create mode 100644 src/Donations/Repositories/DonationNotesRepository.php delete mode 100644 src/LegacyPaymentGateways/DataTransferObjects/LegacyDonationData.php delete mode 100644 src/PaymentGateways/DataTransferObjects/GatewayPaymentData.php delete mode 100644 src/PaymentGateways/DataTransferObjects/GatewaySubscriptionData.php create mode 100644 tests/unit/tests/Donations/Models/TestDonationNote.php create mode 100644 tests/unit/tests/Donations/Repositories/TestDonationNoteRepository.php rename tests/unit/tests/Donations/{ => Repositories}/TestDonationRepository.php (99%) diff --git a/includes/donors/actions.php b/includes/donors/actions.php index f7ae70e672..336d78047c 100644 --- a/includes/donors/actions.php +++ b/includes/donors/actions.php @@ -2,16 +2,13 @@ /** * Insert donor comment to donation. * + * @unreleased remove anonymous * @since 2.2.0 * - * @param int $donation_id - * @param array $donation_data + * @param int $donation_id + * @param array $donation_data */ function __give_insert_donor_donation_comment( $donation_id, $donation_data ) { - $is_anonymous_donation = isset( $_POST['give_anonymous_donation'] ) - ? absint( $_POST['give_anonymous_donation'] ) - : 0; - if ( ! empty( $_POST['give_comment'] ) ) { $comment_meta = array( 'author_email' => $donation_data['user_info']['email'] ); @@ -27,8 +24,6 @@ function __give_insert_donor_donation_comment( $donation_id, $donation_data ) { $comment_meta ); } - - give_update_meta( $donation_id, '_give_anonymous_donation', $is_anonymous_donation ); } add_action( 'give_insert_payment', '__give_insert_donor_donation_comment', 10, 2 ); diff --git a/includes/forms/functions.php b/includes/forms/functions.php index 8898691aaa..ad37186ba1 100644 --- a/includes/forms/functions.php +++ b/includes/forms/functions.php @@ -616,7 +616,7 @@ function give_get_price_option_name( $form_id = 0, $price_id = 0, $payment_id = $prices = give_get_variable_prices( $form_id ); $price_name = ''; - if ( false === $prices ) { + if ( ! $prices ) { return $price_name; } diff --git a/src/Donations/DataTransferObjects/DonationQueryData.php b/src/Donations/DataTransferObjects/DonationQueryData.php index 3b38bdf76d..7498ee59fa 100644 --- a/src/Donations/DataTransferObjects/DonationQueryData.php +++ b/src/Donations/DataTransferObjects/DonationQueryData.php @@ -156,7 +156,7 @@ public static function fromObject($donationQueryObject) $self->purchaseKey = $donationQueryObject->{DonationMetaKeys::PURCHASE_KEY()->getKeyAsCamelCase()}; $self->donorIp = $donationQueryObject->{DonationMetaKeys::DONOR_IP()->getKeyAsCamelCase()}; $self->anonymous = (bool)$donationQueryObject->{DonationMetaKeys::ANONYMOUS()->getKeyAsCamelCase()}; - $self->levelId = (int)$donationQueryObject->{DonationMetaKeys::LEVEL_ID()->getKeyAsCamelCase()}; + $self->levelId = (string)$donationQueryObject->{DonationMetaKeys::LEVEL_ID()->getKeyAsCamelCase()}; $self->gatewayTransactionId = $donationQueryObject->{DonationMetaKeys::GATEWAY_TRANSACTION_ID() ->getKeyAsCamelCase()}; diff --git a/src/Donations/Factories/DonationNoteFactory.php b/src/Donations/Factories/DonationNoteFactory.php new file mode 100644 index 0000000000..3f8880d566 --- /dev/null +++ b/src/Donations/Factories/DonationNoteFactory.php @@ -0,0 +1,21 @@ + 1, + 'content' => $this->faker->text + ]; + } +} diff --git a/src/Donations/Models/Donation.php b/src/Donations/Models/Donation.php index 247ecd88a5..0f698162c1 100644 --- a/src/Donations/Models/Donation.php +++ b/src/Donations/Models/Donation.php @@ -3,13 +3,13 @@ namespace Give\Donations\Models; use DateTime; -use Exception; use Give\Donations\DataTransferObjects\DonationQueryData; use Give\Donations\Factories\DonationFactory; use Give\Donations\Properties\BillingAddress; use Give\Donations\ValueObjects\DonationMode; use Give\Donations\ValueObjects\DonationStatus; use Give\Donors\Models\Donor; +use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\Exceptions\Primitives\InvalidArgumentException; use Give\Framework\Models\Contracts\ModelCrud; use Give\Framework\Models\Contracts\ModelHasFactory; @@ -47,10 +47,11 @@ * @property string $purchaseKey * @property string $donorIp * @property bool $anonymous - * @property int $levelId + * @property string $levelId * @property string $gatewayTransactionId * @property Donor $donor * @property Subscription $subscription + * @property DonationNote[] $notes */ class Donation extends Model implements ModelCrud, ModelHasFactory { @@ -79,7 +80,7 @@ class Donation extends Model implements ModelCrud, ModelHasFactory 'subscriptionId' => ['int', 0], 'billingAddress' => BillingAddress::class, 'anonymous' => ['bool', false], - 'levelId' => ['int', 0], + 'levelId' => ['string', ''], 'gatewayTransactionId' => 'string', ]; @@ -89,6 +90,7 @@ class Donation extends Model implements ModelCrud, ModelHasFactory protected $relationships = [ 'donor' => Relationship::BELONGS_TO, 'subscription' => Relationship::BELONGS_TO, + 'notes' => Relationship::HAS_MANY, ]; /** @@ -100,7 +102,7 @@ class Donation extends Model implements ModelCrud, ModelHasFactory * * @return Donation */ - public static function find($id) + public static function find($id): Donation { return give()->donations->getById($id); } @@ -109,13 +111,9 @@ public static function find($id) * @since 2.20.0 return mutated model instance * @since 2.19.6 * - * @param array $attributes - * - * @return Donation - * * @throws Exception|InvalidArgumentException */ - public static function create(array $attributes) + public static function create(array $attributes): Donation { $donation = new static($attributes); @@ -144,11 +142,9 @@ public function save() /** * @since 2.19.6 * - * @return bool - * * @throws Exception|InvalidArgumentException */ - public function delete() + public function delete(): bool { return give()->donations->delete($this); } @@ -158,7 +154,7 @@ public function delete() * * @return ModelQueryBuilder */ - public function donor() + public function donor(): ModelQueryBuilder { return give()->donors->queryById($this->donorId); } @@ -168,7 +164,7 @@ public function donor() * * @return ModelQueryBuilder */ - public function subscription() + public function subscription(): ModelQueryBuilder { if ($this->subscriptionId) { return give()->subscriptions->queryById($this->subscriptionId); @@ -190,21 +186,19 @@ public function getSequentialId() /** * @since 2.19.6 * - * @return object[] + * @return ModelQueryBuilder */ - public function getNotes() + public function notes(): ModelQueryBuilder { - return give()->donations->getNotesByDonationId($this->id); + return give()->donations->notes->queryByDonationId($this->id); } /** * Returns the amount charged in the currency the GiveWP site is set to * * @since 2.20.0 - * - * @return Money */ - public function amountInBaseCurrency() + public function amountInBaseCurrency(): Money { return $this->amount->inBaseCurrency($this->exchangeRate); } @@ -214,10 +208,8 @@ public function amountInBaseCurrency() * donor paid $100, but the donation was charged $105 with a $5 fee, this method will return $100. * * @since 2.20.0 - * - * @return Money */ - public function intendedAmount() + public function intendedAmount(): Money { return $this->feeAmountRecovered === null ? $this->amount @@ -228,10 +220,8 @@ public function intendedAmount() * Returns the amount intended in the currency the GiveWP site is set to * * @since 2.20.0 - * - * @return Money */ - public function intendedAmountInBaseCurrency() + public function intendedAmountInBaseCurrency(): Money { return $this->intendedAmount()->inBaseCurrency($this->exchangeRate); } @@ -251,7 +241,7 @@ public function gateway(): PaymentGateway * * @inheritDoc */ - protected function getPropertyDefaults() + protected function getPropertyDefaults(): array { return array_merge(parent::getPropertyDefaults(), [ 'mode' => give_is_test_mode() ? DonationMode::TEST() : DonationMode::LIVE(), @@ -265,7 +255,7 @@ protected function getPropertyDefaults() * * @return ModelQueryBuilder */ - public static function query() + public static function query(): ModelQueryBuilder { return give()->donations->prepareQuery(); } @@ -274,10 +264,8 @@ public static function query() * @since 2.19.6 * * @param object $object - * - * @return Donation */ - public static function fromQueryBuilderObject($object) + public static function fromQueryBuilderObject($object): Donation { return DonationQueryData::fromObject($object)->toDonation(); } @@ -285,7 +273,7 @@ public static function fromQueryBuilderObject($object) /** * @return DonationFactory */ - public static function factory() + public static function factory(): DonationFactory { return new DonationFactory(static::class); } diff --git a/src/Donations/Models/DonationNote.php b/src/Donations/Models/DonationNote.php new file mode 100644 index 0000000000..68e2de5299 --- /dev/null +++ b/src/Donations/Models/DonationNote.php @@ -0,0 +1,141 @@ + 'int', + 'donationId' => 'int', + 'content' => 'string', + 'createdAt' => DateTime::class, + ]; + + /** + * @inheritdoc + */ + protected $relationships = [ + 'donation' => Relationship::BELONGS_TO, + ]; + + /** + * @unreleased + * + * @param int $id + * + * @return DonationNote + */ + public static function find($id): DonationNote + { + return give()->donations->notes->getById($id); + } + + + /** + * @unreleased + * + * @param array $attributes + * + * @return $this + * @throws Exception|InvalidArgumentException + */ + public static function create(array $attributes): DonationNote + { + $donationNote = new static($attributes); + + give()->donations->notes->insert($donationNote); + + return $donationNote; + } + + /** + * @unreleased + * + * @throws Exception|InvalidArgumentException + */ + public function save() + { + if (!$this->id) { + give()->donations->notes->insert($this); + } else{ + give()->donations->notes->update($this); + } + } + + /** + * @unreleased + * + * @return bool + * + * @throws Exception|InvalidArgumentException + */ + public function delete() + { + return give()->donations->notes->delete($this); + } + + /** + * @unreleased + * + * @return ModelQueryBuilder + */ + public static function query() + { + return give()->donations->notes->prepareQuery(); + } + + /** + * @return ModelQueryBuilder + */ + public function donation() + { + return give()->donations->queryById($this->donationId); + } + + /** + * @unreleased + * + * @param object $object + * @return DonationNote + */ + public static function fromQueryBuilderObject($object) + { + return new DonationNote([ + 'id' => (int)$object->id, + 'donationId' => (int)$object->donationId, + 'createdAt' => Temporal::toDateTime($object->createdAt), + 'content' => (string)$object->content, + ]); + } + + /** + * @return DonationNoteFactory + */ + public static function factory() + { + return new DonationNoteFactory(static::class); + } +} diff --git a/src/Donations/Repositories/DonationNotesRepository.php b/src/Donations/Repositories/DonationNotesRepository.php new file mode 100644 index 0000000000..875d923b90 --- /dev/null +++ b/src/Donations/Repositories/DonationNotesRepository.php @@ -0,0 +1,207 @@ +prepareQuery() + ->where('comment_ID', $noteId) + ->get(); + } + + /** + * @unreleased + * + * @param DonationNote $donationNote + * + * @throws Exception|InvalidArgumentException + */ + public function insert(DonationNote $donationNote) + { + $this->validateDonationNote($donationNote); + + Hooks::doAction('give_donation_note_creating', $donationNote); + + $dateCreated = Temporal::withoutMicroseconds($donationNote->createdAt ?: Temporal::getCurrentDateTime()); + $dateCreatedFormatted = Temporal::getFormattedDateTime($dateCreated); + + + DB::query('START TRANSACTION'); + + try { + DB::table('give_comments') + ->insert([ + 'comment_content' => $donationNote->content, + 'comment_date' => $dateCreatedFormatted, + 'comment_date_gmt' => get_gmt_from_date($dateCreatedFormatted), + 'comment_parent' => $donationNote->donationId, + 'comment_type' => 'donation', + ]); + } catch (Exception $exception) { + DB::query('ROLLBACK'); + + Log::error('Failed creating a donation note', compact('donationNote')); + + throw new $exception('Failed creating a donation note'); + } + + DB::query('COMMIT'); + + $donationNote->id = DB::last_insert_id(); + $donationNote->createdAt = $dateCreated; + + Hooks::doAction('give_donation_note_created', $donationNote); + } + + /** + * @unreleased + * + * @param DonationNote $donationNote + * + * @throws Exception|InvalidArgumentException + */ + public function update(DonationNote $donationNote) + { + $this->validateDonationNote($donationNote); + + Hooks::doAction('give_donation_note_updating', $donationNote); + + DB::query('START TRANSACTION'); + + try { + DB::table('give_comments') + ->where('comment_ID', $donationNote->id) + ->update([ + 'comment_content' => $donationNote->content, + 'comment_parent' => $donationNote->donationId, + 'comment_type' => 'donation', + ]); + } catch (Exception $exception) { + DB::query('ROLLBACK'); + + Log::error('Failed updating a donation note', compact('donationNote')); + + throw new $exception('Failed updating a donation note'); + } + + DB::query('COMMIT'); + + Hooks::doAction('give_donation_note_updated', $donationNote); + } + + /** + * @unreleased + * + * @param DonationNote $donationNote + * + * @return bool + * @throws Exception + */ + public function delete(DonationNote $donationNote): bool + { + DB::query('START TRANSACTION'); + + Hooks::doAction('give_donation_note_deleting', $donationNote); + + try { + DB::table('give_comments') + ->where('comment_ID', $donationNote->id) + ->delete(); + } catch (Exception $exception) { + DB::query('ROLLBACK'); + + Log::error('Failed deleting a donation note', compact('donationNote')); + + throw new $exception('Failed deleting a donation note'); + } + + DB::query('COMMIT'); + + Hooks::doAction('give_donation_note_deleted', $donationNote); + + return true; + } + + /** + * @unreleased + * + * @param int $donationId + * + * @return ModelQueryBuilder + */ + public function queryByDonationId(int $donationId): ModelQueryBuilder + { + return $this->prepareQuery() + ->where('comment_parent', $donationId) + ->orderBy('comment_ID', 'DESC'); + } + + /** + * @unreleased + * + * @param DonationNote $donationNote + * + * @return void + */ + private function validateDonationNote(DonationNote $donationNote) + { + foreach ($this->requiredDonationProperties as $key) { + if (!isset($donationNote->$key)) { + throw new InvalidArgumentException("'$key' is required."); + } + } + + if (!$donationNote->donation) { + throw new InvalidArgumentException('Invalid donationId, Donation does not exist'); + } + } + + /** + * @return ModelQueryBuilder + */ + public function prepareQuery(): ModelQueryBuilder + { + $builder = new ModelQueryBuilder(DonationNote::class); + + return $builder->from('give_comments') + ->select( + ['comment_ID', 'id'], + ['comment_parent', 'donationId'], + ['comment_content', 'content'], + ['comment_date', 'createdAt'] + ) + ->where('comment_type', 'donation'); + } +} diff --git a/src/Donations/Repositories/DonationRepository.php b/src/Donations/Repositories/DonationRepository.php index b653b61fb9..a8349ff74d 100644 --- a/src/Donations/Repositories/DonationRepository.php +++ b/src/Donations/Repositories/DonationRepository.php @@ -2,12 +2,12 @@ namespace Give\Donations\Repositories; -use Exception; use Give\Donations\Actions\GeneratePurchaseKey; use Give\Donations\Models\Donation; use Give\Donations\ValueObjects\DonationMetaKeys; use Give\Donations\ValueObjects\DonationMode; use Give\Framework\Database\DB; +use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\Exceptions\Primitives\InvalidArgumentException; use Give\Framework\Models\ModelQueryBuilder; use Give\Framework\QueryBuilder\QueryBuilder; @@ -15,7 +15,6 @@ use Give\Helpers\Call; use Give\Helpers\Hooks; use Give\Log\Log; -use Give\ValueObjects\Money; use WP_REST_Request; /** @@ -24,6 +23,18 @@ */ class DonationRepository { + /** + * @var DonationNotesRepository + */ + public $notes; + + /** + * @unreleased + */ + public function __construct() + { + $this->notes = give(DonationNotesRepository::class); + } /** * @since 2.19.6 @@ -59,6 +70,19 @@ public function getById($donationId) /** * @since 2.19.6 * + * @param $donationId + * + * @return ModelQueryBuilder + */ + public function queryById($donationId) + { + return $this->prepareQuery() + ->where('ID', $donationId); + } + + /** + * @unreleased + * * @param int $subscriptionId * * @return Donation[]|null @@ -287,7 +311,10 @@ public function delete(Donation $donation) private function getCoreDonationMetaForDatabase(Donation $donation) { $meta = [ - DonationMetaKeys::AMOUNT => $donation->amount->formatToDecimal(), + DonationMetaKeys::AMOUNT => give_sanitize_amount_for_db( + $donation->amount->formatToDecimal(), + ['currency' => $donation->amount->getCurrency()] + ), DonationMetaKeys::CURRENCY => $donation->amount->getCurrency()->getCode(), DonationMetaKeys::EXCHANGE_RATE => $donation->exchangeRate, DonationMetaKeys::GATEWAY => $donation->gatewayId, @@ -296,19 +323,18 @@ private function getCoreDonationMetaForDatabase(Donation $donation) DonationMetaKeys::LAST_NAME => $donation->lastName, DonationMetaKeys::EMAIL => $donation->email, DonationMetaKeys::FORM_ID => $donation->formId, - DonationMetaKeys::FORM_TITLE => isset($donation->formTitle) ? $donation->formTitle : $this->getFormTitle( - $donation->formId - ), - DonationMetaKeys::MODE => isset($donation->mode) ? $donation->mode->getValue( - ) : $this->getDefaultDonationMode()->getValue(), - DonationMetaKeys::PURCHASE_KEY => isset($donation->purchaseKey) - ? $donation->purchaseKey - : Call::invoke( + DonationMetaKeys::FORM_TITLE => $donation->formTitle ?? $this->getFormTitle($donation->formId), + DonationMetaKeys::MODE => isset($donation->mode) ? + $donation->mode->getValue() : + $this->getDefaultDonationMode()->getValue(), + DonationMetaKeys::PURCHASE_KEY => $donation->purchaseKey ?? Call::invoke( GeneratePurchaseKey::class, $donation->email ), - DonationMetaKeys::DONOR_IP => isset($donation->donorIp) ? $donation->donorIp : give_get_ip(), - DonationMetaKeys::GATEWAY_TRANSACTION_ID => $donation->gatewayTransactionId + DonationMetaKeys::DONOR_IP => $donation->donorIp ?? give_get_ip(), + DonationMetaKeys::GATEWAY_TRANSACTION_ID => $donation->gatewayTransactionId, + DonationMetaKeys::LEVEL_ID => $donation->levelId, + DonationMetaKeys::ANONYMOUS => (int)$donation->anonymous ]; if ($donation->feeAmountRecovered !== null) { @@ -328,14 +354,6 @@ private function getCoreDonationMetaForDatabase(Donation $donation) $meta[DonationMetaKeys::SUBSCRIPTION_ID] = $donation->subscriptionId; } - if (isset($donation->anonymous)) { - $meta[DonationMetaKeys::ANONYMOUS] = $donation->anonymous; - } - - if (isset($donation->levelId)) { - $meta[DonationMetaKeys::LEVEL_ID] = $donation->levelId; - } - return $meta; } diff --git a/src/Donations/ServiceProvider.php b/src/Donations/ServiceProvider.php index f575c1eaa9..712f154285 100644 --- a/src/Donations/ServiceProvider.php +++ b/src/Donations/ServiceProvider.php @@ -11,6 +11,7 @@ use Give\Donations\LegacyListeners\UpdateDonorPaymentIds; use Give\Donations\LegacyListeners\UpdateSequentialId; use Give\Donations\Models\Donation; +use Give\Donations\Repositories\DonationNotesRepository; use Give\Donations\Repositories\DonationRepository; use Give\Helpers\Call; use Give\Helpers\Hooks; @@ -24,6 +25,7 @@ class ServiceProvider implements ServiceProviderInterface public function register() { give()->singleton('donations', DonationRepository::class); + give()->singleton('donationNotes', DonationNotesRepository::class); } /** diff --git a/src/Donors/Models/Donor.php b/src/Donors/Models/Donor.php index 2fab29ceeb..8835cea98e 100644 --- a/src/Donors/Models/Donor.php +++ b/src/Donors/Models/Donor.php @@ -66,7 +66,7 @@ class Donor extends Model implements ModelCrud, ModelHasFactory * * @return Donor */ - public static function find($id) + public static function find($id): Donor { return give()->donors->getById($id); } @@ -74,11 +74,9 @@ public static function find($id) /** * @since 2.19.6 * - * @param string $email - * - * @return Donor + * @return Donor|null */ - public static function whereEmail($email) + public static function whereEmail(string $email) { return give()->donors->getByEmail($email); } @@ -86,11 +84,23 @@ public static function whereEmail($email) /** * @since 2.19.6 * - * @param int $userId + * @param string $donorEmail + * @return bool + */ + public function hasEmail(string $donorEmail): bool + { + $emails = array_merge($this->additionalEmails ?? [], [$this->email]); + + return in_array($donorEmail, $emails, true); + } + + /** + * @unreleased * - * @return Donor + * @param int $userId + * @return Donor|null */ - public static function whereUserId($userId) + public static function whereUserId(int $userId) { return give()->donors->getByWpUserId($userId); } @@ -105,7 +115,7 @@ public static function whereUserId($userId) * * @throws Exception|InvalidArgumentException */ - public static function create(array $attributes) + public static function create(array $attributes): Donor { $donor = new static($attributes); @@ -146,7 +156,7 @@ public function delete() * * @return ModelQueryBuilder */ - public function donations() + public function donations(): ModelQueryBuilder { return give()->donations->queryByDonorId($this->id); } @@ -156,7 +166,7 @@ public function donations() * * @return ModelQueryBuilder */ - public function subscriptions() + public function subscriptions(): ModelQueryBuilder { return give()->subscriptions->queryByDonorId($this->id); } @@ -166,7 +176,7 @@ public function subscriptions() * * @return int */ - public function totalDonations() + public function totalDonations(): int { return give()->donations->getTotalDonationCountByDonorId($this->id); } @@ -176,7 +186,7 @@ public function totalDonations() * * @return int */ - public function totalAmountDonated() + public function totalAmountDonated(): int { return array_sum(array_column($this->donations, DonationMetaKeys::AMOUNT()->getKeyAsCamelCase())); } @@ -186,7 +196,7 @@ public function totalAmountDonated() * * @return ModelQueryBuilder */ - public static function query() + public static function query(): ModelQueryBuilder { return give()->donors->prepareQuery(); } @@ -198,7 +208,7 @@ public static function query() * * @return Donor */ - public static function fromQueryBuilderObject($object) + public static function fromQueryBuilderObject($object): Donor { return DonorQueryData::fromObject($object)->toDonor(); } diff --git a/src/Donors/Repositories/DonorRepository.php b/src/Donors/Repositories/DonorRepository.php index 90fc304c26..27cbb80138 100644 --- a/src/Donors/Repositories/DonorRepository.php +++ b/src/Donors/Repositories/DonorRepository.php @@ -66,7 +66,7 @@ public function getById($donorId) * @param int $userId * @return Donor|null */ - public function getByWpUserId($userId) + public function getByWpUserId(int $userId) { // user_id can technically be 0 so make sure to return null if (!$userId) { diff --git a/src/Framework/LegacyPaymentGateways/Contracts/LegacyPaymentGatewayInterface.php b/src/Framework/LegacyPaymentGateways/Contracts/LegacyPaymentGatewayInterface.php index a8148ddc2c..09f8c6c659 100644 --- a/src/Framework/LegacyPaymentGateways/Contracts/LegacyPaymentGatewayInterface.php +++ b/src/Framework/LegacyPaymentGateways/Contracts/LegacyPaymentGatewayInterface.php @@ -10,8 +10,6 @@ interface LegacyPaymentGatewayInterface { * Returns form fields for donation form to render * * @since 2.18.0 - * - * @return string|bool */ - public function getLegacyFormFieldMarkup( $formId, $args ); + public function getLegacyFormFieldMarkup( int $formId, array $args ): string; } diff --git a/src/Framework/Models/Model.php b/src/Framework/Models/Model.php index 5a2cb78c72..16426069a1 100644 --- a/src/Framework/Models/Model.php +++ b/src/Framework/Models/Model.php @@ -180,7 +180,7 @@ public function getAttribute($key) throw new InvalidArgumentException("$key is not a valid property."); } - return isset($this->attributes[$key]) ? $this->attributes[$key] : null; + return $this->attributes[$key] ?? null; } /** diff --git a/src/Framework/PaymentGateways/Actions/GenerateGatewayRouteUrl.php b/src/Framework/PaymentGateways/Actions/GenerateGatewayRouteUrl.php index c5e6fb2589..ca9d81034e 100644 --- a/src/Framework/PaymentGateways/Actions/GenerateGatewayRouteUrl.php +++ b/src/Framework/PaymentGateways/Actions/GenerateGatewayRouteUrl.php @@ -14,7 +14,7 @@ class GenerateGatewayRouteUrl * @since 2.19.0 remove $donationId param in favor of args * */ - public function __invoke($gatewayId, $gatewayMethod, $args = null) + public function __invoke(string $gatewayId, string $gatewayMethod, array $args = []): string { $queryArgs = [ 'give-listener' => 'give-gateway', diff --git a/src/Framework/PaymentGateways/CommandHandlers/PaymentAbandonedHandler.php b/src/Framework/PaymentGateways/CommandHandlers/PaymentAbandonedHandler.php index 90734691ed..f6fec9a96f 100644 --- a/src/Framework/PaymentGateways/CommandHandlers/PaymentAbandonedHandler.php +++ b/src/Framework/PaymentGateways/CommandHandlers/PaymentAbandonedHandler.php @@ -2,6 +2,7 @@ namespace Give\Framework\PaymentGateways\CommandHandlers; +use Give\Donations\ValueObjects\DonationStatus; use Give\Framework\PaymentGateways\Commands\PaymentAbandoned; class PaymentAbandonedHandler extends PaymentHandler @@ -15,10 +16,10 @@ public function __construct(PaymentAbandoned $paymentCommand) } /** - * @return string + * @inheritDoc */ - protected function getPaymentStatus() + protected function getPaymentStatus(): DonationStatus { - return 'abandoned'; + return DonationStatus::ABANDONED(); } } diff --git a/src/Framework/PaymentGateways/CommandHandlers/PaymentCompleteHandler.php b/src/Framework/PaymentGateways/CommandHandlers/PaymentCompleteHandler.php index 9ee5fa82f4..558a934312 100644 --- a/src/Framework/PaymentGateways/CommandHandlers/PaymentCompleteHandler.php +++ b/src/Framework/PaymentGateways/CommandHandlers/PaymentCompleteHandler.php @@ -2,6 +2,7 @@ namespace Give\Framework\PaymentGateways\CommandHandlers; +use Give\Donations\ValueObjects\DonationStatus; use Give\Framework\PaymentGateways\Commands\PaymentComplete; class PaymentCompleteHandler extends PaymentHandler @@ -15,10 +16,10 @@ public function __construct(PaymentComplete $paymentCommand) } /** - * @return string + * @unreleased */ - protected function getPaymentStatus() + protected function getPaymentStatus(): DonationStatus { - return 'complete'; + return DonationStatus::COMPLETE(); } } diff --git a/src/Framework/PaymentGateways/CommandHandlers/PaymentHandler.php b/src/Framework/PaymentGateways/CommandHandlers/PaymentHandler.php index a4ae32a665..91ad5fba53 100644 --- a/src/Framework/PaymentGateways/CommandHandlers/PaymentHandler.php +++ b/src/Framework/PaymentGateways/CommandHandlers/PaymentHandler.php @@ -2,6 +2,10 @@ namespace Give\Framework\PaymentGateways\CommandHandlers; +use Give\Donations\Models\Donation; +use Give\Donations\Models\DonationNote; +use Give\Donations\ValueObjects\DonationStatus; +use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\PaymentGateways\Commands\PaymentCommand; abstract class PaymentHandler @@ -12,10 +16,11 @@ abstract class PaymentHandler protected $paymentCommand; /** + * @unreleased change return type to DonationStatus + * * @since 2.18.0 - * @return string */ - abstract protected function getPaymentStatus(); + abstract protected function getPaymentStatus(): DonationStatus; /** * @param PaymentCommand $paymentCommand @@ -26,30 +31,30 @@ public function __construct(PaymentCommand $paymentCommand) } /** - * @param PaymentCommand $paymentCommand - * @return static + * @since 2.18.0 */ - public static function make(PaymentCommand $paymentCommand) + public static function make(PaymentCommand $paymentCommand): PaymentHandler { return new static($paymentCommand); } /** + * @unreleased replace $donationId with Donation model * @since 2.18.0 * - * @param int $donationId - * @return void + * @throws Exception */ - public function handle($donationId) + public function handle(Donation $donation) { - give_update_payment_status($donationId, $this->getPaymentStatus()); - - if( $this->paymentCommand->gatewayTransactionId ) { - give_set_payment_transaction_id($donationId, $this->paymentCommand->gatewayTransactionId); - } - - foreach( $this->paymentCommand->paymentNotes as $paymentNote ) { - give_insert_payment_note( $donationId, $paymentNote ); + $donation->status = $this->getPaymentStatus(); + $donation->gatewayTransactionId = $this->paymentCommand->gatewayTransactionId; + $donation->save(); + + foreach ($this->paymentCommand->paymentNotes as $paymentNote) { + DonationNote::create([ + 'donationId' => $donation->id, + 'content' => $paymentNote + ]); } } } diff --git a/src/Framework/PaymentGateways/CommandHandlers/PaymentProcessingHandler.php b/src/Framework/PaymentGateways/CommandHandlers/PaymentProcessingHandler.php index 6ef50c64b6..8cc60b3807 100644 --- a/src/Framework/PaymentGateways/CommandHandlers/PaymentProcessingHandler.php +++ b/src/Framework/PaymentGateways/CommandHandlers/PaymentProcessingHandler.php @@ -2,6 +2,7 @@ namespace Give\Framework\PaymentGateways\CommandHandlers; +use Give\Donations\ValueObjects\DonationStatus; use Give\Framework\PaymentGateways\Commands\PaymentProcessing; class PaymentProcessingHandler extends PaymentHandler @@ -15,10 +16,10 @@ public function __construct(PaymentProcessing $paymentCommand) } /** - * @return string + * @return DonationStatus */ protected function getPaymentStatus() { - return 'processing'; + return DonationStatus::PROCESSING(); } } diff --git a/src/Framework/PaymentGateways/CommandHandlers/PaymentRefundedHandler.php b/src/Framework/PaymentGateways/CommandHandlers/PaymentRefundedHandler.php index 74294be377..636da88d0d 100644 --- a/src/Framework/PaymentGateways/CommandHandlers/PaymentRefundedHandler.php +++ b/src/Framework/PaymentGateways/CommandHandlers/PaymentRefundedHandler.php @@ -2,6 +2,7 @@ namespace Give\Framework\PaymentGateways\CommandHandlers; +use Give\Donations\ValueObjects\DonationStatus; use Give\Framework\PaymentGateways\Commands\PaymentRefunded; class PaymentRefundedHandler extends PaymentHandler @@ -15,10 +16,10 @@ public function __construct(PaymentRefunded $paymentCommand) } /** - * @return string + * @inheritdoc */ - protected function getPaymentStatus() + protected function getPaymentStatus(): DonationStatus { - return 'refunded'; + return DonationStatus::REFUNDED(); } } diff --git a/src/Framework/PaymentGateways/CommandHandlers/RedirectOffsiteHandler.php b/src/Framework/PaymentGateways/CommandHandlers/RedirectOffsiteHandler.php index 1ce112fc97..f2c3e26e63 100644 --- a/src/Framework/PaymentGateways/CommandHandlers/RedirectOffsiteHandler.php +++ b/src/Framework/PaymentGateways/CommandHandlers/RedirectOffsiteHandler.php @@ -10,11 +10,8 @@ class RedirectOffsiteHandler { /** * @since 2.18.0 - * - * @param RedirectOffsite $command - * @return RedirectResponse */ - public function __invoke(RedirectOffsite $command) + public function __invoke(RedirectOffsite $command): RedirectResponse { return response()->redirectTo($command->redirectUrl); } diff --git a/src/Framework/PaymentGateways/CommandHandlers/RespondToBrowserHandler.php b/src/Framework/PaymentGateways/CommandHandlers/RespondToBrowserHandler.php index 325c669c0f..9d93c6386a 100644 --- a/src/Framework/PaymentGateways/CommandHandlers/RespondToBrowserHandler.php +++ b/src/Framework/PaymentGateways/CommandHandlers/RespondToBrowserHandler.php @@ -10,11 +10,8 @@ class RespondToBrowserHandler { /** * @since 2.18.0 - * - * @param RespondToBrowser $command - * @return JsonResponse */ - public function __invoke(RespondToBrowser $command) + public function __invoke(RespondToBrowser $command): JsonResponse { return response()->json($command->data); } diff --git a/src/Framework/PaymentGateways/CommandHandlers/SubscriptionCompleteHandler.php b/src/Framework/PaymentGateways/CommandHandlers/SubscriptionCompleteHandler.php index 65e7222ef5..4ec3db71e2 100644 --- a/src/Framework/PaymentGateways/CommandHandlers/SubscriptionCompleteHandler.php +++ b/src/Framework/PaymentGateways/CommandHandlers/SubscriptionCompleteHandler.php @@ -2,58 +2,30 @@ namespace Give\Framework\PaymentGateways\CommandHandlers; +use Exception; +use Give\Donations\Models\Donation; +use Give\Donations\ValueObjects\DonationStatus; use Give\Framework\PaymentGateways\Commands\SubscriptionComplete; -use Give_Subscription; -use Give_Subscriptions_DB; +use Give\Subscriptions\Models\Subscription; +use Give\Subscriptions\ValueObjects\SubscriptionStatus; -class SubscriptionCompleteHandler { +class SubscriptionCompleteHandler +{ /** + * @unreleased replace logic with models * @since 2.18.0 * - * @param SubscriptionComplete $subscriptionComplete - * @param int $subscriptionId - * @param int $donationId - * @return void + * @throws Exception */ - public function __invoke(SubscriptionComplete $subscriptionComplete, $subscriptionId, $donationId) + public function __invoke(SubscriptionComplete $subscriptionComplete, Subscription $subscription, Donation $donation) { - give_update_payment_status($donationId); - give_set_payment_transaction_id($donationId, $subscriptionComplete->gatewayTransactionId); - - if (function_exists('give_recurring_update_subscription_status') && class_exists('Give_Subscriptions_DB')) { - give_recurring_update_subscription_status($subscriptionId, 'active'); - - $subscription = $this->getSubscription($subscriptionId); - - $subscription->update([ - 'profile_id' => $subscriptionComplete->gatewaySubscriptionId, - 'transaction_id' => $subscriptionComplete->gatewayTransactionId - ]); - } - } - - /** - * @since 2.18.0 - * - * @return Give_Subscriptions_DB - */ - private function subscriptions() - { - /** - * @var Give_Subscriptions_DB $subscriptions - */ - return give(Give_Subscriptions_DB::class); - } - - /** - * @since 2.18.0 - * - * @param int $subscriptionId - * - * @return Give_Subscription - */ - private function getSubscription($subscriptionId) - { - return current($this->subscriptions()->get_subscriptions(['id' => $subscriptionId])); + $donation->status = DonationStatus::COMPLETE(); + $donation->gatewayTransactionId = $subscriptionComplete->gatewayTransactionId; + $donation->save(); + + $subscription->status = SubscriptionStatus::ACTIVE(); + $subscription->gatewaySubscriptionId = $subscriptionComplete->gatewaySubscriptionId; + $subscription->transactionId = $subscriptionComplete->gatewayTransactionId; + $subscription->save(); } } diff --git a/src/Framework/PaymentGateways/Commands/PaymentCommand.php b/src/Framework/PaymentGateways/Commands/PaymentCommand.php index 1b1ec63504..fa9791738f 100644 --- a/src/Framework/PaymentGateways/Commands/PaymentCommand.php +++ b/src/Framework/PaymentGateways/Commands/PaymentCommand.php @@ -25,7 +25,7 @@ abstract class PaymentCommand implements GatewayCommand * @param string|null $gatewayTransactionId * @return static */ - public static function make($gatewayTransactionId = null) + public static function make(string $gatewayTransactionId = null): PaymentCommand { return new static($gatewayTransactionId); } @@ -35,7 +35,7 @@ public static function make($gatewayTransactionId = null) * * @param string|null $gatewayTransactionId */ - public function __construct($gatewayTransactionId = null) + public function __construct(string $gatewayTransactionId = null) { $this->gatewayTransactionId = $gatewayTransactionId; } @@ -44,9 +44,10 @@ public function __construct($gatewayTransactionId = null) * @param string|string[] ...$paymentNotes * @return $this */ - public function setPaymentNotes(...$paymentNotes) + public function setPaymentNotes(...$paymentNotes): PaymentCommand { $this->paymentNotes = $paymentNotes; + return $this; } @@ -54,9 +55,10 @@ public function setPaymentNotes(...$paymentNotes) * @param string $gatewayTransactionId * @return $this */ - public function setTransactionId($gatewayTransactionId) + public function setTransactionId(string $gatewayTransactionId): PaymentCommand { $this->gatewayTransactionId = $gatewayTransactionId; + return $this; } } diff --git a/src/Framework/PaymentGateways/Commands/RedirectOffsite.php b/src/Framework/PaymentGateways/Commands/RedirectOffsite.php index 88f54e3587..ff705ff9ae 100644 --- a/src/Framework/PaymentGateways/Commands/RedirectOffsite.php +++ b/src/Framework/PaymentGateways/Commands/RedirectOffsite.php @@ -13,10 +13,8 @@ class RedirectOffsite implements GatewayCommand { /** * @since 2.18.0 - * - * @param string $redirectUrl */ - public function __construct($redirectUrl) + public function __construct(string $redirectUrl) { $this->redirectUrl = $redirectUrl; } diff --git a/src/Framework/PaymentGateways/Commands/RespondToBrowser.php b/src/Framework/PaymentGateways/Commands/RespondToBrowser.php index 10edac6d8a..b3a34123c9 100644 --- a/src/Framework/PaymentGateways/Commands/RespondToBrowser.php +++ b/src/Framework/PaymentGateways/Commands/RespondToBrowser.php @@ -14,10 +14,8 @@ class RespondToBrowser implements GatewayCommand { /** * @since 2.18.0 - * - * @param array $data */ - public function __construct($data) + public function __construct(array $data) { $this->data = $data; } diff --git a/src/Framework/PaymentGateways/Commands/SubscriptionComplete.php b/src/Framework/PaymentGateways/Commands/SubscriptionComplete.php index 1d869de30c..adf9924c53 100644 --- a/src/Framework/PaymentGateways/Commands/SubscriptionComplete.php +++ b/src/Framework/PaymentGateways/Commands/SubscriptionComplete.php @@ -19,11 +19,8 @@ class SubscriptionComplete implements GatewayCommand { /** * @since 2.18.0 - * - * @param string $gatewayTransactionId - * @param string $gatewaySubscriptionId */ - public function __construct($gatewayTransactionId, $gatewaySubscriptionId) + public function __construct(string $gatewayTransactionId, string $gatewaySubscriptionId) { $this->gatewayTransactionId = $gatewayTransactionId; $this->gatewaySubscriptionId = $gatewaySubscriptionId; diff --git a/src/Framework/PaymentGateways/Contracts/PaymentGatewayInterface.php b/src/Framework/PaymentGateways/Contracts/PaymentGatewayInterface.php index e0771774d8..9850c20ddd 100644 --- a/src/Framework/PaymentGateways/Contracts/PaymentGatewayInterface.php +++ b/src/Framework/PaymentGateways/Contracts/PaymentGatewayInterface.php @@ -5,8 +5,8 @@ use Give\Donations\Models\Donation; use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\PaymentGateways\Commands\GatewayCommand; +use Give\Framework\PaymentGateways\Commands\RedirectOffsite; use Give\Framework\PaymentGateways\Exceptions\PaymentGatewayException; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; /** * @since 2.18.0 @@ -20,7 +20,7 @@ interface PaymentGatewayInterface extends SubscriptionModuleInterface * * @return string */ - public static function id(); + public static function id(): string; /** * Return a unique identifier for the gateway @@ -29,7 +29,7 @@ public static function id(); * * @return string */ - public function getId(); + public function getId(): string; /** * Returns a human-readable name for the gateway @@ -38,7 +38,7 @@ public function getId(); * * @return string - Translated text */ - public function getName(); + public function getName(): string; /** * Returns a human-readable label for use when a donor selects a payment method to use @@ -47,7 +47,7 @@ public function getName(); * * @return string - Translated text */ - public function getPaymentMethodLabel(); + public function getPaymentMethodLabel(): string; /** * Determines if subscriptions are supported @@ -56,20 +56,19 @@ public function getPaymentMethodLabel(); * * @return bool */ - public function supportsSubscriptions(); + public function supportsSubscriptions(): bool; /** * Create a payment with gateway * * @since 2.18.0 * - * @param GatewayPaymentData $paymentData - * - * @return GatewayCommand - * @throws PaymentGatewayException|Exception + * @return GatewayCommand|RedirectOffsite|void * + * @throws PaymentGatewayException + * @throws Exception */ - public function createPayment(GatewayPaymentData $paymentData); + public function createPayment(Donation $donation); /** * @since 2.20.0 diff --git a/src/Framework/PaymentGateways/Contracts/SubscriptionModuleInterface.php b/src/Framework/PaymentGateways/Contracts/SubscriptionModuleInterface.php index f03249b332..917b8efaef 100644 --- a/src/Framework/PaymentGateways/Contracts/SubscriptionModuleInterface.php +++ b/src/Framework/PaymentGateways/Contracts/SubscriptionModuleInterface.php @@ -4,8 +4,7 @@ use Give\Donations\Models\Donation; use Give\Framework\PaymentGateways\Commands\GatewayCommand; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; -use Give\PaymentGateways\DataTransferObjects\GatewaySubscriptionData; +use Give\Framework\PaymentGateways\Commands\RedirectOffsite; use Give\Subscriptions\Models\Subscription; interface SubscriptionModuleInterface @@ -15,21 +14,14 @@ interface SubscriptionModuleInterface * * @since 2.18.0 * - * @param GatewayPaymentData $paymentData - * @param GatewaySubscriptionData $subscriptionData - * - * @return GatewayCommand + * @return GatewayCommand|RedirectOffsite */ - public function createSubscription(GatewayPaymentData $paymentData, GatewaySubscriptionData $subscriptionData); + public function createSubscription(Donation $donation, Subscription $subscription); /** * Cancel subscription. * * @since 2.20.0 - * - * @param Subscription $subscription - * - * @return void */ public function cancelSubscription(Subscription $subscription); @@ -37,26 +29,20 @@ public function cancelSubscription(Subscription $subscription); * Returns whether the gateway supports syncing subscriptions. * * @since 2.20.0 - * - * @return bool */ - public function canSyncSubscriptionWithPaymentGateway(); + public function canSyncSubscriptionWithPaymentGateway(): bool; /** * Whether the gateway supports updating subscription amount. * * @since 2.20.0 - * - * @return bool */ - public function canUpdateSubscriptionAmount(); + public function canUpdateSubscriptionAmount(): bool; /** * Whether the gateway supports updating subscription method. * * @since 2.20.0 - * - * @return bool */ - public function canUpdateSubscriptionPaymentMethod(); + public function canUpdateSubscriptionPaymentMethod(): bool; } diff --git a/src/Framework/PaymentGateways/DonationSummary.php b/src/Framework/PaymentGateways/DonationSummary.php index 9d0a3a1450..8e2bf5b0e4 100644 --- a/src/Framework/PaymentGateways/DonationSummary.php +++ b/src/Framework/PaymentGateways/DonationSummary.php @@ -2,7 +2,7 @@ namespace Give\Framework\PaymentGateways; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; +use Give\Donations\Models\Donation; /** * @since 2.19.0 @@ -12,17 +12,15 @@ class DonationSummary /** @var int */ protected $length = 255; - /** @var GatewayPaymentData */ - protected $paymentData; + /** @var Donation */ + protected $donation; /** * @since 2.19.0 - * - * @param GatewayPaymentData $paymentData */ - public function __construct(GatewayPaymentData $paymentData) + public function __construct(Donation $donation) { - $this->paymentData = $paymentData; + $this->donation = $donation; } /** @@ -30,7 +28,7 @@ public function __construct(GatewayPaymentData $paymentData) * * @param int $length */ - public function setLength($length) + public function setLength(int $length) { $this->length = $length; } @@ -40,7 +38,7 @@ public function setLength($length) * * @return string */ - public function getSummaryWithDonor() + public function getSummaryWithDonor(): string { return $this->trimAndFilter( implode(' - ', [ @@ -55,7 +53,7 @@ public function getSummaryWithDonor() * * @return string */ - public function getSummary() + public function getSummary(): string { return $this->trimAndFilter( implode( @@ -68,28 +66,14 @@ public function getSummary() ); } - /** - * @since 2.19.0 - * - * @param string $property - * - * @return mixed|void - */ - protected function get($property) - { - if (property_exists($this->paymentData, $property)) { - return $this->paymentData->$property; - } - } - /** * @since 2.19.0 * * @return string */ - protected function getLabel() + protected function getLabel(): string { - $formId = give_get_payment_form_id($this->get('donationId')); + $formId = give_get_payment_form_id($this->donation->id); $formTitle = get_the_title($formId); return $formTitle ?: sprintf(__('Donation Form ID: %d', 'give'), $formId); } @@ -98,28 +82,25 @@ protected function getLabel() * @since 2.19.0 * @return string */ - protected function getPriceLabel() + protected function getPriceLabel(): string { - $formId = give_get_payment_form_id($this->get('donationId')); - $priceId = $this->get('priceId'); + $priceId = $this->donation->levelId; return is_numeric($priceId) - ? give_get_price_option_name($formId, $this->get('priceId')) + ? give_get_price_option_name($this->donation->formId, $this->donation->levelId) : ''; } /** * @since 2.19.0 - * - * @return string */ - protected function getDonorLabel() + protected function getDonorLabel(): string { return sprintf( '%s %s (%s)', - $this->get('donorInfo')->firstName, - $this->get('donorInfo')->lastName, - $this->get('donorInfo')->email + $this->donation->firstName, + $this->donation->lastName, + $this->donation->email ); } @@ -130,7 +111,7 @@ protected function getDonorLabel() * * @return string */ - protected function trimAndFilter($text) + protected function trimAndFilter(string $text): string { /** * @since 1.8.12 diff --git a/src/Framework/PaymentGateways/PaymentGateway.php b/src/Framework/PaymentGateways/PaymentGateway.php index 6e24cb2748..1cf25b7c83 100644 --- a/src/Framework/PaymentGateways/PaymentGateway.php +++ b/src/Framework/PaymentGateways/PaymentGateway.php @@ -2,6 +2,7 @@ namespace Give\Framework\PaymentGateways; +use Give\Donations\Models\Donation; use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\FieldsAPI\Exceptions\TypeNotSupported; use Give\Framework\LegacyPaymentGateways\Contracts\LegacyPaymentGatewayInterface; @@ -24,11 +25,9 @@ use Give\Framework\PaymentGateways\Exceptions\PaymentGatewayException; use Give\Framework\PaymentGateways\Log\PaymentGatewayLog; use Give\Framework\PaymentGateways\Routes\RouteSignature; -use Give\Framework\PaymentGateways\Traits\HasRouteMethods; use Give\Framework\PaymentGateways\Traits\HandleHttpResponses; +use Give\Framework\PaymentGateways\Traits\HasRouteMethods; use Give\Helpers\Call; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; -use Give\PaymentGateways\DataTransferObjects\GatewaySubscriptionData; use Give\Subscriptions\Models\Subscription; use function Give\Framework\Http\Response\response; @@ -68,27 +67,25 @@ public function __construct(SubscriptionModule $subscriptionModule = null) /** * @inheritDoc */ - public function supportsSubscriptions() + public function supportsSubscriptions(): bool { return isset($this->subscriptionModule); } /** * @since 2.19.0 - * - * @inheritDoc */ - public function handleCreatePayment(GatewayPaymentData $gatewayPaymentData) + public function handleCreatePayment(Donation $donation) { try { - $command = $this->createPayment($gatewayPaymentData); - $this->handleGatewayPaymentCommand($command, $gatewayPaymentData); + $command = $this->createPayment($donation); + $this->handleGatewayPaymentCommand($command, $donation); } catch (Exception $exception) { PaymentGatewayLog::error( $exception->getMessage(), [ 'Payment Gateway' => $this->getId(), - 'Donation Data' => $gatewayPaymentData, + 'Donation' => $donation, ] ); @@ -104,20 +101,19 @@ public function handleCreatePayment(GatewayPaymentData $gatewayPaymentData) /** * @since 2.19.0 * - * @inheritDoc */ - public function handleCreateSubscription(GatewayPaymentData $paymentData, GatewaySubscriptionData $subscriptionData) + public function handleCreateSubscription(Donation $donation, Subscription $subscription) { try { - $command = $this->createSubscription($paymentData, $subscriptionData); - $this->handleGatewaySubscriptionCommand($command, $paymentData, $subscriptionData); + $command = $this->createSubscription($donation, $subscription); + $this->handleGatewaySubscriptionCommand($command, $donation, $subscription); } catch (Exception $exception) { PaymentGatewayLog::error( $exception->getMessage(), [ 'Payment Gateway' => $this->getId(), - 'Donation Data' => $paymentData, - 'Subscription Data' => $subscriptionData, + 'Donation' => $donation, + 'Subscription' => $subscription, ] ); @@ -136,9 +132,9 @@ public function handleCreateSubscription(GatewayPaymentData $paymentData, Gatewa * * @inheritDoc */ - public function createSubscription(GatewayPaymentData $paymentData, GatewaySubscriptionData $subscriptionData) + public function createSubscription(Donation $donation, Subscription $subscription): GatewayCommand { - return $this->subscriptionModule->createSubscription($paymentData, $subscriptionData); + return $this->subscriptionModule->createSubscription($donation, $subscription); } /** @@ -152,7 +148,7 @@ public function cancelSubscription(Subscription $subscription) /** * @inheritDoc */ - public function canSyncSubscriptionWithPaymentGateway() + public function canSyncSubscriptionWithPaymentGateway(): bool { return $this instanceof SubscriptionTransactionsSynchronizable || $this->subscriptionModule->canSyncSubscriptionWithPaymentGateway(); @@ -161,7 +157,7 @@ public function canSyncSubscriptionWithPaymentGateway() /** * @inheritDoc */ - public function canUpdateSubscriptionAmount() + public function canUpdateSubscriptionAmount(): bool { return $this instanceof SubscriptionAmountEditable || $this->subscriptionModule->canUpdateSubscriptionAmount(); @@ -170,7 +166,7 @@ public function canUpdateSubscriptionAmount() /** * @inheritDoc */ - public function canUpdateSubscriptionPaymentMethod() + public function canUpdateSubscriptionPaymentMethod(): bool { return $this instanceof SubscriptionPaymentMethodEditable || $this->subscriptionModule->canUpdateSubscriptionPaymentMethod(); @@ -181,19 +177,17 @@ public function canUpdateSubscriptionPaymentMethod() * * @since 2.18.0 * - * @param GatewayCommand $command - * @param GatewayPaymentData $gatewayPaymentData - * * @throws TypeNotSupported + * @throws Exception */ - public function handleGatewayPaymentCommand(GatewayCommand $command, GatewayPaymentData $gatewayPaymentData) + public function handleGatewayPaymentCommand(GatewayCommand $command, Donation $donation) { if ($command instanceof PaymentComplete) { $handler = new PaymentCompleteHandler($command); - $handler->handle($gatewayPaymentData->donationId); + $handler->handle($donation); - $response = response()->redirectTo($gatewayPaymentData->redirectUrl); + $response = response()->redirectTo(give_get_success_page_uri()); $this->handleResponse($response); } @@ -201,9 +195,9 @@ public function handleGatewayPaymentCommand(GatewayCommand $command, GatewayPaym if ($command instanceof PaymentProcessing) { $handler = new PaymentProcessingHandler($command); - $handler->handle($gatewayPaymentData->donationId); + $handler->handle($donation); - $response = response()->redirectTo($gatewayPaymentData->redirectUrl); + $response = response()->redirectTo(give_get_success_page_uri()); $this->handleResponse($response); } @@ -233,26 +227,22 @@ public function handleGatewayPaymentCommand(GatewayCommand $command, GatewayPaym * * @since 2.18.0 * - * @param GatewayCommand $command - * @param GatewayPaymentData $gatewayPaymentData - * @param GatewaySubscriptionData $gatewaySubscriptionData - * * @throws TypeNotSupported */ public function handleGatewaySubscriptionCommand( GatewayCommand $command, - GatewayPaymentData $gatewayPaymentData, - GatewaySubscriptionData $gatewaySubscriptionData + Donation $donation, + Subscription $subscription ) { if ($command instanceof SubscriptionComplete) { Call::invoke( SubscriptionCompleteHandler::class, $command, - $gatewaySubscriptionData->subscriptionId, - $gatewayPaymentData->donationId + $subscription, + $donation ); - $response = response()->redirectTo($gatewayPaymentData->redirectUrl); + $response = response()->redirectTo(give_get_success_page_uri()); $this->handleResponse($response); } @@ -270,14 +260,8 @@ public function handleGatewaySubscriptionCommand( * * @since 2.18.0 * @since 2.19.0 remove $donationId param in favor of args - * - * @param string $gatewayMethod - * @param array|null $args - * - * @return string - * */ - public function generateGatewayRouteUrl($gatewayMethod, $args = null) + public function generateGatewayRouteUrl(string $gatewayMethod, array $args = []): string { return Call::invoke(GenerateGatewayRouteUrl::class, $this->getId(), $gatewayMethod, $args); } @@ -288,15 +272,8 @@ public function generateGatewayRouteUrl($gatewayMethod, $args = null) * @since 2.19.5 replace nonce with hash and expiration * @since 2.19.4 replace RouteSignature args with unique donationId * @since 2.19.0 - * - * @param string $gatewayMethod - * @param int $donationId - * @param array|null $args - * - * @return string - * */ - public function generateSecureGatewayRouteUrl($gatewayMethod, $donationId, $args = null) + public function generateSecureGatewayRouteUrl(string $gatewayMethod, int $donationId, array $args = []): string { $signature = new RouteSignature($this->getId(), $gatewayMethod, $donationId); @@ -318,13 +295,8 @@ public function generateSecureGatewayRouteUrl($gatewayMethod, $donationId, $args * 2. Return json response if processing payment on ajax. * * @since 2.19.0 - * - * @param Exception|PaymentGatewayException $exception - * @param string $message - * - * @return void */ - private function handleExceptionResponse($exception, $message) + private function handleExceptionResponse(Exception $exception, string $message) { if ($exception instanceof PaymentGatewayException) { $message = $exception->getMessage(); @@ -340,14 +312,10 @@ private function handleExceptionResponse($exception, $message) /** * @since 2.20.0 - * - * @param string $method - * - * @return bool */ - public function supportsMethodRoute($method) + public function supportsMethodRoute(string $method): bool { - if ( $this->subscriptionModule && $this->subscriptionModule->supportsMethodRoute($method) ) { + if ($this->subscriptionModule && $this->subscriptionModule->supportsMethodRoute($method)) { return true; } @@ -363,7 +331,7 @@ public function supportsMethodRoute($method) */ public function callRouteMethod($method, $queryParams) { - if ( $this->subscriptionModule && $this->subscriptionModule->supportsMethodRoute($method) ) { + if ($this->subscriptionModule && $this->subscriptionModule->supportsMethodRoute($method)) { return $this->subscriptionModule->callRouteMethod($method, $queryParams); } diff --git a/src/Framework/PaymentGateways/SubscriptionModule.php b/src/Framework/PaymentGateways/SubscriptionModule.php index c2d97caabe..2aa3b35974 100644 --- a/src/Framework/PaymentGateways/SubscriptionModule.php +++ b/src/Framework/PaymentGateways/SubscriptionModule.php @@ -33,7 +33,7 @@ public function setGateway(PaymentGateway $gateway) /** * @inheritDoc */ - public function canSyncSubscriptionWithPaymentGateway() + public function canSyncSubscriptionWithPaymentGateway(): bool { return $this instanceof SubscriptionTransactionsSynchronizable; } @@ -41,7 +41,7 @@ public function canSyncSubscriptionWithPaymentGateway() /** * @inheritDoc */ - public function canUpdateSubscriptionAmount() + public function canUpdateSubscriptionAmount(): bool { return $this instanceof SubscriptionAmountEditable; } @@ -49,7 +49,7 @@ public function canUpdateSubscriptionAmount() /** * @inheritDoc */ - public function canUpdateSubscriptionPaymentMethod() + public function canUpdateSubscriptionPaymentMethod(): bool { return $this instanceof SubscriptionPaymentMethodEditable; } diff --git a/src/LegacyPaymentGateways/Adapters/LegacyPaymentGatewayAdapter.php b/src/LegacyPaymentGateways/Adapters/LegacyPaymentGatewayAdapter.php index 15563385c6..eeeaaa5091 100644 --- a/src/LegacyPaymentGateways/Adapters/LegacyPaymentGatewayAdapter.php +++ b/src/LegacyPaymentGateways/Adapters/LegacyPaymentGatewayAdapter.php @@ -2,12 +2,14 @@ namespace Give\LegacyPaymentGateways\Adapters; +use Exception; +use Give\Donors\Models\Donor; use Give\Framework\PaymentGateways\Contracts\PaymentGatewayInterface; -use Give\PaymentGateways\Actions\CreatePaymentAction; -use Give\PaymentGateways\Actions\CreateSubscriptionAction; use Give\PaymentGateways\DataTransferObjects\FormData; -use Give\PaymentGateways\DataTransferObjects\GiveInsertPaymentData; use Give\PaymentGateways\DataTransferObjects\SubscriptionData; +use Give\Subscriptions\Models\Subscription; +use Give\Subscriptions\ValueObjects\SubscriptionPeriod; +use Give\Subscriptions\ValueObjects\SubscriptionStatus; /** * Class LegacyPaymentGatewayAdapter @@ -21,105 +23,149 @@ class LegacyPaymentGatewayAdapter * * @since 2.18.0 * @since 2.19.0 Added missing $args parameter for ID prefixing and general backwards compatibility. - * - * @param int $formId - * @param array $args - * @param PaymentGatewayInterface $registeredGateway - * - * @return string|bool */ - public function getLegacyFormFieldMarkup($formId, $args, $registeredGateway) - { + public function getLegacyFormFieldMarkup( + int $formId, + array $args, + PaymentGatewayInterface $registeredGateway + ): string { return $registeredGateway->getLegacyFormFieldMarkup($formId, $args); } /** * First we create a payment, then move on to the gateway processing * - * @since 2.18.0 + * @unreleased Replace give_insert_payment with donation model. * @since 2.19.0 Replace is_recurring with is_donation_recurring to detect recurring donations. + * @since 2.18.0 * - * @param array $legacyDonationData Legacy Donation Data - * @param PaymentGatewayInterface $registeredGateway - * - * @return void + * @throws Exception */ - public function handleBeforeGateway($legacyDonationData, $registeredGateway) + public function handleBeforeGateway(array $legacyDonationData, PaymentGatewayInterface $registeredGateway) { - $formData = FormData::fromRequest($legacyDonationData); + $formData = FormData::fromRequest($legacyDonationData); $this->validateGatewayNonce($formData->gatewayNonce); - $donationId = $this->createPayment($formData->toGiveInsertPaymentData()); + $donor = $this->getOrCreateDonor( + $formData->donorInfo->wpUserId, + $formData->donorInfo->email, + $formData->donorInfo->firstName, + $formData->donorInfo->lastName + ); + + $donation = $formData->toDonation($donor->id); + $donation->save(); - $gatewayPaymentData = $formData->toGatewayPaymentData($donationId); + $this->setSession($donation->id); - if (give_recurring_is_donation_recurring($formData->legacyDonationData)) { + if (give_recurring_is_donation_recurring($legacyDonationData)) { $subscriptionData = SubscriptionData::fromRequest($legacyDonationData); - $subscriptionId = $this->createSubscription($donationId, $formData, $subscriptionData); - $gatewaySubscriptionData = $subscriptionData->toGatewaySubscriptionData($subscriptionId); + $subscription = Subscription::create([ + 'amount' => $donation->amount, + 'period' => new SubscriptionPeriod($subscriptionData->period), + 'frequency' => (int)$subscriptionData->frequency, + 'donorId' => $donor->id, + 'installments' => (int)$subscriptionData->times, + 'status' => SubscriptionStatus::PENDING(), + 'donationFormId' => $formData->formId + ]); + + give()->subscriptions->updateLegacyColumns( + $subscription->id, + [ + 'parent_payment_id' => $donation->id, + 'expiration' => $subscription->expiration() + ] + ); - $registeredGateway->handleCreateSubscription($gatewayPaymentData, $gatewaySubscriptionData); + $registeredGateway->handleCreateSubscription($donation, $subscription); } - $registeredGateway->handleCreatePayment($gatewayPaymentData); + $registeredGateway->handleCreatePayment($donation); } /** - * Create the payment + * Validate Gateway Nonce * * @since 2.18.0 - * - * @param GiveInsertPaymentData $giveInsertPaymentData - * - * @return int */ - private function createPayment(GiveInsertPaymentData $giveInsertPaymentData) + private function validateGatewayNonce(string $gatewayNonce) { - /** @var CreatePaymentAction $createPaymentAction */ - $createPaymentAction = give(CreatePaymentAction::class); - - return $createPaymentAction($giveInsertPaymentData); + if (!wp_verify_nonce($gatewayNonce, 'give-gateway')) { + wp_die( + esc_html__( + 'We\'re unable to recognize your session. Please refresh the screen to try again; otherwise contact your website administrator for assistance.', + 'give' + ), + esc_html__('Error', 'give'), + ['response' => 403] + ); + } } /** - * Create the payment + * Set donation id to purchase session for use in the donation receipt. * - * @since 2.18.0 + * @unreleased * - * @param int $donationId - * @param FormData $formData - * @param SubscriptionData $subscriptionData + * @param $donationId * - * @return int + * @return void */ - private function createSubscription($donationId, FormData $formData, SubscriptionData $subscriptionData) + private function setSession($donationId) { - /** @var CreateSubscriptionAction $createSubscriptionAction */ - $createSubscriptionAction = give(CreateSubscriptionAction::class); + $purchaseSession = (array)give()->session->get('give_purchase'); - return $createSubscriptionAction($donationId, $formData, $subscriptionData); + if ($purchaseSession && array_key_exists('purchase_key', $purchaseSession)) { + $purchaseSession['donation_id'] = $donationId; + give()->session->set('give_purchase', $purchaseSession); + } } /** - * Validate Gateway Nonce + * @unreleased * - * @since 2.18.0 + * @param int|null $userId + * @param string $donorEmail + * @param string $firstName + * @param string $lastName * - * @param string $gatewayNonce + * @return Donor + * @throws Exception */ - private function validateGatewayNonce($gatewayNonce) - { - if (!wp_verify_nonce($gatewayNonce, 'give-gateway')) { - wp_die( - esc_html__( - 'We\'re unable to recognize your session. Please refresh the screen to try again; otherwise contact your website administrator for assistance.', - 'give' - ), - esc_html__('Error', 'give'), - ['response' => 403] - ); + private function getOrCreateDonor( + int $userId, + string $donorEmail, + string $firstName, + string $lastName + ): Donor { + // first check if donor exists as a user + $donor = Donor::whereUserId($userId); + + // If they exist as a donor & user then make sure they don't already own this email before adding to their additional emails list.. + if ($donor && !$donor->hasEmail($donorEmail)) { + $donor->additionalEmails = array_merge($donor->additionalEmails ?? [], [$donorEmail]); + $donor->save(); } + + // if donor is not a user than check for any donor matching this email + if (!$donor) { + $donor = Donor::whereEmail($donorEmail); + } + + // if no donor exists then create a new one using their personal information from the form. + if (!$donor) { + $donor = Donor::create([ + 'name' => trim("$firstName $lastName"), + 'firstName' => $firstName, + 'lastName' => $lastName, + 'email' => $donorEmail, + 'userId' => $userId ?: null + ]); + } + + return $donor; } } diff --git a/src/LegacyPaymentGateways/DataTransferObjects/LegacyDonationData.php b/src/LegacyPaymentGateways/DataTransferObjects/LegacyDonationData.php deleted file mode 100644 index e911d1ebfd..0000000000 --- a/src/LegacyPaymentGateways/DataTransferObjects/LegacyDonationData.php +++ /dev/null @@ -1,61 +0,0 @@ -paymentData = $paymentData; - $this->paymentMethodId = $paymentMethodId; - } - - /** - * @since 2.19.0 - * @return array - */ - public function toArray() - { - return [ - 'source_id' => $this->paymentMethodId, - 'donation_id' => $this->paymentData->donationId, - 'post_data' => [ - 'give-form-id' => give_get_payment_form_id( $this->paymentData->donationId ), - 'give-price-id' => $this->paymentData->priceId, - 'give-form-title' => give_get_donation_form_title( $this->paymentData->donationId ), - ], - 'user_info' => [ - 'first_name' => $this->paymentData->donorInfo->firstName, - 'last_name' => $this->paymentData->donorInfo->lastName, - 'user_email' => $this->paymentData->donorInfo->email, - ], - ]; - } - - /** - * @since 2.19.0 - * @return array - */ - public function toArrayWithDescription() - { - return $this->toArray() + [ - 'description' => give_payment_gateway_donation_summary( $this->toArray(), false ) - ]; - } -} diff --git a/src/LegacySubscriptions/includes/give-recurring-cache.php b/src/LegacySubscriptions/includes/give-recurring-cache.php index aabee25f80..98b9e45ac0 100644 --- a/src/LegacySubscriptions/includes/give-recurring-cache.php +++ b/src/LegacySubscriptions/includes/give-recurring-cache.php @@ -57,7 +57,6 @@ public function setup() { add_action( 'give_subscription_inserted', array( $this, 'flush_on_subscription_insert' ) ); add_action( 'give_subscription_deleted', array( $this, 'flush_on_subscription_delete' ), 10, 2 ); - add_action( 'give_subscription_updated', array( $this, 'flush_on_subscription_update' ), 10, 4 ); add_action( 'give_cache_filter_group_name', array( $this, 'filter_group_name' ), 999, 2 ); add_action( 'give_deleted_give-donations_cache', array( $this, 'flush_on_donation_edit' ), 10 ); add_action( 'before_delete_post', array( $this, 'flush_on_donation_delete' ), 10 ); diff --git a/src/LegacySubscriptions/includes/give-subscriptions-db.php b/src/LegacySubscriptions/includes/give-subscriptions-db.php index 1fcc2f5a29..bc4df624be 100644 --- a/src/LegacySubscriptions/includes/give-subscriptions-db.php +++ b/src/LegacySubscriptions/includes/give-subscriptions-db.php @@ -3,9 +3,9 @@ * Give Recurring Subscription DB * * @package Give - * @copyright Copyright (c) 2016, GiveWP - * @license https://opensource.org/licenses/gpl-license GNU Public License * @since 1.0 + * @license https://opensource.org/licenses/gpl-license GNU Public License + * @copyright Copyright (c) 2016, GiveWP */ // Exit if accessed directly @@ -48,7 +48,7 @@ public function __construct() */ public function get_columns() { - return array( + return [ 'id' => '%d', 'customer_id' => '%d', 'period' => '%s', @@ -65,7 +65,7 @@ public function get_columns() 'status' => '%s', 'notes' => '%s', 'profile_id' => '%s', - ); + ]; } @@ -77,7 +77,7 @@ public function get_columns() */ public function get_column_defaults() { - return array( + return [ 'customer_id' => 0, 'period' => '', 'frequency' => 1, @@ -93,22 +93,23 @@ public function get_column_defaults() 'status' => '', 'notes' => '', 'profile_id' => '', - ); + ]; } /** * Get subscription by specific data * - * @param int $column - * @param int $row_id - * - * @return mixed|object * @since 1.6 * + * @param int $row_id + * + * @param int $column + * + * @return mixed|object */ public function get_by($column, $row_id) { - $cache_key = Give_Cache::get_key("{$column}_{$row_id}", array($column, $row_id), false); + $cache_key = Give_Cache::get_key("{$column}_{$row_id}", [$column, $row_id], false); $subscription = Give_Recurring_Cache::get_subscription($cache_key); if (is_null($subscription)) { @@ -122,10 +123,11 @@ public function get_by($column, $row_id) /** * Get subscription * - * @param int $row_id + * @since 1.6 + * + * @param int $row_id * * @return mixed|object - * @since 1.6 */ public function get($row_id) { @@ -143,18 +145,21 @@ public function get($row_id) /** * Update subscription * - * @param int $row_id - * @param array $data - * @param string $where - * - * @return bool * @since 1.6 * + * @param array $data + * @param string $where + * + * @param int $row_id + * + * @return bool */ - public function update($row_id, $data = array(), $where = '') + public function update($row_id, $data = [], $where = '') { $status = parent::update($row_id, $data, $where); + (new Give_Recurring_Cache())->flush_on_subscription_update($status, $row_id, $data, $where); + /** * Fire the action when subscriptions updated * @@ -162,17 +167,18 @@ public function update($row_id, $data = array(), $where = '') */ do_action('give_subscription_updated', $status, $row_id, $data, $where); + return $status; } /** * Create subscription * - * @param array $data - * - * @return int|mixed * @since 1.6 * + * @param array $data + * + * @return int|mixed */ public function create($data) { @@ -191,7 +197,7 @@ public function create($data) /** * Delete subscription * - * @param int $subscription_id + * @param int $subscription_id * * @return bool */ @@ -215,18 +221,18 @@ public function delete($subscription_id = 0) /** * Retrieve all subscriptions for a donor. * - * @param array $args + * @since 1.0 + * + * @param array $args * * @access public * @return Give_Subscription[] - * @since 1.0 - * */ - public function get_subscriptions($args = array()) + public function get_subscriptions($args = []) { global $wpdb; - $defaults = array( + $defaults = [ 'number' => 20, 'offset' => 0, 'search' => '', @@ -234,7 +240,7 @@ public function get_subscriptions($args = array()) 'customer_id' => 0, 'orderby' => 'id', 'order' => 'DESC', - ); + ]; $args = wp_parse_args($args, $defaults); @@ -284,11 +290,11 @@ public function get_subscriptions($args = array()) /** * Count the total number of subscriptions in the database. * - * @param array $args + * @param array $args * * @return int|array/null */ - public function count($args = array()) + public function count($args = []) { global $wpdb; @@ -309,7 +315,7 @@ public function count($args = array()) // Simplify result if query for groupBy. if ($group_by_args && $result) { - $temp = array(); + $temp = []; foreach ($result as $data) { $temp[$data[$group_by_args]] = $data['COUNT(id)']; } @@ -369,7 +375,7 @@ public function create_table() /** * Get Renewing Subscriptions * - * @param string $period + * @param string $period * * @return array|bool|mixed|null|object */ @@ -377,17 +383,17 @@ public function get_renewing_subscriptions($period = '+1month') { global $wpdb; - $args = array( + $args = [ 'number' => 99999, 'status' => 'active', 'offset' => 0, 'orderby' => 'id', 'order' => 'DESC', - 'expiration' => array( + 'expiration' => [ 'start' => date('Y-m-d H:i:s', strtotime($period . ' midnight')), 'end' => date('Y-m-d H:i:s', strtotime($period . ' midnight') + (DAY_IN_SECONDS - 1)), - ), - ); + ], + ]; $cache_key = Give_Cache::get_key('give_renewing_subscriptions', $args, false); $subscriptions = Give_Recurring_Cache::get_db_query($cache_key); @@ -412,7 +418,7 @@ public function get_renewing_subscriptions($period = '+1month') /** * Get expiring subscriptions. * - * @param string $period + * @param string $period * * @return array|bool|mixed|null|object */ @@ -420,17 +426,17 @@ public function get_expiring_subscriptions($period = '+1month') { global $wpdb; - $args = array( + $args = [ 'number' => 99999, 'status' => 'active', 'offset' => 0, 'orderby' => 'id', 'order' => 'DESC', - 'expiration' => array( + 'expiration' => [ 'start' => date('Y-m-d H:i:s', strtotime($period . ' midnight')), 'end' => date('Y-m-d H:i:s', strtotime($period . ' midnight') + (DAY_IN_SECONDS - 1)), - ), - ); + ], + ]; $cache_key = Give_Cache::get_key('give_expiring_subscriptions', $args, false); $subscriptions = Give_Recurring_Cache::get_db_query($cache_key); @@ -455,12 +461,13 @@ public function get_expiring_subscriptions($period = '+1month') /** * Generate a cache key from args. * - * @param $prefix + * @deprecated 1.6 + * * @param $args * - * @return string - * @deprecated 1.6 + * @param $prefix * + * @return string */ protected function generate_cache_key($prefix, $args) { @@ -470,11 +477,11 @@ protected function generate_cache_key($prefix, $args) /** * Build the query args for subscriptions. * - * @param array $args + * @param array $args * * @return string The mysql "where" query part. */ - public function generate_where_clause($args = array()) + public function generate_where_clause($args = []) { $where = ' WHERE 1=1'; @@ -578,7 +585,7 @@ public function generate_where_clause($args = array()) /** * Build the query args for subscriptions. * - * @param string $groupby + * @param string $groupby * * @return string The mysql "where" query part. */ @@ -638,7 +645,7 @@ private function mysql_where_args_search($args) LIKE '%%%s%%'", $args['search'] ); - $subscription_donor_id = array(); + $subscription_donor_id = []; $donor_ids = $wpdb->get_results($query, ARRAY_A); if (!empty($donor_ids) && count($donor_ids) > 0) { foreach ($donor_ids as $key => $val) { diff --git a/src/PaymentGateways/Actions/RegisterPaymentGateways.php b/src/PaymentGateways/Actions/RegisterPaymentGateways.php index bcaa9a679d..03f346f6c8 100644 --- a/src/PaymentGateways/Actions/RegisterPaymentGateways.php +++ b/src/PaymentGateways/Actions/RegisterPaymentGateways.php @@ -10,6 +10,7 @@ use Give\PaymentGateways\Gateways\Stripe\CheckoutGateway as StripeCheckoutGateway; use Give\PaymentGateways\Gateways\Stripe\CreditCardGateway as StripeCreditCardGateway; use Give\PaymentGateways\Gateways\Stripe\SEPAGateway as StripeSEPAGateway; +use Give\PaymentGateways\Gateways\TestGateway\TestGateway; use Give\PaymentGateways\PayPalCommerce\PayPalCommerce; class RegisterPaymentGateways @@ -21,7 +22,7 @@ class RegisterPaymentGateways */ public $gateways = [ // When complete, the Test Gateway will eventually replace The legacy Manual Gateway. - //TestGateway::class, + TestGateway::class, //TestGatewayOffsite::class, StripeBECSGateway::class, StripeCheckoutGateway::class, @@ -43,7 +44,7 @@ class RegisterPaymentGateways * @throws InvalidArgumentException|Exception * */ - public function __invoke(array $gateways) + public function __invoke(array $gateways): array { /** @var PaymentGatewayRegister $paymentGatewayRegister */ $paymentGatewayRegister = give(PaymentGatewayRegister::class); diff --git a/src/PaymentGateways/DataTransferObjects/FormData.php b/src/PaymentGateways/DataTransferObjects/FormData.php index d5ff7e78a2..7429691104 100644 --- a/src/PaymentGateways/DataTransferObjects/FormData.php +++ b/src/PaymentGateways/DataTransferObjects/FormData.php @@ -6,6 +6,7 @@ use Give\Donations\Models\Donation; use Give\Donations\Properties\BillingAddress; use Give\Donations\ValueObjects\DonationStatus; +use Give\Framework\Support\ValueObjects\Money; use Give\ValueObjects\Address; use Give\ValueObjects\CardInfo; use Give\ValueObjects\DonorInfo; @@ -100,27 +101,19 @@ class FormData * @var DonorInfo */ public $donorInfo; - /** - * This property is only for internal use. It will be removed in the future. - * We will use this property to gracefully deprecate action and filter which exist in existing donation flow. - * - * @deprecated - * @var array - */ - public $legacyDonationData; + + /** @var bool */ + public $anonymous; /** * Convert data from request into DTO * * @since 2.18.0 - * - * @return self */ - public static function fromRequest(array $request) + public static function fromRequest(array $request): FormData { $self = new static(); - $self->legacyDonationData = $request; $self->price = $request['price']; $self->date = $request['date']; $self->purchaseKey = $request['purchase_key']; @@ -129,7 +122,7 @@ public static function fromRequest(array $request) $self->postData = $request['post_data']; $self->formTitle = $request['post_data']['give-form-title']; $self->formId = (int)$request['post_data']['give-form-id']; - $self->priceId = isset($request['post_data']['give-price-id']) ? $request['post_data']['give-price-id'] : ''; + $self->priceId = $request['post_data']['give-price-id'] ?? ''; $self->formIdPrefix = $request['post_data']['give-form-id-prefix']; $self->currentUrl = $request['post_data']['give-current-url']; $self->formMinimum = $request['post_data']['give-form-minimum']; @@ -143,7 +136,7 @@ public static function fromRequest(array $request) 'firstName' => $request['user_info']['first_name'], 'lastName' => $request['user_info']['last_name'], 'email' => $request['user_info']['email'], - 'honorific' => ! empty($request['user_info']['title']) ? $request['user_info']['title'] : '', + 'honorific' => !empty($request['user_info']['title']) ? $request['user_info']['title'] : '', 'address' => $request['user_info']['address'] ]); $self->cardInfo = CardInfo::fromArray([ @@ -162,22 +155,23 @@ public static function fromRequest(array $request) 'postalCode' => $request['card_info']['card_zip'], ]); + $self->anonymous = isset($request['post_data']['give_anonymous_donation']) && (bool)absint( + $request['post_data']['give_anonymous_donation'] + ); + return $self; } /** * @since 2.19.6 - * - * @return Donation * @throws Exception */ - public function toDonation($donorId) + public function toDonation($donorId): Donation { return new Donation([ 'status' => DonationStatus::PENDING(), - 'gateway' => $this->paymentGateway, - 'amount' => (int)$this->price, - 'currency' => $this->currency, + 'gatewayId' => $this->paymentGateway, + 'amount' => Money::fromDecimal($this->price, $this->currency), 'donorId' => $donorId, 'firstName' => $this->donorInfo->firstName, 'lastName' => $this->donorInfo->lastName, @@ -192,50 +186,8 @@ public function toDonation($donorId) 'address1' => $this->billingAddress->line1, 'address2' => $this->billingAddress->line2 ]), - 'levelId' => (int)$this->priceId - ]); - } - - /** - * - * @return GiveInsertPaymentData - */ - public function toGiveInsertPaymentData() - { - return GiveInsertPaymentData::fromArray([ - 'price' => $this->price, - 'formTitle' => $this->formTitle, - 'formId' => $this->formId, - 'priceId' => $this->priceId, - 'date' => $this->date, - 'donorEmail' => $this->donorInfo->email, - 'purchaseKey' => $this->purchaseKey, - 'currency' => $this->currency, - 'userInfo' => $this->userInfo, - 'paymentGateway' => $this->paymentGateway - ]); - } - - /** - * @param int $donationId - * - * @return GatewayPaymentData - */ - public function toGatewayPaymentData($donationId) - { - return GatewayPaymentData::fromArray([ - 'legacyPaymentData' => $this->legacyDonationData, - 'amount' => $this->amount, - 'currency' => $this->currency, - 'date' => $this->date, - 'price' => $this->price, - 'priceId' => $this->priceId, - 'gatewayId' => $this->paymentGateway, - 'donationId' => $donationId, - 'purchaseKey' => $this->purchaseKey, - 'donorInfo' => $this->donorInfo, - 'cardInfo' => $this->cardInfo, - 'billingAddress' => $this->billingAddress, + 'levelId' => $this->priceId, + 'anonymous' => $this->anonymous ]); } } diff --git a/src/PaymentGateways/DataTransferObjects/GatewayPaymentData.php b/src/PaymentGateways/DataTransferObjects/GatewayPaymentData.php deleted file mode 100644 index e2c11ce441..0000000000 --- a/src/PaymentGateways/DataTransferObjects/GatewayPaymentData.php +++ /dev/null @@ -1,100 +0,0 @@ -legacyPaymentData = $array['legacyPaymentData']; - $self->price = $array['price']; - $self->priceId = $array['priceId']; - $self->currency = $array['currency']; - $self->amount = $array['amount']; - $self->date = $array['date']; - $self->gatewayId = $array['gatewayId']; - $self->donationId = $array['donationId']; - $self->purchaseKey = $array['purchaseKey']; - $self->donorInfo = $array['donorInfo']; - $self->cardInfo = $array['cardInfo']; - $self->billingAddress = $array['billingAddress']; - $self->redirectUrl = give_get_success_page_uri(); - - return $self; - } -} diff --git a/src/PaymentGateways/DataTransferObjects/GatewaySubscriptionData.php b/src/PaymentGateways/DataTransferObjects/GatewaySubscriptionData.php deleted file mode 100644 index 0ba19113f7..0000000000 --- a/src/PaymentGateways/DataTransferObjects/GatewaySubscriptionData.php +++ /dev/null @@ -1,48 +0,0 @@ -period = $array['period']; - $self->times = $array['times']; - $self->frequency = $array['frequency']; - $self->subscriptionId = $array['subscriptionId']; - - return $self; - } -} diff --git a/src/PaymentGateways/DataTransferObjects/SubscriptionData.php b/src/PaymentGateways/DataTransferObjects/SubscriptionData.php index d3003115cf..be6333b8b1 100644 --- a/src/PaymentGateways/DataTransferObjects/SubscriptionData.php +++ b/src/PaymentGateways/DataTransferObjects/SubscriptionData.php @@ -27,10 +27,8 @@ class SubscriptionData * Convert data from request into DTO * * @since 2.18.0 - * - * @return self */ - public static function fromRequest(array $request) + public static function fromRequest(array $request): SubscriptionData { $self = new static(); @@ -40,18 +38,4 @@ public static function fromRequest(array $request) return $self; } - - /** - * @param int $subscriptionId - * @return GatewaySubscriptionData - */ - public function toGatewaySubscriptionData($subscriptionId) - { - return GatewaySubscriptionData::fromArray([ - 'period' => $this->period, - 'times' => $this->times, - 'frequency' => $this->frequency, - 'subscriptionId' => $subscriptionId, - ]); - } } diff --git a/src/PaymentGateways/Gateways/PayPalStandard/Actions/CreatePayPalStandardPaymentURL.php b/src/PaymentGateways/Gateways/PayPalStandard/Actions/CreatePayPalStandardPaymentURL.php index e9e39f8eec..1d14e71c8f 100644 --- a/src/PaymentGateways/Gateways/PayPalStandard/Actions/CreatePayPalStandardPaymentURL.php +++ b/src/PaymentGateways/Gateways/PayPalStandard/Actions/CreatePayPalStandardPaymentURL.php @@ -2,7 +2,8 @@ namespace Give\PaymentGateways\Gateways\PayPalStandard\Actions; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; +use Give\Donations\Models\Donation; +use Give\Framework\PaymentGateways\DonationSummary; /** * This class create PayPal Standard payment gateway one time payment url on basis of donor donation query. @@ -12,37 +13,36 @@ class CreatePayPalStandardPaymentURL { public function __invoke( - GatewayPaymentData $paymentData, + Donation $donation, $successRedirectUrl, // PayPal Standard will redirect donor to this url after successful payment. $failedRedirectUrl, // PayPal Standard will redirect donor to this url after failed payment. $payPalIpnListenerUrl // PayPal Standard will send ipn notification to this url on payment update. ) { $paypalPaymentRedirectUrl = trailingslashit(give_get_paypal_redirect()) . '?'; - $itemName = give_payment_gateway_item_title($paymentData->legacyPaymentData); + $itemName = (new DonationSummary($donation))->getSummary(); $payPalPartnerCode = 'givewp_SP'; - // Setup PayPal API params. $paypalPaymentArguments = [ // PayPal account information 'business' => give_get_option('paypal_email', false), // Donor info - 'first_name' => $paymentData->donorInfo->firstName, - 'last_name' => $paymentData->donorInfo->lastName, - 'email' => $paymentData->donorInfo->email, - 'address1' => $paymentData->billingAddress->line1, - 'address2' => $paymentData->billingAddress->line2, - 'city' => $paymentData->billingAddress->city, - 'state' => $paymentData->billingAddress->state, - 'zip' => $paymentData->billingAddress->postalCode, - 'country' => $paymentData->billingAddress->country, + 'first_name' => $donation->firstName, + 'last_name' => $donation->lastName, + 'email' => $donation->email, + 'address1' => $donation->billingAddress->address1, + 'address2' => $donation->billingAddress->address2, + 'city' => $donation->billingAddress->city, + 'state' => $donation->billingAddress->state, + 'zip' => $donation->billingAddress->zip, + 'country' => $donation->billingAddress->country, // Donation information. - 'invoice' => $paymentData->purchaseKey, - 'amount' => $paymentData->price, + 'invoice' => $donation->purchaseKey, + 'amount' => $donation->amount->formatToDecimal(), 'item_name' => stripslashes($itemName), - 'currency_code' => give_get_currency($paymentData->donationId), + 'currency_code' => give_get_currency($donation->id), // Urls 'return' => $successRedirectUrl, @@ -53,7 +53,7 @@ public function __invoke( 'shipping' => '0', 'no_note' => '1', 'charset' => get_bloginfo('charset'), - 'custom' => $paymentData->donationId, + 'custom' => $donation->id, 'rm' => '2', 'page_style' => give_get_paypal_page_style(), 'cbt' => get_bloginfo('name'), @@ -63,7 +63,7 @@ public function __invoke( // Donations or regular transactions? $paypalPaymentArguments['cmd'] = give_get_paypal_button_type(); - $paypalPaymentArguments = $this->supportLegacyFilter($paypalPaymentArguments, $paymentData); + $paypalPaymentArguments = $this->supportLegacyFilter($paypalPaymentArguments, $donation); /** * Filter the PayPal Standard redirect args. @@ -71,12 +71,12 @@ public function __invoke( * @since 2.19.0 * * @param array $paypalPaymentArguments PayPal Standard payment Data. - * @param GatewayPaymentData $paymentData Gateway payment data. + * @param Donation $paymentData Gateway payment data. */ $paypalPaymentArguments = apply_filters( 'give_gateway_paypal_redirect_args', $paypalPaymentArguments, - $paymentData + $donation ); $paypalPaymentRedirectUrl .= http_build_query($paypalPaymentArguments); @@ -87,25 +87,28 @@ public function __invoke( /** * @since 2.19.0 - * - * @param array $paypalPaymentArguments - * @param GatewayPaymentData $paymentData - * - * @return array */ - private function supportLegacyFilter($paypalPaymentArguments, GatewayPaymentData $paymentData) + private function supportLegacyFilter(array $paypalPaymentArguments, Donation $donation): array { /** * Filter the PayPal Standard redirect args. * + * @unreleased Create and pass legacy payment data to filter hook * @since 1.8 */ return apply_filters_deprecated( 'give_paypal_redirect_args', [ $paypalPaymentArguments, - $paymentData->donationId, - $paymentData->legacyPaymentData + $paypalPaymentArguments['custom'], + [ + 'price' => $donation->amount->formatToDecimal(), + 'purchase_key' => $donation->purchaseKey, + 'user_email' => $donation->email, + 'date' => $donation->createdAt->format('Y-m-d H:i:s'), + 'post_data' => give_clean($_POST), + 'gateway' => $donation->gatewayId, + ] ], '2.19.0' ); diff --git a/src/PaymentGateways/Gateways/PayPalStandard/PayPalStandard.php b/src/PaymentGateways/Gateways/PayPalStandard/PayPalStandard.php index a4009d77cc..a9f217f3f5 100644 --- a/src/PaymentGateways/Gateways/PayPalStandard/PayPalStandard.php +++ b/src/PaymentGateways/Gateways/PayPalStandard/PayPalStandard.php @@ -8,7 +8,6 @@ use Give\Framework\PaymentGateways\Commands\RedirectOffsite; use Give\Framework\PaymentGateways\PaymentGateway; use Give\Helpers\Call; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; use Give\PaymentGateways\Gateways\PayPalStandard\Actions\CreatePayPalStandardPaymentURL; use Give\PaymentGateways\Gateways\PayPalStandard\Actions\GenerateDonationFailedPageUrl; use Give\PaymentGateways\Gateways\PayPalStandard\Actions\GenerateDonationReceiptPageUrl; @@ -16,6 +15,9 @@ use Give\PaymentGateways\Gateways\PayPalStandard\Views\PayPalStandardBillingFields; use Give_Payment; +/** + * @since 2.19.0 + */ class PayPalStandard extends PaymentGateway { public $routeMethods = [ @@ -30,7 +32,7 @@ class PayPalStandard extends PaymentGateway /** * @inheritDoc */ - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup(int $formId, array $args): string { return Call::invoke(PayPalStandardBillingFields::class, $formId); } @@ -38,7 +40,7 @@ public function getLegacyFormFieldMarkup($formId, $args) /** * @inheritDoc */ - public static function id() + public static function id(): string { return 'paypal'; } @@ -46,7 +48,7 @@ public static function id() /** * @inerhitDoc */ - public function getId() + public function getId(): string { return self::id(); } @@ -54,7 +56,7 @@ public function getId() /** * @inheritDoc */ - public function getName() + public function getName(): string { return esc_html__('PayPal Standard', 'give'); } @@ -62,7 +64,7 @@ public function getName() /** * @inheritDoc */ - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return esc_html__('PayPal', 'give'); } @@ -70,21 +72,21 @@ public function getPaymentMethodLabel() /** * @inheritDoc */ - public function createPayment(GatewayPaymentData $paymentData) + public function createPayment(Donation $donation): RedirectOffsite { return new RedirectOffsite( Call::invoke( CreatePayPalStandardPaymentURL::class, - $paymentData, + $donation, $this->generateSecureGatewayRouteUrl( 'handleSuccessPaymentReturn', - $paymentData->donationId, - ['donation-id' => $paymentData->donationId] + $donation->id, + ['donation-id' => $donation->id] ), $this->generateSecureGatewayRouteUrl( 'handleFailedPaymentReturn', - $paymentData->donationId, - ['donation-id' => $paymentData->donationId] + $donation->id, + ['donation-id' => $donation->id] ), $this->generateGatewayRouteUrl( 'handleIpnNotification' @@ -101,22 +103,22 @@ public function createPayment(GatewayPaymentData $paymentData) * @since 2.19.6 1. Do not set donation to "processing" * 2. Add "payment-confirmation" param to receipt page url * - * @param array $queryParams Query params in gateway route. { + * @param array $queryParams Query params in gateway route. { * * @type string "donation-id" Donation id. * * } - * - * @return RedirectResponse */ - protected function handleSuccessPaymentReturn($queryParams) + protected function handleSuccessPaymentReturn(array $queryParams): RedirectResponse { $donationId = (int)$queryParams['donation-id']; - return new RedirectResponse(add_query_arg( - [ 'payment-confirmation' => $this->getId() ], - Call::invoke(GenerateDonationReceiptPageUrl::class, $donationId) - )); + return new RedirectResponse( + add_query_arg( + ['payment-confirmation' => $this->getId()], + Call::invoke(GenerateDonationReceiptPageUrl::class, $donationId) + ) + ); } /** @@ -129,10 +131,8 @@ protected function handleSuccessPaymentReturn($queryParams) * @type string "donation-id" Donation id. * * } - * - * @return RedirectResponse */ - protected function handleFailedPaymentReturn($queryParams) + protected function handleFailedPaymentReturn(array $queryParams): RedirectResponse { $donationId = (int)$queryParams['donation-id']; $payment = new Give_Payment($donationId); diff --git a/src/PaymentGateways/Gateways/PayPalStandard/Views/PayPalStandardBillingFields.php b/src/PaymentGateways/Gateways/PayPalStandard/Views/PayPalStandardBillingFields.php index 6aea5860e6..4164b6c29d 100644 --- a/src/PaymentGateways/Gateways/PayPalStandard/Views/PayPalStandardBillingFields.php +++ b/src/PaymentGateways/Gateways/PayPalStandard/Views/PayPalStandardBillingFields.php @@ -18,7 +18,7 @@ class PayPalStandardBillingFields * * @return string */ - public function __invoke($formId) + public function __invoke(int $formId): string { ob_start(); @@ -58,7 +58,7 @@ public function __invoke($formId) * * @return string */ - private function getLogo() + private function getLogo(): string { return file_get_contents( GIVE_PLUGIN_DIR . 'src/PaymentGateways/Gateways/PayPalStandard/resources/templates/paypal-standard-logo.svg' diff --git a/src/PaymentGateways/Gateways/Stripe/Actions/CreateCheckoutSession.php b/src/PaymentGateways/Gateways/Stripe/Actions/CreateCheckoutSession.php index 96ec8b7244..972faab2fd 100644 --- a/src/PaymentGateways/Gateways/Stripe/Actions/CreateCheckoutSession.php +++ b/src/PaymentGateways/Gateways/Stripe/Actions/CreateCheckoutSession.php @@ -3,11 +3,12 @@ namespace Give\PaymentGateways\Gateways\Stripe\Actions; use Give\Donations\Models\Donation; +use Give\Donations\Models\DonationNote; +use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\PaymentGateways\DonationSummary; use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; use Give\PaymentGateways\Exceptions\InvalidPropertyName; use Give\PaymentGateways\Gateways\Stripe\ValueObjects\CheckoutSession; -use Give\ValueObjects\Money; use Give_Stripe_Customer; /** @@ -19,21 +20,22 @@ class CreateCheckoutSession * @since 2.20.0 Update function to get input value to line_items[0][name] * @since 2.19.0 * - * @param GatewayPaymentData $paymentData - * @param DonationSummary $donationSummary - * @param Give_Stripe_Customer $giveStripeCustomer + * @param GatewayPaymentData $paymentData + * @param DonationSummary $donationSummary + * @param Give_Stripe_Customer $giveStripeCustomer * * @return CheckoutSession * @throws InvalidPropertyName + * @throws Exception */ public function __invoke( - GatewayPaymentData $paymentData, + Donation $donation, DonationSummary $donationSummary, Give_Stripe_Customer $giveStripeCustomer ) { $session_args = [ 'customer' => $giveStripeCustomer->get_id(), - 'client_reference_id' => $paymentData->purchaseKey, + 'client_reference_id' => $donation->purchaseKey, 'payment_method_types' => ['card'], 'billing_address_collection' => give_is_setting_enabled( give_get_option('stripe_collect_billing') @@ -41,17 +43,17 @@ public function __invoke( 'mode' => 'payment', 'line_items' => [ [ - 'name' => Donation::find($paymentData->donationId)->formTitle, + 'name' => Donation::find($donation->id)->formTitle, 'description' => $donationSummary->getSummaryWithDonor(), - 'amount' => Money::of($paymentData->price, $paymentData->currency)->getMinorAmount(), - 'currency' => $paymentData->currency, + 'amount' => $donation->amount->formatToMinorAmount(), + 'currency' => $donation->amount->getCurrency(), 'quantity' => 1, ], ], 'payment_intent_data' => [ 'capture_method' => 'automatic', 'description' => $donationSummary->getSummaryWithDonor(), - 'metadata' => give_stripe_prepare_metadata($paymentData->donationId), + 'metadata' => give_stripe_prepare_metadata($donation->id), 'statement_descriptor' => give_stripe_get_statement_descriptor(), ], 'submit_type' => 'donate', @@ -60,16 +62,19 @@ public function __invoke( 'locale' => give_stripe_get_preferred_locale(), ]; - // If featured image exists, then add it to checkout session. - $formId = give_get_payment_form_id($paymentData->donationId); - if (!empty(get_the_post_thumbnail($formId))) { - $session_args['line_items'][0]['images'] = [get_the_post_thumbnail_url($formId)]; + if ($formThumbnail = get_the_post_thumbnail($donation->formId)) { + $session_args['line_items'][0]['images'] = [$formThumbnail]; } $session = give(CheckoutSession::class)->create($session_args); - give_insert_payment_note($paymentData->donationId, 'Stripe Checkout Session ID: ' . $session->id()); - give_set_payment_transaction_id($paymentData->donationId, $session->id()); + DonationNote::create([ + 'donationId' => $donation->id, + 'content' => 'Stripe Checkout Session ID: ' . $session->id() + ]); + + $donation->gatewayTransactionId = $session->id(); + $donation->save(); return $session; } diff --git a/src/PaymentGateways/Gateways/Stripe/Actions/CreatePaymentIntent.php b/src/PaymentGateways/Gateways/Stripe/Actions/CreatePaymentIntent.php index 88befee18d..145f8ffbe6 100644 --- a/src/PaymentGateways/Gateways/Stripe/Actions/CreatePaymentIntent.php +++ b/src/PaymentGateways/Gateways/Stripe/Actions/CreatePaymentIntent.php @@ -2,13 +2,13 @@ namespace Give\PaymentGateways\Gateways\Stripe\Actions; -use Give\LegacyPaymentGateways\DataTransferObjects\LegacyDonationData; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; +use Give\Donations\Models\Donation; +use Give\Donations\Models\DonationNote; +use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\PaymentGateways\DonationSummary; use Give\PaymentGateways\Exceptions\InvalidPropertyName; use Give\PaymentGateways\Gateways\Stripe\ValueObjects\PaymentIntent; use Give\PaymentGateways\Gateways\Stripe\ValueObjects\PaymentMethod; -use Give\ValueObjects\Money; /** * @since 2.19.0 @@ -20,10 +20,8 @@ class CreatePaymentIntent /** * @since 2.19.0 - * - * @param array $paymentIntentArgs */ - public function __construct($paymentIntentArgs = []) + public function __construct(array $paymentIntentArgs = []) { $this->defaultIntentArgs = $paymentIntentArgs; } @@ -31,20 +29,15 @@ public function __construct($paymentIntentArgs = []) /** * @since 2.19.0 * - * @param GatewayPaymentData $paymentData - * @param DonationSummary $donationSummary - * @param \Give_Stripe_Customer $giveStripeCustomer - * @param PaymentMethod $paymentMethod - * - * @return PaymentIntent * @throws InvalidPropertyName + * @throws Exception */ public function __invoke( - GatewayPaymentData $paymentData, + Donation $donation, DonationSummary $donationSummary, \Give_Stripe_Customer $giveStripeCustomer, PaymentMethod $paymentMethod - ) { + ): PaymentIntent { /** * This filter hook is used to update the payment intent arguments. * @@ -53,50 +46,50 @@ public function __invoke( $intent_args = apply_filters( 'give_stripe_create_intent_args', array_merge([ - 'amount' => Money::of($paymentData->price, $paymentData->currency)->getMinorAmount(), - 'currency' => $paymentData->currency, + 'amount' => $donation->amount->formatToMinorAmount(), + 'currency' => $donation->amount->getCurrency(), 'payment_method_types' => ['card'], 'statement_descriptor' => give_stripe_get_statement_descriptor(), 'description' => $donationSummary->getSummaryWithDonor(), - 'metadata' => give_stripe_prepare_metadata( - $paymentData->donationId, - new LegacyDonationData($paymentData, $paymentMethod->id()) - ), + 'metadata' => give_stripe_prepare_metadata($donation->id), 'customer' => $giveStripeCustomer->get_id(), 'payment_method' => $paymentMethod->id(), 'confirm' => true, - 'return_url' => $paymentData->redirectUrl, + 'return_url' => give_get_success_page_uri(), ], $this->defaultIntentArgs) ); // Send Stripe Receipt emails when enabled. if (give_is_setting_enabled(give_get_option('stripe_receipt_emails'))) { - $intent_args['receipt_email'] = $paymentData->donorInfo->email; + $intent_args['receipt_email'] = $donation->email; } $intent = give(PaymentIntent::class)->create($intent_args); - give_insert_payment_note( - $paymentData->donationId, - sprintf(__('Stripe Charge/Payment Intent ID: %s', 'give'), $intent->id()) - ); - give_insert_payment_note( - $paymentData->donationId, - sprintf(__('Stripe Payment Intent Client Secret: %s', 'give'), $intent->clientSecret()) - ); + DonationNote::create([ + 'donationId' => $donation->id, + 'content' => sprintf(__('Stripe Charge/Payment Intent ID: %s', 'give'), $intent->id()) + ]); + + DonationNote::create([ + 'donationId' => $donation->id, + 'content' => sprintf(__('Stripe Payment Intent Client Secret: %s', 'give'), $intent->clientSecret()) + ]); + give_update_meta( - $paymentData->donationId, + $donation->id, '_give_stripe_payment_intent_client_secret', $intent->clientSecret() ); - if ('requires_action' == $intent->status()) { - give_insert_payment_note( - $paymentData->donationId, - __('Stripe requires additional action to be fulfilled. Check your Stripe account.', 'give') - ); + if ('requires_action' === $intent->status()) { + DonationNote::create([ + 'donationId' => $donation->id, + 'content' => __('Stripe requires additional action to be fulfilled. Check your Stripe account.', 'give') + ]); + give_update_meta( - $paymentData->donationId, + $donation->id, '_give_stripe_payment_intent_require_action_url', $intent->nextActionRedirectUrl() ); diff --git a/src/PaymentGateways/Gateways/Stripe/Actions/GetOrCreateStripeCustomer.php b/src/PaymentGateways/Gateways/Stripe/Actions/GetOrCreateStripeCustomer.php index 5ba5255cef..4af351273c 100644 --- a/src/PaymentGateways/Gateways/Stripe/Actions/GetOrCreateStripeCustomer.php +++ b/src/PaymentGateways/Gateways/Stripe/Actions/GetOrCreateStripeCustomer.php @@ -2,7 +2,9 @@ namespace Give\PaymentGateways\Gateways\Stripe\Actions; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; +use Give\Donations\Models\Donation; +use Give\Donations\Models\DonationNote; +use Give\Framework\Exceptions\Primitives\Exception; use Give\PaymentGateways\Gateways\Stripe\Exceptions\StripeCustomerException; use Give_Stripe_Customer; @@ -12,48 +14,39 @@ class GetOrCreateStripeCustomer /** * @since 2.20.0 add second param support to function. * This param is optional because we use it only when donor subscribe for recurring donation. + * @unreleased Update function first argument type to Donation model * @since 2.19.0 * - * @param GatewayPaymentData $stripePaymentMethodId - * @param string $stripePaymentMethopdId - * * @return Give_Stripe_Customer * @throws StripeCustomerException */ - public function __invoke(GatewayPaymentData $paymentData, $stripePaymentMethodId = '') + public function __invoke(Donation $donation, string $stripePaymentMethodId = ''): Give_Stripe_Customer { - $giveStripeCustomer = new Give_Stripe_Customer($paymentData->donorInfo->email, $stripePaymentMethodId); + $giveStripeCustomer = new Give_Stripe_Customer($donation->email, $stripePaymentMethodId); if (!$giveStripeCustomer->get_id()) { throw new StripeCustomerException(__('Unable to find or create stripe customer object.', 'give')); } - $this->saveStripeCustomerId($paymentData->donationId, $giveStripeCustomer->get_id()); + $this->saveStripeCustomerId($donation, $giveStripeCustomer->get_id()); return $giveStripeCustomer; } /** + * @unreleased Update function first argument type to Donation model * @since 2.19.0 - * - * @param int $donationId - * @param string $stripeCustomerId - * - * @return void + * @throws Exception */ - protected function saveStripeCustomerId($donationId, $stripeCustomerId) + protected function saveStripeCustomerId(Donation $donation, string $stripeCustomerId) { - $donor = new \Give_Donor( - give_get_payment_donor_id($donationId) - ); - - $donor->update_meta(give_stripe_get_customer_key(), $stripeCustomerId); + give()->donor_meta->update_meta($donation->donorId, give_stripe_get_customer_key(), $stripeCustomerId); - give_insert_payment_note( - $donationId, - sprintf(__('Stripe Customer ID: %s', 'give'), $stripeCustomerId) - ); + DonationNote::create([ + 'donationId' => $donation->id, + 'content' => sprintf(__('Stripe Customer ID: %s', 'give'), $stripeCustomerId) + ]); - give_update_meta($donationId, give_stripe_get_customer_key(), $stripeCustomerId); + give_update_meta($donation->id, give_stripe_get_customer_key(), $stripeCustomerId); } } diff --git a/src/PaymentGateways/Gateways/Stripe/Actions/GetPaymentMethodFromRequest.php b/src/PaymentGateways/Gateways/Stripe/Actions/GetPaymentMethodFromRequest.php index 517ff77889..e64f295d38 100644 --- a/src/PaymentGateways/Gateways/Stripe/Actions/GetPaymentMethodFromRequest.php +++ b/src/PaymentGateways/Gateways/Stripe/Actions/GetPaymentMethodFromRequest.php @@ -2,7 +2,9 @@ namespace Give\PaymentGateways\Gateways\Stripe\Actions; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; +use Give\Donations\Models\Donation; +use Give\Donations\Models\DonationNote; +use Give\Framework\Exceptions\Primitives\Exception; use Give\PaymentGateways\Gateways\Stripe\Exceptions\PaymentMethodException; use Give\PaymentGateways\Gateways\Stripe\ValueObjects\PaymentMethod; @@ -10,22 +12,26 @@ class GetPaymentMethodFromRequest { /** * @since 2.19.0 - * @param GatewayPaymentData $paymentData + * * @throws PaymentMethodException - * @return PaymentMethod $paymentMethod + * @throws Exception */ - public function __invoke( GatewayPaymentData $paymentData ) + public function __invoke(Donation $donation): PaymentMethod { - if( ! isset( $_POST['give_stripe_payment_method'] ) ) { + if (!isset($_POST['give_stripe_payment_method'])) { throw new PaymentMethodException('Payment Method Not Found'); } $paymentMethod = new PaymentMethod( - give_clean( $_POST['give_stripe_payment_method'] ) + give_clean($_POST['give_stripe_payment_method']) ); - give_update_meta($paymentData->donationId, '_give_stripe_source_id', $paymentMethod->id()); - give_insert_payment_note($paymentData->donationId, sprintf(__('Stripe Source/Payment Method ID: %s', 'give'), $paymentMethod->id())); + give_update_meta($donation->id, '_give_stripe_source_id', $paymentMethod->id()); + + DonationNote::create([ + 'donationId' => $donation->id, + 'content' => sprintf(__('Stripe Source/Payment Method ID: %s', 'give'), $paymentMethod->id()) + ]); return $paymentMethod; } diff --git a/src/PaymentGateways/Gateways/Stripe/Actions/SaveDonationSummary.php b/src/PaymentGateways/Gateways/Stripe/Actions/SaveDonationSummary.php index 02dde40c60..5e2fd3cdc1 100644 --- a/src/PaymentGateways/Gateways/Stripe/Actions/SaveDonationSummary.php +++ b/src/PaymentGateways/Gateways/Stripe/Actions/SaveDonationSummary.php @@ -2,7 +2,7 @@ namespace Give\PaymentGateways\Gateways\Stripe\Actions; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; +use Give\Donations\Models\Donation; use Give\Framework\PaymentGateways\DonationSummary; /** @@ -11,18 +11,17 @@ class SaveDonationSummary { /** - * @param GatewayPaymentData $paymentData - * - * @return DonationSummary + * @since 2.19.0 */ - public function __invoke(GatewayPaymentData $paymentData) + public function __invoke(Donation $donation): DonationSummary { - $summary = new DonationSummary($paymentData); + $summary = new DonationSummary($donation); give_update_meta( - $paymentData->donationId, + $donation->id, '_give_stripe_donation_summary', $summary->getSummaryWithDonor() ); + return $summary; } } diff --git a/src/PaymentGateways/Gateways/Stripe/BECSGateway.php b/src/PaymentGateways/Gateways/Stripe/BECSGateway.php index 5107ca19c0..c123314a40 100644 --- a/src/PaymentGateways/Gateways/Stripe/BECSGateway.php +++ b/src/PaymentGateways/Gateways/Stripe/BECSGateway.php @@ -5,12 +5,10 @@ use Give\Donations\Models\Donation; use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\PaymentGateways\Commands\GatewayCommand; -use Give\Framework\PaymentGateways\Contracts\SubscriptionModuleInterface; use Give\Framework\PaymentGateways\Exceptions\PaymentGatewayException; use Give\Framework\PaymentGateways\PaymentGateway; use Give\Framework\PaymentGateways\SubscriptionModule; use Give\Helpers\Call; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; use Give\PaymentGateways\Gateways\Stripe\Traits\BECSMandateForm; use Give\PaymentGateways\Gateways\Stripe\Traits\HandlePaymentIntentStatus; @@ -44,29 +42,29 @@ public function __construct(SubscriptionModule $subscriptionModule = null) * @return GatewayCommand * @throws PaymentGatewayException */ - public function createPayment( GatewayPaymentData $paymentData ) + public function createPayment( Donation $donation ): GatewayCommand { - $paymentMethod = Call::invoke( Actions\GetPaymentMethodFromRequest::class, $paymentData ); - $donationSummary = Call::invoke( Actions\SaveDonationSummary::class, $paymentData ); - $stripeCustomer = Call::invoke( Actions\GetOrCreateStripeCustomer::class, $paymentData ); + $paymentMethod = Call::invoke( Actions\GetPaymentMethodFromRequest::class, $donation ); + $donationSummary = Call::invoke( Actions\SaveDonationSummary::class, $donation ); + $stripeCustomer = Call::invoke( Actions\GetOrCreateStripeCustomer::class, $donation ); $createIntentAction = new Actions\CreatePaymentIntent( $this->getPaymentIntentArgs() ); return $this->handlePaymentIntentStatus( $createIntentAction( - $paymentData, + $donation, $donationSummary, $stripeCustomer, $paymentMethod ), - $paymentData->donationId + $donation ); } /** * @inheritDoc */ - public static function id() + public static function id(): string { return 'stripe_becs'; } @@ -74,7 +72,7 @@ public static function id() /** * @inheritDoc */ - public function getId() + public function getId(): string { return self::id(); } @@ -82,7 +80,7 @@ public function getId() /** * @inheritDoc */ - public function getName() + public function getName(): string { return __('Stripe - BECS Direct Debit', 'give'); } @@ -90,7 +88,7 @@ public function getName() /** * @inheritDoc */ - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return __('Stripe - BECS Direct Debit', 'give'); } @@ -98,7 +96,7 @@ public function getPaymentMethodLabel() /** * @inheritDoc */ - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup(int $formId, array $args): string { return $this->getMandateFormHTML( $formId, $args ); } @@ -107,7 +105,7 @@ public function getLegacyFormFieldMarkup($formId, $args) * @since 2.19.0 * @return array */ - protected function getPaymentIntentArgs() + protected function getPaymentIntentArgs(): array { return [ 'payment_method_types' => [ 'au_becs_debit' ], diff --git a/src/PaymentGateways/Gateways/Stripe/CheckoutGateway.php b/src/PaymentGateways/Gateways/Stripe/CheckoutGateway.php index df07461187..f29e1137cd 100644 --- a/src/PaymentGateways/Gateways/Stripe/CheckoutGateway.php +++ b/src/PaymentGateways/Gateways/Stripe/CheckoutGateway.php @@ -11,7 +11,6 @@ use Give\Framework\PaymentGateways\PaymentGateway; use Give\Helpers\Call; use Give\Helpers\Gateways\Stripe; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; use Give\PaymentGateways\Exceptions\InvalidPropertyName; use Give\PaymentGateways\Gateways\Stripe\Exceptions\CheckoutException; @@ -31,22 +30,22 @@ class CheckoutGateway extends PaymentGateway * @throws Exceptions\PaymentIntentException * @throws InvalidPropertyName */ - protected function createPaymentModal( GatewayPaymentData $paymentData ) + protected function createPaymentModal(Donation $donation) { - $paymentMethod = Call::invoke( Actions\GetPaymentMethodFromRequest::class, $paymentData ); - $donationSummary = Call::invoke( Actions\SaveDonationSummary::class, $paymentData ); - $stripeCustomer = Call::invoke( Actions\GetOrCreateStripeCustomer::class, $paymentData ); + $paymentMethod = Call::invoke(Actions\GetPaymentMethodFromRequest::class, $donation); + $donationSummary = Call::invoke(Actions\SaveDonationSummary::class, $donation); + $stripeCustomer = Call::invoke(Actions\GetOrCreateStripeCustomer::class, $donation); $createIntentAction = new Actions\CreatePaymentIntent([]); return $this->handlePaymentIntentStatus( $createIntentAction( - $paymentData, + $donation, $donationSummary, $stripeCustomer, $paymentMethod ), - $paymentData->donationId + $donation ); } @@ -55,16 +54,15 @@ protected function createPaymentModal( GatewayPaymentData $paymentData ) /** * @inheritDoc * @since 2.19.0 - * @return GatewayCommand * @throws PaymentGatewayException */ - public function createPayment(GatewayPaymentData $paymentData) + public function createPayment(Donation $donation): GatewayCommand { switch (give_stripe_get_checkout_type()) { case 'modal': - return $this->createPaymentModal($paymentData); + return $this->createPaymentModal($donation); case 'redirect': - return $this->createPaymentRedirect($paymentData); + return $this->createPaymentRedirect($donation); default: throw new CheckoutException('Invalid Checkout Error'); } @@ -73,24 +71,22 @@ public function createPayment(GatewayPaymentData $paymentData) /** * @since 2.19.7 fix argument order of CreateCheckoutSession * @since 2.19.0 - * - * @return RedirectOffsite */ - protected function createPaymentRedirect(GatewayPaymentData $paymentData) + protected function createPaymentRedirect(Donation $donation): RedirectOffsite { - $donationSummary = Call::invoke(Actions\SaveDonationSummary::class, $paymentData); - $stripeCustomer = Call::invoke(Actions\GetOrCreateStripeCustomer::class, $paymentData); - $session = Call::invoke(Actions\CreateCheckoutSession::class, $paymentData, $donationSummary, $stripeCustomer); + $donationSummary = Call::invoke(Actions\SaveDonationSummary::class, $donation); + $stripeCustomer = Call::invoke(Actions\GetOrCreateStripeCustomer::class, $donation); + $session = Call::invoke(Actions\CreateCheckoutSession::class, $donation, $donationSummary, $stripeCustomer); return new RedirectOffsite( - $this->getRedirectUrl( $session->id(), give_get_payment_form_id( $paymentData->donationId ) ) + $this->getRedirectUrl($session->id(), give_get_payment_form_id($donation->id)) ); } /** * @inheritDoc */ - public static function id() + public static function id(): string { return 'stripe_checkout'; } @@ -98,7 +94,7 @@ public static function id() /** * @inheritDoc */ - public function getId() + public function getId(): string { return self::id(); } @@ -106,7 +102,7 @@ public function getId() /** * @inheritDoc */ - public function getName() + public function getName(): string { return __('Stripe - Checkout', 'give'); } @@ -114,22 +110,24 @@ public function getName() /** * @inheritDoc */ - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return __('Stripe - Checkout', 'give'); } /** * @inheritDoc + * + * @return string|void */ - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup(int $formId, array $args): string { - Stripe::canShowBillingAddress( $formId, $args ); + Stripe::canShowBillingAddress($formId, $args); - switch( give_stripe_get_checkout_type() ) { + switch (give_stripe_get_checkout_type()) { case 'modal': return $this->getCheckoutInstructions() - . $this->getCheckoutModalHTML( $formId, $args ); + . $this->getCheckoutModalHTML($formId, $args); case 'redirect': return $this->getCheckoutInstructions(); } diff --git a/src/PaymentGateways/Gateways/Stripe/CreditCardGateway.php b/src/PaymentGateways/Gateways/Stripe/CreditCardGateway.php index 74c6e4d33d..f9413b94c2 100644 --- a/src/PaymentGateways/Gateways/Stripe/CreditCardGateway.php +++ b/src/PaymentGateways/Gateways/Stripe/CreditCardGateway.php @@ -5,12 +5,10 @@ use Give\Donations\Models\Donation; use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\PaymentGateways\Commands\GatewayCommand; -use Give\Framework\PaymentGateways\Contracts\SubscriptionModuleInterface; use Give\Framework\PaymentGateways\Exceptions\PaymentGatewayException; use Give\Framework\PaymentGateways\PaymentGateway; use Give\Framework\PaymentGateways\SubscriptionModule; use Give\Helpers\Call; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; /** * @since 2.19.0 @@ -45,32 +43,32 @@ public function __construct(SubscriptionModule $subscriptionModule = null) * @inheritDoc * @since 2.19.7 fix handlePaymentIntentStatus not receiving extra param * @since 2.19.0 - * @return GatewayCommand + * * @throws PaymentGatewayException */ - public function createPayment(GatewayPaymentData $paymentData) + public function createPayment(Donation $donation): GatewayCommand { - $paymentMethod = Call::invoke( Actions\GetPaymentMethodFromRequest::class, $paymentData ); - $donationSummary = Call::invoke( Actions\SaveDonationSummary::class, $paymentData ); - $stripeCustomer = Call::invoke( Actions\GetOrCreateStripeCustomer::class, $paymentData ); + $paymentMethod = Call::invoke(Actions\GetPaymentMethodFromRequest::class, $donation); + $donationSummary = Call::invoke(Actions\SaveDonationSummary::class, $donation); + $stripeCustomer = Call::invoke(Actions\GetOrCreateStripeCustomer::class, $donation); $createIntentAction = new Actions\CreatePaymentIntent([]); return $this->handlePaymentIntentStatus( $createIntentAction( - $paymentData, + $donation, $donationSummary, $stripeCustomer, $paymentMethod ), - $paymentData->donationId + $donation ); } /** * @inheritDoc */ - public static function id() + public static function id(): string { return 'stripe'; } @@ -78,7 +76,7 @@ public static function id() /** * @inheritDoc */ - public function getId() + public function getId(): string { return self::id(); } @@ -86,7 +84,7 @@ public function getId() /** * @inheritDoc */ - public function getName() + public function getName(): string { return __('Stripe - Credit Card', 'give'); } @@ -94,7 +92,7 @@ public function getName() /** * @inheritDoc */ - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return __('Stripe - Credit Card', 'give'); } @@ -102,7 +100,7 @@ public function getPaymentMethodLabel() /** * @inheritDoc */ - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup(int $formId, array $args): string { return $this->getCreditCardFormHTML($formId, $args); } diff --git a/src/PaymentGateways/Gateways/Stripe/SEPAGateway.php b/src/PaymentGateways/Gateways/Stripe/SEPAGateway.php index 318e3b4d73..4467ecbba8 100644 --- a/src/PaymentGateways/Gateways/Stripe/SEPAGateway.php +++ b/src/PaymentGateways/Gateways/Stripe/SEPAGateway.php @@ -5,12 +5,10 @@ use Give\Donations\Models\Donation; use Give\Framework\Exceptions\Primitives\Exception; use Give\Framework\PaymentGateways\Commands\GatewayCommand; -use Give\Framework\PaymentGateways\Contracts\SubscriptionModuleInterface; use Give\Framework\PaymentGateways\Exceptions\PaymentGatewayException; use Give\Framework\PaymentGateways\PaymentGateway; use Give\Framework\PaymentGateways\SubscriptionModule; use Give\Helpers\Call; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; use Give\PaymentGateways\Gateways\Stripe\Traits\HandlePaymentIntentStatus; use Give\PaymentGateways\Gateways\Stripe\Traits\SEPAMandateForm; @@ -32,9 +30,18 @@ public function __construct(SubscriptionModule $subscriptionModule = null) { parent::__construct($subscriptionModule); - $this->errorMessages['accountConfiguredNoSsl'] = esc_html__( 'IBAN fields are disabled because your site is not running securely over HTTPS.', 'give' ); - $this->errorMessages['accountNotConfiguredNoSsl'] = esc_html__( 'IBAN fields are disabled because Stripe is not connected and your site is not running securely over HTTPS.', 'give' ); - $this->errorMessages['accountNotConfigured'] = esc_html__( 'IBAN fields are disabled. Please connect and configure your Stripe account to accept donations.', 'give' ); + $this->errorMessages['accountConfiguredNoSsl'] = esc_html__( + 'IBAN fields are disabled because your site is not running securely over HTTPS.', + 'give' + ); + $this->errorMessages['accountNotConfiguredNoSsl'] = esc_html__( + 'IBAN fields are disabled because Stripe is not connected and your site is not running securely over HTTPS.', + 'give' + ); + $this->errorMessages['accountNotConfigured'] = esc_html__( + 'IBAN fields are disabled. Please connect and configure your Stripe account to accept donations.', + 'give' + ); } /** @@ -44,29 +51,29 @@ public function __construct(SubscriptionModule $subscriptionModule = null) * @return GatewayCommand * @throws PaymentGatewayException */ - public function createPayment( GatewayPaymentData $paymentData ) + public function createPayment(Donation $donation): GatewayCommand { - $paymentMethod = Call::invoke( Actions\GetPaymentMethodFromRequest::class, $paymentData ); - $donationSummary = Call::invoke( Actions\SaveDonationSummary::class, $paymentData ); - $stripeCustomer = Call::invoke( Actions\GetOrCreateStripeCustomer::class, $paymentData ); + $paymentMethod = Call::invoke(Actions\GetPaymentMethodFromRequest::class, $donation); + $donationSummary = Call::invoke(Actions\SaveDonationSummary::class, $donation); + $stripeCustomer = Call::invoke(Actions\GetOrCreateStripeCustomer::class, $donation); - $createIntentAction = new Actions\CreatePaymentIntent( $this->getPaymentIntentArgs() ); + $createIntentAction = new Actions\CreatePaymentIntent($this->getPaymentIntentArgs()); return $this->handlePaymentIntentStatus( $createIntentAction( - $paymentData, + $donation, $donationSummary, $stripeCustomer, $paymentMethod ), - $paymentData->donationId + $donation ); } /** * @inheritDoc */ - public static function id() + public static function id(): string { return 'stripe_sepa'; } @@ -74,7 +81,7 @@ public static function id() /** * @inheritDoc */ - public function getId() + public function getId(): string { return self::id(); } @@ -82,7 +89,7 @@ public function getId() /** * @inheritDoc */ - public function getName() + public function getName(): string { return __('Stripe - SEPA Direct Debit', 'give'); } @@ -90,7 +97,7 @@ public function getName() /** * @inheritDoc */ - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return __('Stripe - SEPA Direct Debit', 'give'); } @@ -98,23 +105,23 @@ public function getPaymentMethodLabel() /** * @inheritDoc */ - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup(int $formId, array $args): string { - return $this->getMandateFormHTML( $formId, $args ); + return $this->getMandateFormHTML($formId, $args); } /** * @since 2.19.0 * @return array */ - protected function getPaymentIntentArgs() + protected function getPaymentIntentArgs(): array { return [ - 'payment_method_types' => [ 'sepa_debit' ], - 'setup_future_usage' => 'on_session', - 'mandate_data' => [ + 'payment_method_types' => ['sepa_debit'], + 'setup_future_usage' => 'on_session', + 'mandate_data' => [ 'customer_acceptance' => [ - 'type' => 'online', + 'type' => 'online', 'online' => [ 'ip_address' => give_stripe_get_ip_address(), 'user_agent' => give_get_user_agent(), diff --git a/src/PaymentGateways/Gateways/Stripe/Traits/HandlePaymentIntentStatus.php b/src/PaymentGateways/Gateways/Stripe/Traits/HandlePaymentIntentStatus.php index 11c3842679..7f651650ad 100644 --- a/src/PaymentGateways/Gateways/Stripe/Traits/HandlePaymentIntentStatus.php +++ b/src/PaymentGateways/Gateways/Stripe/Traits/HandlePaymentIntentStatus.php @@ -2,6 +2,7 @@ namespace Give\PaymentGateways\Gateways\Stripe\Traits; +use Give\Donations\Models\Donation; use Give\Framework\PaymentGateways\Commands\PaymentCommand; use Give\Framework\PaymentGateways\Commands\PaymentComplete; use Give\Framework\PaymentGateways\Commands\PaymentProcessing; @@ -12,19 +13,18 @@ trait HandlePaymentIntentStatus { /** + * @unreleased Update second argument type to Donation model * @since 2.19.7 fix param order and only pass donationId * - * @param PaymentIntent $paymentIntent - * @param string $donationId - * * @return PaymentCommand|RedirectOffsite * @throws PaymentIntentException */ - public function handlePaymentIntentStatus(PaymentIntent $paymentIntent, $donationId) + public function handlePaymentIntentStatus(PaymentIntent $paymentIntent, Donation $donation) { switch ($paymentIntent->status()) { case 'requires_action': - give_set_payment_transaction_id($donationId, $paymentIntent->id()); + $donation->gatewayTransactionId = $paymentIntent->id(); + $donation->save(); return new RedirectOffsite($paymentIntent->nextActionRedirectUrl()); case 'succeeded': return new PaymentComplete($paymentIntent->id()); diff --git a/src/PaymentGateways/Gateways/Stripe/Traits/SEPAMandateForm.php b/src/PaymentGateways/Gateways/Stripe/Traits/SEPAMandateForm.php index 89794a56d4..ac687ecbc9 100644 --- a/src/PaymentGateways/Gateways/Stripe/Traits/SEPAMandateForm.php +++ b/src/PaymentGateways/Gateways/Stripe/Traits/SEPAMandateForm.php @@ -6,48 +6,51 @@ trait SEPAMandateForm { use FormFieldMarkup; - public function getMandateFormHTML( $form_id, $args ) + public function getMandateFormHTML(int $form_id, array $args): string { ob_start(); - $id_prefix = ! empty( $args['id_prefix'] ) ? $args['id_prefix'] : ''; + $id_prefix = !empty($args['id_prefix']) ? $args['id_prefix'] : ''; - do_action( 'give_before_cc_fields', $form_id ); ?> + do_action('give_before_cc_fields', $form_id); ?>
    - +
    - +
    canShowFields() ) { + if ($this->canShowFields()) { ?>
    @@ -58,33 +61,35 @@ class="give-stripe-sepa-iban-field give-stripe-cc-field" * * Note: Kept this hook as it is. * - * @param int $form_id Donation Form ID. - * @param array $args List of additional arguments. - * * @since 2.5.0 + * + * @param array $args List of additional arguments. + * + * @param int $form_id Donation Form ID. */ - do_action( 'give_after_cc_expiration', $form_id, $args ); + do_action('give_after_cc_expiration', $form_id, $args); /** * This action hook is used to display content after the Credit Card expiration field. * - * @param int $form_id Donation Form ID. - * @param array $args List of additional arguments. - * * @since 2.5.0 + * + * @param array $args List of additional arguments. + * + * @param int $form_id Donation Form ID. */ - do_action( 'give_stripe_after_cc_expiration', $form_id, $args ); + do_action('give_stripe_after_cc_expiration', $form_id, $args); } ?>
    donationId}"; + $transactionId = "test-gateway-transaction-id-{$donation->id}"; return new PaymentComplete($transactionId); } diff --git a/src/PaymentGateways/Gateways/TestGateway/TestGatewayOffsite.php b/src/PaymentGateways/Gateways/TestGateway/TestGatewayOffsite.php index ad2cdea8b5..4ce1b76d69 100644 --- a/src/PaymentGateways/Gateways/TestGateway/TestGatewayOffsite.php +++ b/src/PaymentGateways/Gateways/TestGateway/TestGatewayOffsite.php @@ -3,12 +3,14 @@ namespace Give\PaymentGateways\Gateways\TestGateway; use Give\Donations\Models\Donation; +use Give\Donations\Models\DonationNote; +use Give\Donations\ValueObjects\DonationStatus; use Give\Framework\Exceptions\Primitives\Exception; +use Give\Framework\Http\Response\Types\RedirectResponse; use Give\Framework\PaymentGateways\Commands\RedirectOffsite; use Give\Framework\PaymentGateways\Exceptions\PaymentGatewayException; use Give\Framework\PaymentGateways\PaymentGateway; use Give\Helpers\Form\Utils as FormUtils; -use Give\PaymentGateways\DataTransferObjects\GatewayPaymentData; use Give\PaymentGateways\Gateways\TestGateway\Views\LegacyFormFieldMarkup; use function Give\Framework\Http\Response\response; @@ -36,7 +38,7 @@ class TestGatewayOffsite extends PaymentGateway /** * @inheritDoc */ - public static function id() + public static function id(): string { return 'test-gateway-offsite'; } @@ -44,7 +46,7 @@ public static function id() /** * @inheritDoc */ - public function getId() + public function getId(): string { return self::id(); } @@ -52,7 +54,7 @@ public function getId() /** * @inheritDoc */ - public function getName() + public function getName(): string { return __('Test Gateway Offsite', 'give'); } @@ -60,7 +62,7 @@ public function getName() /** * @inheritDoc */ - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return __('Test Gateway Offsite', 'give'); } @@ -68,7 +70,7 @@ public function getPaymentMethodLabel() /** * @inheritDoc */ - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup(int $formId, array $args): string { if (FormUtils::isLegacyForm($formId)) { return false; @@ -83,12 +85,12 @@ public function getLegacyFormFieldMarkup($formId, $args) /** * @inheritDoc */ - public function createPayment(GatewayPaymentData $paymentData) + public function createPayment(Donation $donation) { $redirectUrl = $this->generateSecureGatewayRouteUrl( 'securelyReturnFromOffsiteRedirect', - $paymentData->donationId, - ['give-donation-id' => $paymentData->donationId] + $donation->id, + ['give-donation-id' => $donation->id] ); return new RedirectOffsite($redirectUrl); @@ -97,20 +99,20 @@ public function createPayment(GatewayPaymentData $paymentData) /** * An example of using a routeMethod for extending the Gateway API to handle a redirect. * + * @unreleased update to use Donation model * @since 2.19.0 * * @param array $queryParams + * + * @return RedirectResponse + * @throws Exception * @throws PaymentGatewayException */ - protected function returnFromOffsiteRedirect($queryParams) + protected function returnFromOffsiteRedirect(array $queryParams): RedirectResponse { - $donationId = $queryParams['give-donation-id']; + $donation = Donation::find($queryParams['give-donation-id']); - if (!get_post($donationId)) { - throw new PaymentGatewayException('Donation does not exist'); - } - - $this->updateDonation($donationId); + $this->updateDonation($donation); return response()->redirectTo(give_get_success_page_uri()); } @@ -118,35 +120,39 @@ protected function returnFromOffsiteRedirect($queryParams) /** * An example of using a secureRouteMethod for extending the Gateway API to handle a redirect. * + * @unreleased update to use Donation model * @since 2.19.0 * * @param array $queryParams - * @throws PaymentGatewayException + * + * @return RedirectResponse + * @throws Exception */ - protected function securelyReturnFromOffsiteRedirect($queryParams) + protected function securelyReturnFromOffsiteRedirect(array $queryParams): RedirectResponse { - $donationId = $queryParams['give-donation-id']; + $donation = Donation::find($queryParams['give-donation-id']); - if (!get_post($donationId)) { - throw new PaymentGatewayException('Donation does not exist'); - } - - $this->updateDonation($donationId); + $this->updateDonation($donation); return response()->redirectTo(give_get_success_page_uri()); } /** - * Helper for updating donation + * @param Donation $donation * - * @param $donationId * @return void + * @throws Exception */ - private function updateDonation($donationId) + private function updateDonation(Donation $donation) { - give_insert_payment_note($donationId, 'NOTE GOES HERE'); - give_update_payment_status($donationId); - give_set_payment_transaction_id($donationId, "test-gateway-transaction-id"); + $donation->status = DonationStatus::COMPLETE(); + $donation->gatewayTransactionId = "test-gateway-transaction-id"; + $donation->save(); + + DonationNote::create([ + 'donationId' => $donation->id, + 'content' => 'Donation Completed from Test Gateway Offsite.' + ]); } /** diff --git a/src/PaymentGateways/PayPalCommerce/PayPalCommerce.php b/src/PaymentGateways/PayPalCommerce/PayPalCommerce.php index 51e91f998c..edde73b5c7 100644 --- a/src/PaymentGateways/PayPalCommerce/PayPalCommerce.php +++ b/src/PaymentGateways/PayPalCommerce/PayPalCommerce.php @@ -32,13 +32,8 @@ class PayPalCommerce extends PaymentGateway /** * @since 2.19.0 - * - * @param int $formId - * @param array $args - * - * @return string */ - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup(int $formId, array $args): string { return give(AdvancedCardFields::class)->addCreditCardForm($formId); } @@ -48,7 +43,7 @@ public function getLegacyFormFieldMarkup($formId, $args) * * @return string */ - public static function id() + public static function id(): string { return 'paypal-commerce'; } @@ -58,7 +53,7 @@ public static function id() * * @return string */ - public function getId() + public function getId(): string { return self::id(); } @@ -68,7 +63,7 @@ public function getId() * * @return string */ - public function getName() + public function getName(): string { return esc_html__('PayPal Donations', 'give'); } @@ -78,7 +73,7 @@ public function getName() * * @return string */ - public function getPaymentMethodLabel() + public function getPaymentMethodLabel(): string { return esc_html__('Credit Card', 'give'); } @@ -86,12 +81,9 @@ public function getPaymentMethodLabel() /** * @since 2.19.0 * - * @param GatewayPaymentData $paymentData - * - * @return GatewayCommand * @throws PaymentGatewayException */ - public function createPayment(GatewayPaymentData $paymentData) + public function createPayment(Donation $donation): GatewayCommand { $paypalOrder = Call::invoke(GetPayPalOrderFromRequest::class); $command = PaymentComplete::make($paypalOrder->payment->id); @@ -104,7 +96,7 @@ public function createPayment(GatewayPaymentData $paymentData) ]; give('payment_meta')->update_meta( - $paymentData->donationId, + $donation->id, '_give_order_id', $paypalOrder->id ); diff --git a/src/Subscriptions/Models/Subscription.php b/src/Subscriptions/Models/Subscription.php index 4be5668520..29f7ca0644 100644 --- a/src/Subscriptions/Models/Subscription.php +++ b/src/Subscriptions/Models/Subscription.php @@ -5,7 +5,6 @@ use DateTime; use Exception; use Give\Donations\Models\Donation; -use Give\Donations\ValueObjects\DonationStatus; use Give\Donors\Models\Donor; use Give\Framework\Models\Contracts\ModelCrud; use Give\Framework\Models\Contracts\ModelHasFactory; @@ -88,7 +87,7 @@ public static function find($id) * * @return ModelQueryBuilder */ - public function donor() + public function donor(): ModelQueryBuilder { return give()->donors->queryById($this->donorId); } @@ -98,7 +97,7 @@ public function donor() * * @return ModelQueryBuilder */ - public function donations() + public function donations(): ModelQueryBuilder { return give()->donations->queryBySubscriptionId($this->id); } @@ -110,7 +109,7 @@ public function donations() * * @return object[] */ - public function getNotes() + public function getNotes(): array { return give()->subscriptions->getNotesBySubscriptionId($this->id); } @@ -165,7 +164,7 @@ public function save() * @return bool * @throws Exception */ - public function delete() + public function delete(): bool { return give()->subscriptions->delete($this); } @@ -177,7 +176,7 @@ public function delete() * * @throws Exception */ - public function cancel($force = false) + public function cancel(bool $force = false) { if (!$force && $this->status->isCanceled()) { return; @@ -191,7 +190,7 @@ public function cancel($force = false) * * @return ModelQueryBuilder */ - public static function query() + public static function query(): ModelQueryBuilder { return give()->subscriptions->prepareQuery(); } @@ -203,7 +202,7 @@ public static function query() * * @return Subscription */ - public static function fromQueryBuilderObject($object) + public static function fromQueryBuilderObject($object): Subscription { return SubscriptionQueryData::fromObject($object)->toSubscription(); } @@ -215,7 +214,7 @@ public static function fromQueryBuilderObject($object) * * @return string */ - public function expiration() + public function expiration(): string { $frequency = $this->frequency; $period = $this->period; @@ -232,7 +231,7 @@ public function expiration() /** * @return PaymentGateway */ - public function gateway() + public function gateway(): PaymentGateway { return give()->gateways->getPaymentGateway($this->gatewayId); } @@ -240,7 +239,7 @@ public function gateway() /** * @return SubscriptionFactory */ - public static function factory() + public static function factory(): SubscriptionFactory { return new SubscriptionFactory(static::class); } diff --git a/src/Subscriptions/Repositories/SubscriptionRepository.php b/src/Subscriptions/Repositories/SubscriptionRepository.php index 195936974b..fa00f5d5d3 100644 --- a/src/Subscriptions/Repositories/SubscriptionRepository.php +++ b/src/Subscriptions/Repositories/SubscriptionRepository.php @@ -167,7 +167,7 @@ public function insert(Subscription $subscription) * * @param Subscription $subscription * - * @return void + * @return Subscription * @throws Exception */ public function update(Subscription $subscription) @@ -204,7 +204,13 @@ public function update(Subscription $subscription) DB::query('COMMIT'); - Hooks::doAction('give_subscription_updating', $subscription); + $subscriptionId = DB::last_insert_id(); + + $subscription = $this->getById($subscriptionId); + + Hooks::doAction('give_subscription_updated', $subscription); + + return $subscription; } /** diff --git a/tests/unit/tests/Donations/Models/TestDonation.php b/tests/unit/tests/Donations/Models/TestDonation.php index 1661b043e1..2ae163489c 100644 --- a/tests/unit/tests/Donations/Models/TestDonation.php +++ b/tests/unit/tests/Donations/Models/TestDonation.php @@ -4,6 +4,7 @@ use Exception; use Give\Donations\Models\Donation; +use Give\Donations\Models\DonationNote; use Give\Donations\ValueObjects\DonationStatus; use Give\Donors\Models\Donor; use Give\Framework\Database\DB; @@ -39,6 +40,7 @@ public function tearDown() $donorMetaTable = DB::prefix('give_donormeta'); $subscriptionsTable = DB::prefix('give_subscriptions'); $sequentialOrderingTable = DB::prefix('give_sequential_ordering'); + $notesTable = DB::prefix('give_comments'); DB::query("TRUNCATE TABLE $donorTable"); DB::query("TRUNCATE TABLE $donorMetaTable"); @@ -46,6 +48,7 @@ public function tearDown() DB::query("TRUNCATE TABLE $donationsTable"); DB::query("TRUNCATE TABLE $subscriptionsTable"); DB::query("TRUNCATE TABLE $sequentialOrderingTable"); + DB::query("TRUNCATE TABLE $notesTable"); } /** @@ -68,6 +71,8 @@ public function testCreateShouldInsertDonation() 'lastName' => 'Murray', 'email' => 'billMurray@givewp.com', 'formId' => 1, + 'levelId' => 'custom', + 'anonymous' => true ]); $donationFromDatabase = Donation::find($donation->id); @@ -122,6 +127,48 @@ public function testDonationShouldGetSequentialId() $this->assertEquals(1, $donation->getSequentialId()); } + /** + * @unreleased + * + * @throws Exception + */ + public function testShouldGetNotes() + { + /** @var Donor $donor */ + $donor = Donor::factory()->create(); + + /** @var Donation $donation */ + $donation = Donation::factory()->create(['donorId' => $donor->id]); + + $donationNote1 = DonationNote::factory()->create(['donationId' => $donation->id]); + $donationNote2 = DonationNote::factory()->create(['donationId' => $donation->id]); + $donationNote3 = DonationNote::factory()->create(['donationId' => $donation->id]); + + $this->assertCount(3, $donation->notes); + + $this->assertEquals($donationNote1->id, $donation->notes[2]->id); + $this->assertEquals($donationNote2->id, $donation->notes[1]->id); + $this->assertEquals($donationNote3->id, $donation->notes[0]->id); + } + + /** + * @unreleased + */ + public function testDonationShouldGetIntendedAmountInBaseCurrency() + { + // When a donation has a fee recovery amount + $donation = Donation::factory()->create([ + 'amount' => new Money(5000, 'USD'), + 'feeAmountRecovered' => new Money(500, 'USD'), + 'exchangeRate' => '0.9', + ]); + + self::assertMoneyEquals( + $donation->intendedAmount()->inBaseCurrency($donation->exchangeRate), + $donation->intendedAmountInBaseCurrency() + ); + } + /** * @unreleased */ @@ -158,22 +205,4 @@ public function testDonationShouldGetIntendedAmount() self::assertMoneyEquals(new Money(5000, 'USD'), $donation->intendedAmount()); } - - /** - * @unreleased - */ - public function testDonationShouldGetIntendedAmountInBaseCurrency() - { - // When a donation has a fee recovery amount - $donation = Donation::factory()->create([ - 'amount' => new Money(5000, 'USD'), - 'feeAmountRecovered' => new Money(500, 'USD'), - 'exchangeRate' => '0.9', - ]); - - self::assertMoneyEquals( - $donation->intendedAmount()->inBaseCurrency($donation->exchangeRate), - $donation->intendedAmountInBaseCurrency() - ); - } } diff --git a/tests/unit/tests/Donations/Models/TestDonationNote.php b/tests/unit/tests/Donations/Models/TestDonationNote.php new file mode 100644 index 0000000000..51731f4256 --- /dev/null +++ b/tests/unit/tests/Donations/Models/TestDonationNote.php @@ -0,0 +1,75 @@ +create(); + $donation = Donation::factory()->create(['donorId' => $donor->id]); + + $donationNote = DonationNote::create([ + 'donationId' => $donation->id, + 'content' => 'im a note' + ]); + + $donationNoteFromDatabase = DonationNote::find($donationNote->id); + + $this->assertEquals($donationNote->getAttributes(), $donationNoteFromDatabase->getAttributes()); + } + + /** + * @unreleased + * + * @return void + * @throws Exception + */ + public function testDonationNoteShouldGetDonation() + { + $donor = Donor::factory()->create(); + + /** @var Donation $donation */ + $donation = Donation::factory()->create(['donorId' => $donor->id]); + + /** @var DonationNote $donationNote */ + $donationNote = DonationNote::factory()->create(['donationId' => $donation->id]); + + $this->assertInstanceOf(Donation::class, $donationNote->donation); + $this->assertEquals($donation->id, $donationNote->donation->id); + } +} diff --git a/tests/unit/tests/Donations/Repositories/TestDonationNoteRepository.php b/tests/unit/tests/Donations/Repositories/TestDonationNoteRepository.php new file mode 100644 index 0000000000..5d22f6a844 --- /dev/null +++ b/tests/unit/tests/Donations/Repositories/TestDonationNoteRepository.php @@ -0,0 +1,213 @@ +create(); + $donation = Donation::factory()->create(['donorId' => $donor->id]); + $donationNote = DonationNote::factory()->create(['donationId' => $donation->id]); + $repository = new DonationNotesRepository(); + + $donationNoteFromDatabase = $repository->getById($donationNote->id); + + $this->assertInstanceOf(DonationNote::class, $donationNoteFromDatabase); + $this->assertEquals($donationNote->id, $donationNoteFromDatabase->id); + } + + /** + * @unreleased + * + * @return void + * + * @throws Exception + */ + public function testInsertShouldAddDonationNoteToDatabase() + { + $donor = Donor::factory()->create(); + $donation = Donation::factory()->create(['donorId' => $donor->id]); + $donationNote = new DonationNote(['donationId' => $donation->id, 'content' => 'im a note']); + + $repository = new DonationNotesRepository(); + + $repository->insert($donationNote); + + /** @var DonationNote $query */ + $query = $repository->prepareQuery() + ->where('comment_ID', $donationNote->id) + ->get(); + + + // simulate asserting database has values + $this->assertInstanceOf(DonationNote::class, $donationNote); + $this->assertEquals($query->id, $donationNote->id); + $this->assertEquals($query->donationId, $donationNote->donationId); + $this->assertEquals($query->content, $donationNote->content); + } + + /** + * @unreleased + * + * @return void + * + * @throws Exception + */ + public function testInsertShouldFailValidationWhenMissingKeyAndThrowException() + { + $this->expectException(InvalidArgumentException::class); + + $donationNoteMissingDonationId = new DonationNote([ + 'content' => 'im a note', + ]); + + $repository = new DonationNotesRepository(); + + $repository->insert($donationNoteMissingDonationId); + } + + /** + * @unreleased + * + * @return void + * + * @throws Exception + */ + public function testInsertShouldFailValidationWhenDonationDoesNotExistAndThrowException() + { + $this->expectException(InvalidArgumentException::class); + + $donationNoteWithInvalidDonation = new DonationNote([ + 'donationId' => 10000, + 'content' => 'im a note' + ]); + + $repository = new DonationNotesRepository(); + + $repository->insert($donationNoteWithInvalidDonation); + } + + /** + * @unreleased + * + * @return void + * + * @throws Exception + */ + public function testUpdateShouldFailValidationAndThrowException() + { + $this->expectException(InvalidArgumentException::class); + + $donationNoteMissingDonationId = new DonationNote([ + 'content' => 'im a note' + ]); + + $repository = new DonationNotesRepository(); + + $repository->update($donationNoteMissingDonationId); + } + + /** + * @unreleased + * + * @return void + * + * @throws Exception + */ + public function testUpdateShouldUpdateDonationNoteValuesInTheDatabase() + { + /** @var Donor $donor */ + $donor = Donor::factory()->create(); + + /** @var Donation $donation */ + $donation = Donation::factory()->create(['donorId' => $donor->id]); + + /** @var DonationNote $donationNote */ + $donationNote = DonationNote::factory()->create(['donationId' => $donation->id]); + + $repository = new DonationNotesRepository(); + + $donationNote->content = 'im an updated note'; + + // call update method + $repository->update($donationNote); + + /** @var DonationNote $query */ + $query = $repository->prepareQuery() + ->where('comment_ID', $donationNote->id) + ->get(); + + $this->assertEquals('im an updated note', $query->content); + } + + /** + * @unreleased + * + * @return void + * + * @throws Exception + */ + public function testDeleteShouldRemoveDonationNoteFromTheDatabase() + { + /** @var Donor $donor */ + $donor = Donor::factory()->create(); + + /** @var Donation $donation */ + $donation = Donation::factory()->create(['donorId' => $donor->id]); + + /** @var DonationNote $donationNote */ + $donationNote = DonationNote::factory()->create(['donationId' => $donation->id]); + + $repository = new DonationNotesRepository(); + + $repository->delete($donationNote); + + /** @var DonationNote $query */ + $query = $repository->prepareQuery() + ->where('comment_ID', $donation->id) + ->get(); + + $this->assertNull($query); + } +} diff --git a/tests/unit/tests/Donations/TestDonationRepository.php b/tests/unit/tests/Donations/Repositories/TestDonationRepository.php similarity index 99% rename from tests/unit/tests/Donations/TestDonationRepository.php rename to tests/unit/tests/Donations/Repositories/TestDonationRepository.php index 6dc9d199f7..5035a59a50 100644 --- a/tests/unit/tests/Donations/TestDonationRepository.php +++ b/tests/unit/tests/Donations/Repositories/TestDonationRepository.php @@ -1,6 +1,6 @@ donorInfo = new DonorInfo(); - $paymentData->donationId = Give_Helper_Payment::create_simple_payment(); + $donationId = Give_Helper_Payment::create_simple_payment(); + $donation = Donation::find($donationId); - $summary = new DonationSummary($paymentData); + $summary = new DonationSummary($donation); $this->assertEquals( - give_payment_gateway_donation_summary($this->get_legacy_donation_data($paymentData), false), + give_payment_gateway_donation_summary($this->get_legacy_donation_data($donation), false), $summary->getSummary() ); } @@ -31,15 +29,16 @@ public function it_summarizes_a_simple_donation() /** @test */ public function it_summarizes_a_multilevel_donation() { - $paymentData = new GatewayPaymentData(); - $paymentData->donorInfo = new DonorInfo(); - $paymentData->donationId = Give_Helper_Payment::create_multilevel_payment(['result_type' => 'object']); - $paymentData->priceId = 2; + $donationId = Give_Helper_Payment::create_multilevel_payment(['result_type' => 'object']); + $donation = Donation::find($donationId); + $donation->levelId = '2'; - $summary = new DonationSummary($paymentData); + $donation->save(); + + $summary = new DonationSummary($donation); $this->assertEquals( - give_payment_gateway_donation_summary($this->get_legacy_donation_data($paymentData), false), + give_payment_gateway_donation_summary($this->get_legacy_donation_data($donation), false), $summary->getSummary() ); } @@ -47,17 +46,18 @@ public function it_summarizes_a_multilevel_donation() /** @test */ public function it_summarizes_a_donation_with_donor_name_and_email() { - $paymentData = new GatewayPaymentData(); - $paymentData->donorInfo = new DonorInfo(); - $paymentData->donorInfo->firstName = 'Tester'; - $paymentData->donorInfo->lastName = 'Test'; - $paymentData->donorInfo->email = 'tester@test.test'; - $paymentData->donationId = Give_Helper_Payment::create_simple_payment(); + $donationId = Give_Helper_Payment::create_simple_payment(); + $donation = Donation::find($donationId); + $donation->firstName = 'Tester'; + $donation->lastName = 'Test'; + $donation->email = 'tester@test.test'; + + $donation->save(); - $summary = new DonationSummary($paymentData); + $summary = new DonationSummary($donation); $this->assertEquals( - give_payment_gateway_donation_summary($this->get_legacy_donation_data($paymentData), true), + give_payment_gateway_donation_summary($this->get_legacy_donation_data($donation), true), $summary->getSummaryWithDonor() ); } @@ -65,18 +65,17 @@ public function it_summarizes_a_donation_with_donor_name_and_email() /** @test */ public function it_summarizes_a_donation_with_filter() { - $paymentData = new GatewayPaymentData(); - $paymentData->donorInfo = new DonorInfo(); - $paymentData->donationId = Give_Helper_Payment::create_simple_payment(); + $donationId = Give_Helper_Payment::create_simple_payment(); + $donation = Donation::find($donationId); add_filter('give_payment_gateway_donation_summary', function ($summary) { return 'FILTERED SUMMARY'; }); - $summary = new DonationSummary($paymentData); + $summary = new DonationSummary($donation); $this->assertEquals( - give_payment_gateway_donation_summary($this->get_legacy_donation_data($paymentData), false), + give_payment_gateway_donation_summary($this->get_legacy_donation_data($donation), false), $summary->getSummary() ); } @@ -85,35 +84,34 @@ public function it_summarizes_a_donation_with_filter() public function it_summarizes_a_simple_donation_truncated() { $length = 10; - $paymentData = new GatewayPaymentData(); - $paymentData->donorInfo = new DonorInfo(); - $paymentData->donationId = Give_Helper_Payment::create_simple_payment(); + $donationId = Give_Helper_Payment::create_simple_payment(); + $donation = Donation::find($donationId); - $summary = new DonationSummary($paymentData); + $summary = new DonationSummary($donation); $summary->setLength($length); $this->assertEquals( - give_payment_gateway_donation_summary($this->get_legacy_donation_data($paymentData), false, $length), + give_payment_gateway_donation_summary($this->get_legacy_donation_data($donation), false, $length), $summary->getSummary() ); } - public function get_legacy_donation_data(GatewayPaymentData $paymentData) + public function get_legacy_donation_data(Donation $donation) { - $formId = give_get_payment_form_id($paymentData->donationId); + $formId = give_get_payment_form_id($donation->id); return [ 'source_id' => 'pm_1234', - 'donation_id' => $paymentData->donationId, + 'donation_id' => $donation->id, 'post_data' => [ 'give-form-title' => get_the_title($formId), 'give-form-id' => $formId, - 'give-price-id' => $paymentData->priceId, + 'give-price-id' => $donation->levelId, ], 'user_info' => [ - 'first_name' => $paymentData->donorInfo->firstName, - 'last_name' => $paymentData->donorInfo->lastName, + 'first_name' => $donation->firstName, + 'last_name' => $donation->lastName, ], - 'user_email' => $paymentData->donorInfo->email, + 'user_email' => $donation->email, ]; } } diff --git a/tests/unit/tests/Framework/PaymentGateways/Traits/HasRouteMethodTest.php b/tests/unit/tests/Framework/PaymentGateways/Traits/HasRouteMethodTest.php index 3b2b51b05c..80357f5139 100644 --- a/tests/unit/tests/Framework/PaymentGateways/Traits/HasRouteMethodTest.php +++ b/tests/unit/tests/Framework/PaymentGateways/Traits/HasRouteMethodTest.php @@ -1,10 +1,9 @@ setUpStripeAccounts(); + parent::setUp(); + $this->setUpStripeAccounts(); $this->form = Give_Helper_Form::create_simple_form(); $_POST['give-form-id'] = $this->form->get_ID(); @@ -26,11 +25,11 @@ public function it_creates_a_payment_that_is_complete() $_POST['give_stripe_payment_method'] = 'pm_1234'; $gateway = new CreditCardGateway(); - $this->mock(Give_Stripe_Payment_Intent::class, function() { - return new Give_Stripe_Payment_Intent( 'succeeded' ); + $this->mock(Give_Stripe_Payment_Intent::class, function () { + return new Give_Stripe_Payment_Intent('succeeded'); }); - $this->assertInstanceOf( PaymentComplete::class, $gateway->createPayment( $this->getMockPaymentData() ) ); + $this->assertInstanceOf(PaymentComplete::class, $gateway->createPayment($this->getDonationModel())); } /** @test */ @@ -39,11 +38,11 @@ public function it_creates_a_payment_that_is_processing() $_POST['give_stripe_payment_method'] = 'pm_1234'; $gateway = new CreditCardGateway(); - $this->mock(Give_Stripe_Payment_Intent::class, function() { - return new Give_Stripe_Payment_Intent( 'processing' ); + $this->mock(Give_Stripe_Payment_Intent::class, function () { + return new Give_Stripe_Payment_Intent('processing'); }); - $this->assertInstanceOf( PaymentProcessing::class, $gateway->createPayment( $this->getMockPaymentData() ) ); + $this->assertInstanceOf(PaymentProcessing::class, $gateway->createPayment($this->getDonationModel())); } /** @test */ @@ -52,22 +51,18 @@ public function it_creates_a_payment_that_requires_action() $_POST['give_stripe_payment_method'] = 'pm_1234'; $gateway = new CreditCardGateway(); - $this->mock(Give_Stripe_Payment_Intent::class, function() { - return new Give_Stripe_Payment_Intent( 'requires_action' ); + $this->mock(Give_Stripe_Payment_Intent::class, function () { + return new Give_Stripe_Payment_Intent('requires_action'); }); - $this->assertInstanceOf( RedirectOffsite::class, $gateway->createPayment( $this->getMockPaymentData() ) ); + $this->assertInstanceOf(RedirectOffsite::class, $gateway->createPayment($this->getDonationModel())); } - public function getMockPaymentData() + public function getDonationModel() { - $paymentData = new GatewayPaymentData; - $paymentData->donationId = 0; - $paymentData->price = '1.00'; - $paymentData->currency = 'USD'; - $paymentData->donorInfo = new DonorInfo(); - $paymentData->donorInfo->email = 'tester@test.test'; - return $paymentData; + $donationId = Give_Helper_Payment::create_simple_payment(); + + return \Give\Donations\Models\Donation::find($donationId); } private function setUpStripeAccounts() @@ -105,31 +100,40 @@ private function setUpStripeAccounts() ); // Set default account globally. - give_update_option( '_give_stripe_default_account', 'account_1' ); + give_update_option('_give_stripe_default_account', 'account_1'); } } -class Give_Stripe_Customer { - public function get_id() { +class Give_Stripe_Customer +{ + public function get_id() + { return 'cust_1234'; } } -class Give_Stripe_Payment_Intent { +class Give_Stripe_Payment_Intent +{ protected $status; - public function __construct( $status ) { + + public function __construct($status) + { $this->status = $status; } - public function create() { - return json_decode(json_encode([ - 'id' => 'pi_1234', - 'status' => $this->status, - 'client_secret' => 'pi_secret', - 'next_action' => [ - 'redirect_to_url' => [ - 'url' => '', + + public function create() + { + return json_decode( + json_encode([ + 'id' => 'pi_1234', + 'status' => $this->status, + 'client_secret' => 'pi_secret', + 'next_action' => [ + 'redirect_to_url' => [ + 'url' => '', + ] ] - ] - ])); + ]) + ); } } diff --git a/tests/unit/tests/PaymentGateways/PaymentGatewaysRegisterTest.php b/tests/unit/tests/PaymentGateways/PaymentGatewaysRegisterTest.php index 965fff7f5c..343e31d686 100644 --- a/tests/unit/tests/PaymentGateways/PaymentGatewaysRegisterTest.php +++ b/tests/unit/tests/PaymentGateways/PaymentGatewaysRegisterTest.php @@ -122,12 +122,12 @@ public function getPaymentMethodLabel(): string return 'Credit Card'; } - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup(int $formId, array $args): string { // TODO: Implement getLegacyFormFieldMarkup() method. } - public function createPayment(GatewayPaymentData $paymentData) + public function createPayment(Donation $donation) { // TODO: Implement createPayment() method. } @@ -175,12 +175,12 @@ public function getPaymentMethodLabel(): string return 'PayPal'; } - public function getLegacyFormFieldMarkup($formId, $args) + public function getLegacyFormFieldMarkup(int $formId, array $args): string { // TODO: Implement getLegacyFormFieldMarkup() method. } - public function createPayment(GatewayPaymentData $paymentData) + public function createPayment(Donation $donation) { // TODO: Implement createPayment() method. } From 54cfc00b0eb7c90b4985fec7bba47229e9a9d065 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Mon, 16 May 2022 09:59:24 -0700 Subject: [PATCH 09/53] chore: bump platform PHP version to 7.0 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 454b8219d3..ea373ef873 100644 --- a/composer.json +++ b/composer.json @@ -55,7 +55,7 @@ }, "config": { "platform": { - "php": "5.6.40" + "php": ">=7.0" }, "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true, From fa4e716dbf8206a6336c4535e7004163aa439432 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Mon, 16 May 2022 10:05:47 -0700 Subject: [PATCH 10/53] chore: lock platform php version to 7.0 to avoid installing packages on higher versions --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ea373ef873..30aca8bf06 100644 --- a/composer.json +++ b/composer.json @@ -55,7 +55,7 @@ }, "config": { "platform": { - "php": ">=7.0" + "php": "7.0" }, "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true, From 54a43e9825606e36705229b5b2096f68ef05d8ce Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Mon, 16 May 2022 13:52:16 -0700 Subject: [PATCH 11/53] chore: remove Cypress and e2e tests in favor of Ghost Inspector --- .distignore | 1 - .gitignore | 5 - cypress.json | 15 - package-lock.json | 2764 +---------------- package.json | 2 - tests/e2e/README.md | 18 - tests/e2e/fixtures/example.json | 5 - tests/e2e/integration/logs/logs_page_spec.js | 80 - .../onboarding/onboarding_wizard_spec.js | 171 - .../integration/onboarding/setup_page_spec.js | 29 - tests/e2e/integration/sample_spec.js | 8 - tests/e2e/plugins/index.js | 23 - tests/e2e/support/commands.js | 41 - tests/e2e/support/index.d.ts | 18 - tests/e2e/support/index.js | 20 - 15 files changed, 71 insertions(+), 3129 deletions(-) delete mode 100644 cypress.json delete mode 100644 tests/e2e/README.md delete mode 100644 tests/e2e/fixtures/example.json delete mode 100644 tests/e2e/integration/logs/logs_page_spec.js delete mode 100644 tests/e2e/integration/onboarding/onboarding_wizard_spec.js delete mode 100644 tests/e2e/integration/onboarding/setup_page_spec.js delete mode 100644 tests/e2e/integration/sample_spec.js delete mode 100644 tests/e2e/plugins/index.js delete mode 100644 tests/e2e/support/commands.js delete mode 100644 tests/e2e/support/index.d.ts delete mode 100644 tests/e2e/support/index.js diff --git a/.distignore b/.distignore index 64695d3653..15edd1340b 100644 --- a/.distignore +++ b/.distignore @@ -32,7 +32,6 @@ jsconfig.json globals.d.ts tsconfig.json -cypress.json sample-data/wordpress.sql sample-data/sample-data.numbers bower.json diff --git a/.gitignore b/.gitignore index e98ade911f..1b5241348c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,6 @@ /tmp /tests/bin/tmp -# Cypress -/cypress -/tests/e2e/videos -/tests/e2e/screenshots - # Numerous always-ignore extensions .diff .err diff --git a/cypress.json b/cypress.json deleted file mode 100644 index c285f70db7..0000000000 --- a/cypress.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "env": { - "wp_user": "admin", - "wp_pass": "password", - "site": { - "url": "http://localhost:8888" - } - }, - "fixturesFolder": "tests/e2e/fixtues", - "integrationFolder": "tests/e2e/integration", - "pluginsFolder": "tests/e2e/plugins", - "screenshotsFolder": "tests/e2e/screenshots", - "videosFolder": "tests/e2e/videos", - "supportFile": "tests/e2e/support/index.js" -} diff --git a/package-lock.json b/package-lock.json index d598ce76fa..82f0d25660 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@wordpress/hooks": "^3.3.1", "@wordpress/i18n": "^3.19.0", "@wordpress/server-side-render": "^3.1.3", - "accounting": "*", + "accounting": "latest", "axios": "^0.21.2", "chart.js": "^2.9.3", "chartjs-plugin-crosshair": "^1.1.4", @@ -36,10 +36,10 @@ "hint.css": "^2.5.1", "iframe-resizer": "^4.2.10", "jquery": "^3.6.0", - "jquery-chosen": "*", - "jquery.payment": "*", + "jquery-chosen": "latest", + "jquery.payment": "latest", "lodash": "^4.17.21", - "magnific-popup": "*", + "magnific-popup": "latest", "moment": "^2.24.0", "prop-types": "^15.7.2", "react": "^16.12.0", @@ -58,7 +58,7 @@ "react-select": "^3.1.0", "styled-components": "^5.2.1", "swr": "^1.2.0", - "uiblocker": "*", + "uiblocker": "latest", "vhtml": "^2.2.0" }, "devDependencies": { @@ -79,7 +79,6 @@ "axios-mock-adapter": "^1.18.2", "babel-loader": "^8.2.2", "babel-plugin-react-require": "^3.1.3", - "cypress": "^8.7.0", "jest": "^24.9.0", "jest-puppeteer": "^4.4.0", "laravel-mix": "^6.0.34", @@ -1804,73 +1803,6 @@ "node": ">=0.1.95" } }, - "node_modules/@cypress/request": { - "version": "2.88.6", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.6.tgz", - "integrity": "sha512-z0UxBE/+qaESAHY9p9sM2h8Y4XqtsbDCt0/DPOrqA/RZgKi4PkxdpXyK4wCCnSk1xHqWHZZAE+gV6aDAR6+caQ==", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@cypress/request/node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/@cypress/request/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - } - }, - "node_modules/@cypress/xvfb/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz", @@ -2869,27 +2801,6 @@ "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", "dev": true }, - "node_modules/@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "peer": true, - "dependencies": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@mrmlnc/readdir-enhanced/node_modules/glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", - "dev": true, - "peer": true - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3638,18 +3549,6 @@ "@types/node": "*" } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", - "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", - "dev": true - }, - "node_modules/@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true - }, "node_modules/@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -3659,101 +3558,12 @@ "@types/node": "*" } }, - "node_modules/@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", "dev": true }, - "node_modules/@types/tapable": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", - "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/@types/uglify-js": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", - "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/@types/uglify-js/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@types/webpack": { - "version": "4.41.31", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.31.tgz", - "integrity": "sha512-/i0J7sepXFIp1ZT7FjUGi1eXMCg8HCCzLJEQkKsOtbJFontsJLolBcDC+3qxn5pPwiCt1G0ZdRmYRzNBtvpuGQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@types/node": "*", - "@types/tapable": "^1", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "anymatch": "^3.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/@types/webpack-sources": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", - "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - } - }, - "node_modules/@types/webpack-sources/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/webpack/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@types/ws": { "version": "8.5.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.2.tgz", @@ -3778,16 +3588,6 @@ "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", "dev": true }, - "node_modules/@types/yauzl": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", - "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@use-gesture/core": { "version": "10.2.9", "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.2.9.tgz", @@ -5783,12 +5583,12 @@ "node_modules/accounting": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/accounting/-/accounting-0.4.1.tgz", - "integrity": "sha1-h91BA+/39EYPHhhvXGd+1s9WaIM=" + "integrity": "sha512-RU6KY9Y5wllyaCNBo1W11ZOTnTHMMgOZkIwdOOs6W5ibMTp72i4xIbEA48djxVGqMNTUNbvrP/1nWg5Af5m2gQ==" }, "node_modules/acorn": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", - "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -5995,15 +5795,6 @@ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -6075,26 +5866,6 @@ "node": ">= 8" } }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -6149,29 +5920,6 @@ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", "dev": true }, - "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "peer": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -6210,16 +5958,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -6299,12 +6037,6 @@ "node": ">=4" } }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true - }, "node_modules/async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", @@ -6317,15 +6049,6 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -6818,18 +6541,6 @@ "file-uri-to-path": "1.0.0" } }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, "node_modules/blueimp-md5": { "version": "2.18.0", "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.18.0.tgz", @@ -7196,15 +6907,6 @@ "node": ">=8" } }, - "node_modules/cachedir": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", - "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -7217,13 +6919,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true, - "peer": true - }, "node_modules/caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -7382,15 +7077,6 @@ "chart.js": "^2.9.3" } }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -7581,22 +7267,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", @@ -7854,15 +7524,6 @@ "node": ">= 6" } }, - "node_modules/common-tags": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -8096,7 +7757,7 @@ "version": "2.6.12", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", + "deprecated": "core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", "dev": true, "hasInstallScript": true }, @@ -8755,264 +8416,6 @@ "node": ">=0.8" } }, - "node_modules/cypress": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-8.7.0.tgz", - "integrity": "sha512-b1bMC3VQydC6sXzBMFnSqcvwc9dTZMgcaOzT0vpSD+Gq1yFc+72JDWi55sfUK5eIeNLAtWOGy1NNb6UlhMvB+Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@cypress/request": "^2.88.6", - "@cypress/xvfb": "^1.2.4", - "@types/node": "^14.14.31", - "@types/sinonjs__fake-timers": "^6.0.2", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.0", - "commander": "^5.1.0", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.2", - "enquirer": "^2.3.6", - "eventemitter2": "^6.4.3", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.0", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.5", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "proxy-from-env": "1.0.0", - "ramda": "~0.27.1", - "request-progress": "^3.0.0", - "supports-color": "^8.1.1", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "url": "^0.11.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/cypress/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cypress/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", - "dev": true - }, - "node_modules/cypress/node_modules/cli-table3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.0.tgz", - "integrity": "sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "colors": "^1.1.2" - } - }, - "node_modules/cypress/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cypress/node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cypress/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/cypress/node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/cypress/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cypress/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/cypress/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/cypress/node_modules/proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true - }, - "node_modules/cypress/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/cypress/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -9047,16 +8450,10 @@ "webidl-conversions": "^4.0.2" } }, - "node_modules/dayjs": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.5.tgz", - "integrity": "sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==", - "dev": true - }, "node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -9464,43 +8861,6 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, - "node_modules/dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "dev": true, - "peer": true, - "dependencies": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/dir-glob/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "peer": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/dir-glob/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, "node_modules/direction": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/direction/-/direction-1.0.4.tgz", @@ -9837,18 +9197,6 @@ "node": ">=10.13.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", @@ -10166,12 +9514,6 @@ "node": ">= 0.6" } }, - "node_modules/eventemitter2": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.4.tgz", - "integrity": "sha512-HLU3NDY6wARrLCEwyGKRBvuWYyvW6mHYv72SJJAH3iJN3a6eVUvkjFkcxah1bcTgGVBBrFdIopBJPhCQFMLyXw==", - "dev": true - }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -10203,100 +9545,6 @@ "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", "dev": true }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/execa/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -10794,16 +10042,6 @@ "node": ">= 10" } }, - "node_modules/file-type": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", - "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -11370,15 +10608,6 @@ "node": ">=0.10.0" } }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, - "dependencies": { - "async": "^3.2.0" - } - }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -11447,30 +10676,6 @@ "node": ">= 0.4" } }, - "node_modules/global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-dirs/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -11479,233 +10684,6 @@ "node": ">=4" } }, - "node_modules/globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "dev": true, - "peer": true, - "dependencies": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby/node_modules/@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "peer": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "peer": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "dev": true, - "peer": true, - "dependencies": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/globby/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "peer": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "peer": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "peer": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/globby/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "peer": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "peer": true - }, - "node_modules/globby/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "peer": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "peer": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "peer": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "peer": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/good-listener": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", @@ -12399,15 +11377,6 @@ "ms": "^2.1.1" } }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "engines": { - "node": ">=8.12.0" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -12464,13 +11433,6 @@ "url": "https://github.com/davidjbradshaw/iframe-resizer/blob/master/FUNDING.md" } }, - "node_modules/ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true, - "peer": true - }, "node_modules/image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", @@ -12484,57 +11446,6 @@ "node": ">=0.10.0" } }, - "node_modules/imagemin": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-6.1.0.tgz", - "integrity": "sha512-8ryJBL1CN5uSHpiBMX0rJw79C9F9aJqMnjGnrd/1CafegpNuA81RBAAru/jQQEOWlOJJlpRnlcVFF6wq+Ist0A==", - "dev": true, - "peer": true, - "dependencies": { - "file-type": "^10.7.0", - "globby": "^8.0.1", - "make-dir": "^1.0.0", - "p-pipe": "^1.1.0", - "pify": "^4.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imagemin/node_modules/make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "peer": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/make-dir/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/img-loader": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/img-loader/-/img-loader-4.0.0.tgz", @@ -13112,9 +12023,9 @@ } }, "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { "is-extglob": "^2.1.1" @@ -13123,22 +12034,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -13300,18 +12195,6 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -16550,15 +15433,6 @@ "node": ">=10" } }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", - "dev": true, - "engines": { - "node": "> 0.8" - } - }, "node_modules/lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -16692,33 +15566,6 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" }, - "node_modules/listr2": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.13.1.tgz", - "integrity": "sha512-pk4YBDA2cxtpM8iLHbz6oEsfZieJKHf6Pt19NlKaHZZVpqHyVs/Wqr7RfBBCeAFCJchGO7WQHVkUPZTvJMHk8w==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rxjs": "^6.6.7", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - } - }, - "node_modules/listr2/node_modules/colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true - }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -16831,12 +15678,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", - "dev": true - }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -16849,171 +15690,6 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -17327,9 +16003,9 @@ "dev": true }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -18263,12 +16939,6 @@ "node": ">=0.10.0" } }, - "node_modules/ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=", - "dev": true - }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -18377,16 +17047,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-pipe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", - "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, "node_modules/p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", @@ -18545,13 +17205,6 @@ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true, - "peer": true - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -18630,12 +17283,6 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, - "node_modules/php-parser": { - "version": "3.0.0-prerelease.9", - "resolved": "git+ssh://git@github.com/glayzzle/php-parser.git#3279b7ee9bd78b914b5b840edc749eee0fabbfd8", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -18652,15 +17299,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/pirates": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", @@ -20323,18 +18961,6 @@ "node": ">=10.13.0" } }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pretty-format": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", @@ -20516,6 +19142,7 @@ "version": "1.20.0", "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.20.0.tgz", "integrity": "sha512-bt48RDBy2eIwZPrkgbcwHtb51mj2nKvHOPMaSH2IsWiv7lOG9k9zhaRzpDZafrk05ajMc3cu+lSQYYOfH2DkVQ==", + "deprecated": "Version no longer supported. Upgrade to @latest", "dev": true, "hasInstallScript": true, "dependencies": { @@ -20579,6 +19206,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", "engines": { "node": ">=0.4.x" } @@ -20620,12 +19248,6 @@ "performance-now": "^2.1.0" } }, - "node_modules/ramda": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz", - "integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==", - "dev": true - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -21453,15 +20075,6 @@ "node": ">= 6" } }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", - "dev": true, - "dependencies": { - "throttleit": "^1.0.0" - } - }, "node_modules/request-promise-core": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", @@ -21935,6 +20548,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "deprecated": "some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added", "dev": true, "dependencies": { "@cnakazawa/watch": "^1.0.3", @@ -22627,66 +21241,6 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, - "node_modules/slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -22877,6 +21431,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", "dev": true, "dependencies": { "atob": "^2.1.2", @@ -22909,6 +21464,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true }, "node_modules/spawnd": { @@ -23282,20 +21838,20 @@ } }, "node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { "node": ">=8" } @@ -23950,12 +22506,6 @@ "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", "dev": true }, - "node_modules/throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -24001,18 +22551,6 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, "node_modules/tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", @@ -24361,9 +22899,9 @@ } }, "node_modules/underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.3.tgz", + "integrity": "sha512-QvjkYpiD+dJJraRA8+dGAU4i7aBbb2s0S3jA45TFOvg2VgqvdCDd/3N6CqA8gluk1W91GLoXg5enMUx560QzuA==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -24501,15 +23039,6 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -25709,6 +24238,12 @@ "text-table": "^0.2.0" } }, + "node_modules/wp-textdomain/node_modules/php-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.0.3.tgz", + "integrity": "sha512-WjbrtYrwmLY9hpoKoq1+mVqJhT0dEVDZRWSpNIw2MpTw3VM/K4C6e0WR4KlU6G/XROkV7tpH4NesV2dDiPxqaw==", + "dev": true + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -27138,68 +25673,6 @@ "minimist": "^1.2.0" } }, - "@cypress/request": { - "version": "2.88.6", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.6.tgz", - "integrity": "sha512-z0UxBE/+qaESAHY9p9sM2h8Y4XqtsbDCt0/DPOrqA/RZgKi4PkxdpXyK4wCCnSk1xHqWHZZAE+gV6aDAR6+caQ==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - } - } - }, - "@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, "@discoveryjs/json-ext": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz", @@ -28040,26 +26513,6 @@ "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", "dev": true }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "peer": true, - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - }, - "dependencies": { - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", - "dev": true, - "peer": true - } - } - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -28726,18 +27179,6 @@ "@types/node": "*" } }, - "@types/sinonjs__fake-timers": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", - "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", - "dev": true - }, - "@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true - }, "@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -28747,98 +27188,12 @@ "@types/node": "*" } }, - "@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true, - "optional": true, - "peer": true - }, "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", "dev": true }, - "@types/tapable": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", - "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", - "dev": true, - "optional": true, - "peer": true - }, - "@types/uglify-js": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", - "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "peer": true - } - } - }, - "@types/webpack": { - "version": "4.41.31", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.31.tgz", - "integrity": "sha512-/i0J7sepXFIp1ZT7FjUGi1eXMCg8HCCzLJEQkKsOtbJFontsJLolBcDC+3qxn5pPwiCt1G0ZdRmYRzNBtvpuGQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@types/node": "*", - "@types/tapable": "^1", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "anymatch": "^3.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "peer": true - } - } - }, - "@types/webpack-sources": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", - "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "optional": true, - "peer": true - } - } - }, "@types/ws": { "version": "8.5.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.2.tgz", @@ -28863,16 +27218,6 @@ "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", "dev": true }, - "@types/yauzl": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", - "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", - "dev": true, - "optional": true, - "requires": { - "@types/node": "*" - } - }, "@use-gesture/core": { "version": "10.2.9", "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.2.9.tgz", @@ -30502,12 +28847,12 @@ "accounting": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/accounting/-/accounting-0.4.1.tgz", - "integrity": "sha1-h91BA+/39EYPHhhvXGd+1s9WaIM=" + "integrity": "sha512-RU6KY9Y5wllyaCNBo1W11ZOTnTHMMgOZkIwdOOs6W5ibMTp72i4xIbEA48djxVGqMNTUNbvrP/1nWg5Af5m2gQ==" }, "acorn": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", - "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "dev": true }, "acorn-globals": { @@ -30668,12 +29013,6 @@ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -30720,12 +29059,6 @@ "picomatch": "^2.0.4" } }, - "arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -30773,23 +29106,6 @@ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", "dev": true }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "peer": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "peer": true - }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -30816,13 +29132,6 @@ "es-abstract": "^1.18.0-next.1" } }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "peer": true - }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -30897,12 +29206,6 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true - }, "async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", @@ -30915,12 +29218,6 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -31301,18 +29598,6 @@ "file-uri-to-path": "1.0.0" } }, - "blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, "blueimp-md5": { "version": "2.18.0", "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.18.0.tgz", @@ -31634,12 +29919,6 @@ "responselike": "^2.0.0" } }, - "cachedir": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", - "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", - "dev": true - }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -31649,13 +29928,6 @@ "get-intrinsic": "^1.0.2" } }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true, - "peer": true - }, "caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -31785,12 +30057,6 @@ "chart.js": "^2.9.3" } }, - "check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", - "dev": true - }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -31937,16 +30203,6 @@ "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==", "dev": true }, - "cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - } - }, "cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", @@ -32166,12 +30422,6 @@ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true }, - "common-tags": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", - "dev": true - }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -32902,199 +31152,6 @@ "fs-exists-sync": "^0.1.0" } }, - "cypress": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-8.7.0.tgz", - "integrity": "sha512-b1bMC3VQydC6sXzBMFnSqcvwc9dTZMgcaOzT0vpSD+Gq1yFc+72JDWi55sfUK5eIeNLAtWOGy1NNb6UlhMvB+Q==", - "dev": true, - "requires": { - "@cypress/request": "^2.88.6", - "@cypress/xvfb": "^1.2.4", - "@types/node": "^14.14.31", - "@types/sinonjs__fake-timers": "^6.0.2", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.0", - "commander": "^5.1.0", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.2", - "enquirer": "^2.3.6", - "eventemitter2": "^6.4.3", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.0", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.5", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "proxy-from-env": "1.0.0", - "ramda": "~0.27.1", - "request-progress": "^3.0.0", - "supports-color": "^8.1.1", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "url": "^0.11.0", - "yauzl": "^2.10.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", - "dev": true - }, - "cli-table3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.0.tgz", - "integrity": "sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==", - "dev": true, - "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^4.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - } - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "requires": { - "ci-info": "^3.2.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -33128,16 +31185,10 @@ } } }, - "dayjs": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.5.tgz", - "integrity": "sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==", - "dev": true - }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } @@ -33441,36 +31492,6 @@ } } }, - "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "dev": true, - "peer": true, - "requires": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - }, - "dependencies": { - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "peer": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "peer": true - } - } - }, "direction": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/direction/-/direction-1.0.4.tgz", @@ -33756,15 +31777,6 @@ "tapable": "^2.2.0" } }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, "entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", @@ -34001,12 +32013,6 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, - "eventemitter2": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.4.tgz", - "integrity": "sha512-HLU3NDY6wARrLCEwyGKRBvuWYyvW6mHYv72SJJAH3iJN3a6eVUvkjFkcxah1bcTgGVBBrFdIopBJPhCQFMLyXw==", - "dev": true - }, "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -34035,75 +32041,6 @@ "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", "dev": true }, - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "requires": { - "pify": "^2.2.0" - } - }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -34523,13 +32460,6 @@ "tslib": "^2.0.3" } }, - "file-type": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", - "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==", - "dev": true, - "peer": true - }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -34944,15 +32874,6 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, - "getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, - "requires": { - "async": "^3.2.0" - } - }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -35009,223 +32930,11 @@ "is-symbol": "^1.0.1" } }, - "global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "requires": { - "ini": "2.0.0" - }, - "dependencies": { - "ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true - } - } - }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, - "globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "dev": true, - "peer": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - }, - "dependencies": { - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true, - "peer": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "peer": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "peer": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "dev": true, - "peer": true, - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "peer": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "peer": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "peer": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "peer": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "peer": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "peer": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "peer": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "peer": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "peer": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "peer": true - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "peer": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } - } - }, "good-listener": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", @@ -35793,12 +33502,6 @@ } } }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -35826,13 +33529,6 @@ "resolved": "https://registry.npmjs.org/iframe-resizer/-/iframe-resizer-4.3.2.tgz", "integrity": "sha512-gOWo2hmdPjMQsQ+zTKbses08mDfDEMh4NneGQNP4qwePYujY1lguqP6gnbeJkf154gojWlBhIltlgnMfYjGHWA==" }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true, - "peer": true - }, "image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", @@ -35840,49 +33536,6 @@ "dev": true, "optional": true }, - "imagemin": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-6.1.0.tgz", - "integrity": "sha512-8ryJBL1CN5uSHpiBMX0rJw79C9F9aJqMnjGnrd/1CafegpNuA81RBAAru/jQQEOWlOJJlpRnlcVFF6wq+Ist0A==", - "dev": true, - "peer": true, - "requires": { - "file-type": "^10.7.0", - "globby": "^8.0.1", - "make-dir": "^1.0.0", - "p-pipe": "^1.1.0", - "pify": "^4.0.1", - "replace-ext": "^1.0.0" - }, - "dependencies": { - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "peer": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "peer": true - } - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "peer": true - } - } - }, "img-loader": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/img-loader/-/img-loader-4.0.0.tgz", @@ -36293,24 +33946,14 @@ "dev": true }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { "is-extglob": "^2.1.1" } }, - "is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "requires": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - } - }, "is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -36415,12 +34058,6 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -38877,12 +36514,6 @@ } } }, - "lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", - "dev": true - }, "lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -38979,29 +36610,6 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" }, - "listr2": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.13.1.tgz", - "integrity": "sha512-pk4YBDA2cxtpM8iLHbz6oEsfZieJKHf6Pt19NlKaHZZVpqHyVs/Wqr7RfBBCeAFCJchGO7WQHVkUPZTvJMHk8w==", - "dev": true, - "requires": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rxjs": "^6.6.7", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true - } - } - }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -39097,12 +36705,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", - "dev": true - }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -39115,121 +36717,6 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -39474,9 +36961,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -40222,12 +37709,6 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=", - "dev": true - }, "p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -40299,13 +37780,6 @@ "aggregate-error": "^3.0.0" } }, - "p-pipe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", - "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", - "dev": true, - "peer": true - }, "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", @@ -40436,13 +37910,6 @@ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true, - "peer": true - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -40506,11 +37973,6 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, - "php-parser": { - "version": "git+ssh://git@github.com/glayzzle/php-parser.git#3279b7ee9bd78b914b5b840edc749eee0fabbfd8", - "dev": true, - "from": "php-parser@^3.0.0-prerelease.8" - }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -40521,12 +37983,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, "pirates": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", @@ -41833,12 +39289,6 @@ "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", "dev": true }, - "pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true - }, "pretty-format": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", @@ -42073,12 +39523,6 @@ "performance-now": "^2.1.0" } }, - "ramda": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz", - "integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==", - "dev": true - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -42747,15 +40191,6 @@ } } }, - "request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", - "dev": true, - "requires": { - "throttleit": "^1.0.0" - } - }, "request-promise-core": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", @@ -43677,50 +41112,6 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true, - "peer": true - }, - "slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - } - } - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -44233,17 +41624,17 @@ } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" } } }, @@ -44736,12 +42127,6 @@ "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", "dev": true }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -44784,15 +42169,6 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", @@ -45065,9 +42441,9 @@ } }, "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.3.tgz", + "integrity": "sha512-QvjkYpiD+dJJraRA8+dGAU4i7aBbb2s0S3jA45TFOvg2VgqvdCDd/3N6CqA8gluk1W91GLoXg5enMUx560QzuA==" }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -45179,12 +42555,6 @@ } } }, - "untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true - }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -46104,6 +43474,14 @@ "moment": "^2.24.0", "php-parser": "^3.0.0-prerelease.8", "text-table": "^0.2.0" + }, + "dependencies": { + "php-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.0.3.tgz", + "integrity": "sha512-WjbrtYrwmLY9hpoKoq1+mVqJhT0dEVDZRWSpNIw2MpTw3VM/K4C6e0WR4KlU6G/XROkV7tpH4NesV2dDiPxqaw==", + "dev": true + } } }, "wrap-ansi": { diff --git a/package.json b/package.json index 9589e033e9..654ab96e94 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,6 @@ "production": "mix --production", "build": "mix --production", "watch": "mix watch", - "test:e2e": "cypress open", "env": "wp-env" }, "repository": { @@ -38,7 +37,6 @@ "axios-mock-adapter": "^1.18.2", "babel-loader": "^8.2.2", "babel-plugin-react-require": "^3.1.3", - "cypress": "^8.7.0", "jest": "^24.9.0", "jest-puppeteer": "^4.4.0", "laravel-mix": "^6.0.34", diff --git a/tests/e2e/README.md b/tests/e2e/README.md deleted file mode 100644 index f3f84bc50f..0000000000 --- a/tests/e2e/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# GiveWP e2e testing - -End-to-end testing (e2e) checks whether GiveWP's features display and function as intended. These tests focus on the output of the webpage and interactions with it. - -## How to run the tests? - -### Prerequisites -These tests run inside a dockerized container, so it is necessary that you have the [Docker Engine](https://docs.docker.com/install/) and [docker-compose](https://docs.docker.com/compose/install/) installed on your system. For a quick installation from scratch, you can simply install the [Docker Desktop app](https://www.docker.com/products/docker-desktop). - -A sample `wordpress.sql` is provided within the `/sample-data/` folder that has a few sample forms, donations, and donors to test in various combinations. - -### Testing - -1. Start local development environment (with docker) by running `npm run env start`. -1. Run `npm run test:e2e` to open the Cypress UI test runner in the browser. -1. Stop the local development environment by running `npm run env stop`. -### Learn More -You can find more information about what e2e testing achieves, how e2e tests are implemented in GiveWP, and how to write your own tests via the [GiveWP dev manual](https://app.gitbook.com/@give/s/givewp/testing/types-of-tests/end-to-end-testing). Happy testing! diff --git a/tests/e2e/fixtures/example.json b/tests/e2e/fixtures/example.json deleted file mode 100644 index 519902d71a..0000000000 --- a/tests/e2e/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} diff --git a/tests/e2e/integration/logs/logs_page_spec.js b/tests/e2e/integration/logs/logs_page_spec.js deleted file mode 100644 index eaf42bf679..0000000000 --- a/tests/e2e/integration/logs/logs_page_spec.js +++ /dev/null @@ -1,80 +0,0 @@ -const cy = window.cy; -const baseURL = window.baseURL; - -describe( 'Test Logs page', function() { - it( 'can use logs table', function() { - // Flush logs - cy.exec( 'wp-env run cli wp give flush-logs' ); - - // Seed logs - cy.exec( 'wp-env run cli "wp give test-logs --type=notice --category=CypressCategory --count=5"' ); - cy.exec( 'wp-env run cli "wp give test-logs --type=error --source=CypressSource"' ); - - cy.visit( baseURL + '/wp-admin/edit.php?post_type=give_forms&page=give-tools&tab=logs' ); - // Logs table is visible - cy.getByTest( 'logs-table' ).should( 'exist' ); - - // Do we have logs displayed - cy.getByTest( 'logs-table' ).find( '.give-table-row' ).should( 'exist' ); - - // View log details - cy.getByTest( 'view-log' ).eq( 0 ).click(); - cy.getByTest( 'log-modal' ).should( 'exist' ); - - // Close log details - cy.getByTest( 'log-modal-close' ).click(); - cy.getByTest( 'log-modal' ).should( 'not.exist' ); - - // Check pagination - cy.get( '.tablenav-pages-navspan' ).last().click(); - cy.getByTest( 'logs-table' ).find( '.give-table-row' ).should( 'exist' ); - - // Sort by status - cy.getByTest( 'logs-status-dropdown' ).select( 'notice' ); - cy.getByTest( 'logs-status-dropdown' ).should( 'have.value', 'notice' ); - - // Wait for the react state to update the DOM - cy.wait( 100 ); - - // Check sorted - cy.getByTest( 'logs-table' ).find( '.give-table-row' ).each( ( row ) => { - cy.wrap( row.children().eq( 0 ) ).should( 'contain.text', 'Notice' ); - } ); - - // Reset status sort - cy.getByTest( 'logs-status-dropdown' ).select( 'All statuses' ); - - // Sort by Category - cy.getByTest( 'logs-category-dropdown' ).select( 'CypressCategory' ); - cy.getByTest( 'logs-category-dropdown' ).should( 'have.value', 'CypressCategory' ); - - // Wait for the react state to update the DOM - cy.wait( 100 ); - - // Check sorted - cy.getByTest( 'logs-table' ).find( '.give-table-row' ).each( ( row ) => { - cy.wrap( row.children().eq( 1 ) ).should( 'contain.text', 'CypressCategory' ); - } ); - - // Reset category sort - cy.getByTest( 'logs-category-dropdown' ).select( 'All categories' ); - - // Sort by Source - cy.getByTest( 'logs-source-dropdown' ).select( 'CypressSource' ); - cy.getByTest( 'logs-source-dropdown' ).should( 'have.value', 'CypressSource' ); - - // Wait for the react state to update the DOM - cy.wait( 100 ); - - // Check sorted - cy.getByTest( 'logs-table' ).find( '.give-table-row' ).each( ( row ) => { - cy.wrap( row.children().eq( 2 ) ).should( 'contain.text', 'CypressSource' ); - } ); - - // Flush logs - cy.getByTest( 'flush-logs-btn' ).click(); - cy.getByTest( 'flush-logs-confirm-btn' ).click(); - cy.getByTest( 'logs-table' ).find( '.give-table-row' ).should( 'not.exist' ); - } ); -} ); - diff --git a/tests/e2e/integration/onboarding/onboarding_wizard_spec.js b/tests/e2e/integration/onboarding/onboarding_wizard_spec.js deleted file mode 100644 index 88fce39f3c..0000000000 --- a/tests/e2e/integration/onboarding/onboarding_wizard_spec.js +++ /dev/null @@ -1,171 +0,0 @@ -const cy = window.cy; -const baseURL = window.baseURL; - -/** - * Test interactions and functionality required to utilize the Onboarding Wizard - */ - -// First, describe this spec, and what you are testing -describe( 'Test onboarding wizard', function() { - // For reach test, describe what it aims to check - it( 'can enable setup page', function() { - cy.visit( baseURL + '/wp-admin/edit.php?post_type=give_forms&page=give-settings&tab=advanced' ); - - // Target inputs by their name attribute - cy.get( 'input[name="setup_page_enabled"][value="enabled"]' ).click(); - cy.get( 'input[name="save"]' ).click(); - cy.visit( baseURL + '/wp-admin' ); - - // Be sure to include some assertion (here, that a link to the Setup Page should now exist) - cy.get( 'a[href="edit.php?post_type=give_forms&page=give-setup"]' ).should( 'exist' ); - } ); - - it( 'can open the onboarding wizard', function() { - cy.visit( baseURL + '/wp-admin/edit.php?post_type=give_forms&page=give-setup' ); - - // When not an input or anchor tag, use get by test to target elements by their data-givewp-test attribute - cy.getByTest( 'setup-configuration' ).click(); - cy.getByTest( 'intro-continue-button' ).should( 'exist' ); - } ); - - it( 'can dismess onboarding wizard', function() { - cy.visit( baseURL + '/wp-admin/?page=give-onboarding-wizard' ); - cy.getByTest( 'dismiss-wizard-link' ).click(); - cy.getByTest( 'setup-configuration' ).should( 'exist' ); - } ); - - it( 'can navigate through the Onboarding Wizard', function() { - cy.visit( baseURL + '/wp-admin/?page=give-onboarding-wizard' ); - - // Intro continue button should lead to cause step - cy.getByTest( 'intro-continue-button' ).click(); - cy.getByTest( 'cause-continue-button' ).should( 'exist' ); - - // Only one fundraising type card should be selected at a time - cy.get( 'label[for="organization"]' ).click(); - cy.get( 'input[value="organization"]' ).should( 'have.attr', 'checked' ); - cy.get( 'input[value="individual"]' ).should( 'not.have.attr', 'checked' ); - - // Cause types should be selectable - cy.getByTest( 'cause-select' ).within( () => { - cy.get( '.givewp-select__value-container' ).click(); - cy.get( '.givewp-select__menu-list > div' ).eq( 2 ).click(); - cy.get( '.givewp-select__value-container' ).contains( 'Environmental' ); - } ); - - // Cause continue button should lead to location step - cy.getByTest( 'cause-continue-button' ).click(); - cy.getByTest( 'location-continue-button' ).should( 'exist' ); - - // Changes to country should update options in state/province and currency inputs - - // Set country to Canada - cy.getByTest( 'country-select' ).within( () => { - cy.get( '.givewp-select__value-container' ).click(); - cy.get( '.givewp-select__menu-list > div' ).eq( 1 ).click(); - } ); - - // Check Canadian provinces - cy.getByTest( 'state-select' ).within( () => { - cy.get( '.givewp-select__value-container' ).click(); - cy.get( '.givewp-select__menu-list > div' ).eq( 1 ).contains( 'Alberta' ); - cy.get( '.givewp-select__menu-list > div' ).eq( 2 ).contains( 'British Columbia' ); - } ); - - // Check Candaian currency - cy.getByTest( 'currency-select' ).within( () => { - cy.get( '.givewp-select__value-container' ).contains( 'Canadian Dollars ($)' ); - } ); - - // Set country to UK - cy.getByTest( 'country-select' ).within( () => { - cy.get( '.givewp-select__value-container' ).click(); - cy.get( '.givewp-select__menu-list > div' ).eq( 2 ).click(); - } ); - - // Check that state select input does not exist - cy.getByTest( 'state-select' ).should( 'not.exist' ); - - // Check UK currency - cy.getByTest( 'currency-select' ).within( () => { - cy.get( '.givewp-select__value-container' ).contains( 'Pounds Sterling (£)' ); - } ); - - // Set country to US - cy.getByTest( 'country-select' ).within( () => { - cy.get( '.givewp-select__value-container' ).click(); - cy.get( '.givewp-select__menu-list > div' ).eq( 0 ).click(); - } ); - - // Check US states - cy.getByTest( 'state-select' ).within( () => { - cy.get( '.givewp-select__value-container' ).click(); - cy.get( '.givewp-select__menu-list > div' ).eq( 1 ).contains( 'Alabama' ); - cy.get( '.givewp-select__menu-list > div' ).eq( 2 ).contains( 'Alaska' ); - } ); - - // Check US currency - cy.getByTest( 'currency-select' ).within( () => { - cy.get( '.givewp-select__value-container' ).contains( 'US Dollars ($)' ); - } ); - - // Location continue button should lead to features step - cy.getByTest( 'location-continue-button' ).click(); - cy.getByTest( 'features-continue-button' ).should( 'exist' ); - - // Multiple feature cards can be selected - cy.get( 'label[for="donation-comments"]' ).click(); - cy.get( 'label[for="terms-conditions"]' ).click(); - cy.get( 'input[value="donation-comments"]' ).should( 'have.attr', 'checked' ); - cy.get( 'input[value="terms-conditions"]' ).should( 'have.attr', 'checked' ); - - // Feature cards can be unselected - cy.get( 'label[for="donation-comments"]' ).click(); - cy.get( 'label[for="terms-conditions"]' ).click(); - cy.get( 'input[value="donation-comments"]' ).should( 'not.have.attr', 'checked' ); - cy.get( 'input[value="terms-conditions"]' ).should( 'not.have.attr', 'checked' ); - - // Features continue button should lead to preview step - cy.getByTest( 'features-continue-button' ).click(); - cy.getByTest( 'preview-continue-button' ).should( 'exist' ); - - // Prevew form iframe should load - cy.getByTest( 'preview-form' ).within( () => { - cy.get( 'iframe' ).its( '0.contentDocument.body' ).should( 'be.visible' ); - } ); - - // Preview continue button should lead to addons step - cy.getByTest( 'preview-continue-button' ).click(); - cy.getByTest( 'addons-continue-button' ).should( 'exist' ); - - // Multiple addon cards can be selected - cy.get( 'label[for="recurring-donations"]' ).click(); - cy.get( 'label[for="donors-cover-fees"]' ).click(); - cy.get( 'input[value="recurring-donations"]' ).should( 'have.attr', 'checked' ); - cy.get( 'input[value="donors-cover-fees"]' ).should( 'have.attr', 'checked' ); - - // Addon cards can be unselected - cy.get( 'label[for="recurring-donations"]' ).click(); - cy.get( 'label[for="donors-cover-fees"]' ).click(); - cy.get( 'input[value="recurring-donations"]' ).should( 'not.have.attr', 'checked' ); - cy.get( 'input[value="donors-cover-fees"]' ).should( 'not.have.attr', 'checked' ); - - // Top navigation should work as expected - - // Check that first step link works as expected - cy.getByTest( 'navigation-step' ).eq( 0 ).click(); - cy.getByTest( 'cause-continue-button' ).should( 'exist' ); - - // Check that third step link works as expected - cy.getByTest( 'navigation-step' ).eq( 2 ).click(); - cy.getByTest( 'features-continue-button' ).should( 'exist' ); - - // Check that last step link works as expected - cy.getByTest( 'navigation-step' ).eq( 4 ).click(); - cy.getByTest( 'addons-continue-button' ).should( 'exist' ); - - // Addons continue button should lead to setup page - cy.getByTest( 'addons-continue-button' ).click(); - cy.getByTest( 'setup-configuration' ).should( 'exist' ); - } ); -} ); diff --git a/tests/e2e/integration/onboarding/setup_page_spec.js b/tests/e2e/integration/onboarding/setup_page_spec.js deleted file mode 100644 index f014e0af19..0000000000 --- a/tests/e2e/integration/onboarding/setup_page_spec.js +++ /dev/null @@ -1,29 +0,0 @@ -const cy = window.cy; -const baseURL = window.baseURL; - -describe( 'Test setup page', function() { - it( 'can enable setup page', function() { - cy.visit( baseURL + '/wp-admin/edit.php?post_type=give_forms&page=give-settings&tab=advanced' ); - cy.get( 'input[name="setup_page_enabled"][value="enabled"]' ).click(); - cy.get( 'input[name="save"]' ).click(); - cy.visit( baseURL + '/wp-admin' ); - cy.get( 'a[href="edit.php?post_type=give_forms&page=give-setup"]' ).should( 'exist' ); - } ); - it( 'can manually launch wizard', function() { - cy.visit( baseURL + '/wp-admin/edit.php?post_type=give_forms&page=give-setup' ); - cy.getByTest( 'setup-configuration' ).click(); - cy.getByTest( 'intro-continue-button' ).should( 'exist' ); - } ); - it( 'can dismiss setup page', function() { - cy.visit( baseURL + '/wp-admin/edit.php?post_type=give_forms&page=give-setup' ); - cy.getByTest( 'setup-dismiss' ).click(); - cy.get( 'a[href="edit.php?post_type=give_forms&page=give-setup"]' ).should( 'not.exist' ); - } ); - it( 'can disable setup page', function() { - cy.visit( baseURL + '/wp-admin/edit.php?post_type=give_forms&page=give-settings&tab=advanced' ); - cy.get( 'input[name="setup_page_enabled"][value="disabled"]' ).click(); - cy.get( 'input[name="save"]' ).click(); - cy.visit( baseURL + '/wp-admin' ); - cy.get( 'a[href="edit.php?post_type=give_forms&page=give-setup"]' ).should( 'not.exist' ); - } ); -} ); diff --git a/tests/e2e/integration/sample_spec.js b/tests/e2e/integration/sample_spec.js deleted file mode 100644 index fe0f548676..0000000000 --- a/tests/e2e/integration/sample_spec.js +++ /dev/null @@ -1,8 +0,0 @@ -const cy = window.cy; -const baseURL = window.baseURL; - -describe( 'View reports', function() { - it( 'can view reports', function() { - cy.visit( baseURL + '/wp-admin/edit.php?post_type=give_forms&page=give-reports#/' ); - } ); -} ); diff --git a/tests/e2e/plugins/index.js b/tests/e2e/plugins/index.js deleted file mode 100644 index a319ff6165..0000000000 --- a/tests/e2e/plugins/index.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable valid-jsdoc, no-unused-vars */ - -/// -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -/** - * @type {Cypress.PluginConfig} - */ -module.exports = ( on, config ) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config -}; diff --git a/tests/e2e/support/commands.js b/tests/e2e/support/commands.js deleted file mode 100644 index 9d8a42b501..0000000000 --- a/tests/e2e/support/commands.js +++ /dev/null @@ -1,41 +0,0 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add("login", (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) - -const cy = window.cy; -const Cypress = window.Cypress; - -window.baseURL = Cypress.env( 'site' ).url; -const baseURL = window.baseURL; - -Cypress.Commands.add( 'getByTest', name => cy.get( `[data-givewp-test="${ name }"]` ) ); - -beforeEach( function() { - cy.visit( baseURL + '/wp-login.php' ); - cy.wait( 1000 ); - cy.get( '#user_login' ).type( Cypress.env( 'wp_user' ) ); - cy.get( '#user_pass' ).type( Cypress.env( 'wp_pass' ) ); - cy.get( '#wp-submit' ).click(); -} ); diff --git a/tests/e2e/support/index.d.ts b/tests/e2e/support/index.d.ts deleted file mode 100644 index ba0967f7dc..0000000000 --- a/tests/e2e/support/index.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -/// - -/** - * This extends the cy command so the IDE is aware of custom commands - */ -declare namespace Cypress { - interface Chainable { - /** - * Retrieves the element by the data-givewp-test attribute. - * Equivalent to cy.get('[data-givewp-test="name"]') - * - * @param name - * - * @example cy.getByTest('email') - */ - getByTest(name: string): Chainable; - } -} \ No newline at end of file diff --git a/tests/e2e/support/index.js b/tests/e2e/support/index.js deleted file mode 100644 index 37a498fb5b..0000000000 --- a/tests/e2e/support/index.js +++ /dev/null @@ -1,20 +0,0 @@ -// *********************************************************** -// This example support/index.js is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands'; - -// Alternatively you can use CommonJS syntax: -// require('./commands') From 510824f4b441570a642b9b315a7d706530278bcc Mon Sep 17 00:00:00 2001 From: Ante Laca Date: Mon, 16 May 2022 23:28:05 +0200 Subject: [PATCH 12/53] Refactor: Move Admin UI repository code into Controllers (#6390) Co-authored-by: Jason Adams --- .../DonationFormsRequestController.php | 112 +++++++++ .../DonationFormsResponseData.php | 167 +++++++++++++ src/DonationForms/Endpoints/ListForms.php | 135 +++-------- .../Repositories/DonationFormsRepository.php | 113 +-------- .../ValueObjects/DonationFormMetaKeys.php | 23 ++ .../components/DonationFormsRowActions.tsx | 2 +- .../DonationsRequestController.php | 165 +++++++++++++ src/Donations/Endpoints/ListDonations.php | 8 +- .../Repositories/DonationRepository.php | 227 +++--------------- .../Controllers/DonorsRequestController.php | 130 ++++++++++ src/Donors/Endpoints/ListDonors.php | 8 +- src/Donors/Repositories/DonorRepository.php | 137 ++--------- .../DonationFormsRepositoryTest.php | 39 +-- 13 files changed, 721 insertions(+), 545 deletions(-) create mode 100644 src/DonationForms/Controllers/DonationFormsRequestController.php create mode 100644 src/DonationForms/DataTransferObjects/DonationFormsResponseData.php create mode 100644 src/DonationForms/ValueObjects/DonationFormMetaKeys.php create mode 100644 src/Donations/Controllers/DonationsRequestController.php create mode 100644 src/Donors/Controllers/DonorsRequestController.php diff --git a/src/DonationForms/Controllers/DonationFormsRequestController.php b/src/DonationForms/Controllers/DonationFormsRequestController.php new file mode 100644 index 0000000000..c5d5d1fb89 --- /dev/null +++ b/src/DonationForms/Controllers/DonationFormsRequestController.php @@ -0,0 +1,112 @@ +request = $request; + } + + /** + * @return array + */ + public function getForms(): array + { + $page = $this->request->get_param('page'); + $perPage = $this->request->get_param('perPage'); + $search = $this->request->get_param('search'); + $status = $this->request->get_param('status'); + + $query = DB::table('posts') + ->select( + 'id', + ['post_date', 'createdAt'], + ['post_date_gmt', 'createdAtGmt'], + ['post_status', 'status'], + ['post_title', 'title'] + ) + ->attachMeta('give_formmeta', 'id', 'form_id', + [DonationFormMetaKeys::FORM_EARNINGS, 'revenue'], + [DonationFormMetaKeys::DONATION_LEVELS, 'donationLevels'], + [DonationFormMetaKeys::SET_PRICE, 'setPrice'], + [DonationFormMetaKeys::GOAL_OPTION, 'goalEnabled'] + ) + ->where('post_type', 'give_forms') + ->limit($perPage) + ->orderBy('id', 'DESC') + ->offset(($page - 1) * $perPage); + + // Status + if ($status === 'any') { + $query->whereIn('post_status', ['publish', 'draft', 'pending', 'private']); + } else { + $query->where('post_status', $status); + } + + // Search + if ($search) { + if (ctype_digit($search)) { + $query->where('ID', $search); + } else { + $searchTerms = array_map('trim', explode(' ', $search)); + foreach ($searchTerms as $term) { + if ($term) { + $query->whereLike('post_title', $term); + } + } + } + } + + return $query->getAll(); + } + + /** + * @return int + */ + public function getTotalFormsCount(): int + { + $search = $this->request->get_param('search'); + $status = $this->request->get_param('status'); + $perPage = $this->request->get_param('perPage'); + + $query = DB::table('posts') + ->where('post_type', 'give_forms'); + + if ($status === 'any') { + $query->whereIn('post_status', ['publish', 'draft', 'pending']); + } else { + $query->where('post_status', $status); + } + + if ($search) { + if (ctype_digit($search)) { + $query->where('ID', $search); + } else { + $query->whereLike('post_title', $search); + } + } + + $query->limit($perPage); + + return $query->count(); + } +} diff --git a/src/DonationForms/DataTransferObjects/DonationFormsResponseData.php b/src/DonationForms/DataTransferObjects/DonationFormsResponseData.php new file mode 100644 index 0000000000..6e61f57d6d --- /dev/null +++ b/src/DonationForms/DataTransferObjects/DonationFormsResponseData.php @@ -0,0 +1,167 @@ +id = $form->id; + $self->name = $form->title; + $self->status = $form->status; + $self->goal = $form->goalEnabled === 'enabled' ? $self->getGoal($form->id) : false; + $self->donations = give()->donationFormsRepository->getFormDonationsCount($form->id); + $self->amount = $self->getFormAmount($form); + $self->revenue = $self->formatAmount($form->revenue ?? ''); + $self->datetime = Date::getDateTime($form->createdAt); + $self->shortcode = sprintf('[give_form id="%d"]', $form->id); + $self->permalink = html_entity_decode(get_permalink($form->id)); + $self->edit = html_entity_decode(get_edit_post_link($form->id)); + + return $self; + } + + /** + * Convert DTO to array + * + * @unreleased + */ + public function toArray(): array + { + return get_object_vars($this); + } + + /** + * @param int $formId + * + * @return array + * + * @unreleased + */ + private function getGoal(int $formId): array + { + $goal = give_goal_progress_stats($formId); + + $getFormatFromGoal = static function ($goal) { + switch ($goal['format']) { + case 'donation': + return _n('donation', 'donations', $goal['raw_goal'], 'give'); + + case 'donors': + return _n('donor', 'donors', $goal['raw_goal'], 'give'); + + case 'amount': + return __('amount', 'give'); + + case 'percentage': + return __('percentage', 'give'); + + default: + return ''; + } + }; + + return [ + 'actual' => html_entity_decode($goal['actual']), + 'goal' => html_entity_decode($goal['goal']), + 'progress' => html_entity_decode($goal['progress']), + 'format' => $getFormatFromGoal($goal) + ]; + } + + /** + * @param object $form + * + * @return string + * + * @unreleased + */ + private function getFormAmount($form): string + { + $donationLevels = unserialize($form->donationLevels, ['allowed_classes' => false]); + + if ( + is_array($donationLevels) + && $amount = array_column($donationLevels, '_give_amount') + ) { + return $this->formatAmount(min($amount)) . ' - ' . $this->formatAmount(max($amount)); + } + + return $this->formatAmount($form->setPrice ?? ''); + } + + /** + * @param string $amount + * + * @return string + * + * @unreleased + */ + private function formatAmount(string $amount): string + { + return html_entity_decode(give_currency_filter(give_format_amount($amount))); + } +} diff --git a/src/DonationForms/Endpoints/ListForms.php b/src/DonationForms/Endpoints/ListForms.php index 99b2e7c469..16bbd208f0 100644 --- a/src/DonationForms/Endpoints/ListForms.php +++ b/src/DonationForms/Endpoints/ListForms.php @@ -2,9 +2,10 @@ namespace Give\DonationForms\Endpoints; +use Give\DonationForms\Controllers\DonationFormsRequestController; +use Give\DonationForms\DataTransferObjects\DonationFormsResponseData; use WP_REST_Request; use WP_REST_Response; -use Give\Helpers\Date; /** * @since 2.19.0 @@ -26,28 +27,28 @@ public function registerRoute() $this->endpoint, [ [ - 'methods' => 'GET', - 'callback' => [$this, 'handleRequest'], + 'methods' => 'GET', + 'callback' => [$this, 'handleRequest'], 'permission_callback' => [$this, 'permissionsCheck'], ], 'args' => [ - 'page' => [ - 'type' => 'integer', - 'required' => false, - 'default' => 1, - 'minimum' => 1 + 'page' => [ + 'type' => 'integer', + 'required' => false, + 'default' => 1, + 'minimum' => 1 ], 'perPage' => [ - 'type' => 'integer', - 'required' => false, - 'default' => 30, - 'minimum' => 1 + 'type' => 'integer', + 'required' => false, + 'default' => 30, + 'minimum' => 1 ], - 'status' => [ - 'type' => 'string', - 'required' => false, - 'default' => 'any', - 'enum' => [ + 'status' => [ + 'type' => 'string', + 'required' => false, + 'default' => 'any', + 'enum' => [ 'publish', 'future', 'draft', @@ -58,9 +59,9 @@ public function registerRoute() 'any' ] ], - 'search' => [ - 'type' => 'string', - 'required' => false + 'search' => [ + 'type' => 'string', + 'required' => false ] ], ] @@ -68,105 +69,29 @@ public function registerRoute() } /** - * @param WP_REST_Request $request + * @param WP_REST_Request $request * * @return WP_REST_Response */ - public function handleRequest(WP_REST_Request $request) + public function handleRequest(WP_REST_Request $request): WP_REST_Response { - $data = []; - $forms = give()->donationFormsRepository->getFormsForRequest($request); - $totalForms = give()->donationFormsRepository->getTotalFormsCountForRequest($request); + $data = []; + $controller = new DonationFormsRequestController($request); + $forms = $controller->getForms(); + $totalForms = $controller->getTotalFormsCount(); $totalPages = (int)ceil($totalForms / $request->get_param('perPage')); foreach ($forms as $form) { - $data[] = [ - 'id' => $form->id, - 'name' => $form->title, - 'status' => $form->status, - 'goal' => $form->goalEnabled === 'enabled' ? $this->getGoal($form->id) : false, - 'donations' => give()->donationFormsRepository->getFormDonationsCount($form->id), - 'amount' => $this->getFormAmount($form), - 'revenue' => $this->formatAmount($form->revenue), - 'datetime' => Date::getDateTime($form->createdAt), - 'shortcode' => sprintf('[give_form id="%d"]', $form->id), - 'permalink' => html_entity_decode(get_permalink($form->id)), - 'edit' => html_entity_decode(get_edit_post_link($form->id)) - ]; + $data[] = DonationFormsResponseData::fromObject($form)->toArray(); } return new WP_REST_Response( [ - 'items' => $data, + 'items' => $data, 'totalItems' => $totalForms, 'totalPages' => $totalPages, - 'trash' => defined('EMPTY_TRASH_DAYS') && EMPTY_TRASH_DAYS > 0, + 'trash' => defined('EMPTY_TRASH_DAYS') && EMPTY_TRASH_DAYS > 0, ] ); } - - /** - * @param int $formId - * - * @return array - */ - private function getGoal($formId) - { - $goal = give_goal_progress_stats($formId); - - $getFormatFromGoal = function ($goal) { - switch ($goal[ 'format' ]) { - case 'donation': - return _n('donation', 'donations', $goal[ 'raw_goal' ], 'give'); - - case 'donors': - return _n('donor', 'donors', $goal[ 'raw_goal' ], 'give'); - - case 'amount': - return __('amount', 'give'); - - case 'percentage': - return __('percentage', 'give'); - - default: - return ''; - } - }; - - return [ - 'actual' => html_entity_decode($goal[ 'actual' ]), - 'goal' => html_entity_decode($goal[ 'goal' ]), - 'progress' => html_entity_decode($goal[ 'progress' ]), - 'format' => $getFormatFromGoal($goal) - ]; - } - - /** - * @param object $form - * - * - * @return string - */ - private function getFormAmount($form) - { - $donationLevels = unserialize($form->donationLevels); - - if (is_array($donationLevels)) { - $amount = array_column($donationLevels, '_give_amount'); - - return $this->formatAmount(min($amount)) . ' - ' . $this->formatAmount(max($amount)); - } - - return $this->formatAmount($form->setPrice); - } - - /** - * @param string $amount - * - * @return string - */ - private function formatAmount($amount) - { - return html_entity_decode(give_currency_filter(give_format_amount($amount))); - } } diff --git a/src/DonationForms/Repositories/DonationFormsRepository.php b/src/DonationForms/Repositories/DonationFormsRepository.php index bf50c5f208..464af1f16e 100644 --- a/src/DonationForms/Repositories/DonationFormsRepository.php +++ b/src/DonationForms/Repositories/DonationFormsRepository.php @@ -2,8 +2,8 @@ namespace Give\DonationForms\Repositories; +use Give\Donations\ValueObjects\DonationMetaKeys; use Give\Framework\Database\DB; -use WP_REST_Request; /** * @since 2.19.0 @@ -11,113 +11,16 @@ class DonationFormsRepository { /** - * @param WP_REST_Request $request - * - * @return array - */ - public function getFormsForRequest(WP_REST_Request $request) - { - $page = $request->get_param('page'); - $perPage = $request->get_param('perPage'); - $search = $request->get_param('search'); - $status = $request->get_param('status'); - - $query = DB::table('posts') - ->select( - ['ID', 'id'], - ['post_date', 'createdAt'], - ['post_date_gmt', 'createdAtGmt'], - ['post_status', 'status'], - ['post_title', 'title'] - ) - ->attachMeta('give_formmeta', 'id', 'form_id', - ['_give_form_earnings', 'revenue'], - ['_give_donation_levels', 'donationLevels'], - ['_give_set_price', 'setPrice'], - ['_give_goal_option', 'goalEnabled'] - ) - ->where('post_type', 'give_forms') - ->limit($perPage) - ->orderBy('id', 'DESC') - ->offset(($page - 1) * $perPage); - - // Status - if ($status === 'any') { - $query->whereIn('post_status', ['publish', 'draft', 'pending', 'private']); - } else { - $query->where('post_status', $status); - } - - // Search - if ($search) { - if (ctype_digit($search)) { - $query->where('ID', $search); - } else { - $searchTerms = array_map('trim', explode(' ', $search)); - foreach ($searchTerms as $term) - { - if ($term) - { - $query->whereLike('post_title', $term); - } - } - } - } - - return $query->getAll(); - } - - /** - * @param WP_REST_Request $request + * @param int $formId * * @return int */ - public function getTotalFormsCountForRequest(WP_REST_Request $request) + public function getFormDonationsCount(int $formId): int { - $search = $request->get_param('search'); - $status = $request->get_param('status'); - $perPage = $request->get_param('perPage'); - - $query = DB::table('posts') - ->selectRaw('SELECT COUNT(ID) AS count') - ->where('post_type', 'give_forms'); - - if ($status === 'any') { - $query->whereIn('post_status', ['publish', 'draft', 'pending']); - } else { - $query->where('post_status', $status); - } - - if ($search) { - if (ctype_digit($search)) { - $query->where('ID', $search); - } else { - $query->whereLike('post_title', $search); - } - } - - $query->limit($perPage); - - $total = $query->get(); - - return $total->count; - } - - /** - * @param int $formId - * - * @return int - */ - public function getFormDonationsCount($formId) - { - $donations = DB::table('posts') - ->selectRaw('SELECT COUNT(ID) as count') - ->leftJoin('give_donationmeta', 'ID', 'donation_id') - ->where('meta_key', '_give_payment_form_id') - ->where('meta_value', $formId) - ->get(); - - - return $donations->count; + return DB::table('posts') + ->leftJoin('give_donationmeta', 'ID', 'donation_id') + ->where('meta_key', DonationMetaKeys::FORM_ID) + ->where('meta_value', $formId) + ->count(); } } diff --git a/src/DonationForms/ValueObjects/DonationFormMetaKeys.php b/src/DonationForms/ValueObjects/DonationFormMetaKeys.php new file mode 100644 index 0000000000..43a1322f04 --- /dev/null +++ b/src/DonationForms/ValueObjects/DonationFormMetaKeys.php @@ -0,0 +1,23 @@ + { const response = await donationFormsApi.fetchWithArgs(endpoint, {ids: [id]}, method); diff --git a/src/Donations/Controllers/DonationsRequestController.php b/src/Donations/Controllers/DonationsRequestController.php new file mode 100644 index 0000000000..3cddeb6695 --- /dev/null +++ b/src/Donations/Controllers/DonationsRequestController.php @@ -0,0 +1,165 @@ +request = $request; + } + + /** + * @unreleased + * + * @return array + */ + public function getDonations(): array + { + $page = $this->request->get_param('page'); + $perPage = $this->request->get_param('perPage'); + + $query = DB::table('posts') + ->distinct() + ->select( + 'id', + ['post_date', 'createdAt'], + ['post_status', 'status'] + ) + ->attachMeta( + 'give_donationmeta', + 'id', + 'donation_id', + DonationMetaKeys::FORM_ID, + DonationMetaKeys::FORM_TITLE, + DonationMetaKeys::AMOUNT, + DonationMetaKeys::DONOR_ID, + DonationMetaKeys::FIRST_NAME, + DonationMetaKeys::LAST_NAME, + DonationMetaKeys::EMAIL, + DonationMetaKeys::GATEWAY, + DonationMetaKeys::MODE, + DonationMetaKeys::ANONYMOUS, + DonationMetaKeys::SUBSCRIPTION_INITIAL_DONATION, + DonationMetaKeys::IS_RECURRING + ) + ->where('post_type', 'give_payment'); + + $query = $this->getWhereConditions($query); + + $query->limit($perPage) + ->orderBy('id', 'DESC') + ->offset(($page - 1) * $perPage); + + $donations = $query->getAll(); + + if (!$donations) { + return []; + } + + return $donations; + } + + /** + * @unreleased + * + * @return int + */ + public function getTotalDonationsCount(): int + { + $query = DB::table('posts') + ->where('post_type', 'give_payment'); + + $query = $this->getWhereConditions($query); + + return $query->count(); + } + + /** + * @param QueryBuilder $query + * @unreleased + * + * @return QueryBuilder + */ + private function getWhereConditions(QueryBuilder $query): QueryBuilder + { + $search = $this->request->get_param('search'); + $start = $this->request->get_param('start'); + $end = $this->request->get_param('end'); + $form = $this->request->get_param('form'); + $donor = $this->request->get_param('donor'); + + if ($form || $donor || ($search && !ctype_digit($search))) { + $query->leftJoin( + 'give_donationmeta', + 'id', + 'metaTable.donation_id', + 'metaTable' + ); + } + + if ($search) { + if (ctype_digit($search)) { + $query->where('id', $search); + } else if (strpos($search, '@') !== false) { + $query + ->where('metaTable.meta_key', DonationMetaKeys::EMAIL) + ->whereLike('metaTable.meta_value', $search); + } else { + $query + ->where('metaTable.meta_key', DonationMetaKeys::FIRST_NAME) + ->whereLike('metaTable.meta_value', $search) + ->orWhere('metaTable.meta_key', DonationMetaKeys::LAST_NAME) + ->whereLike('metaTable.meta_value', $search); + } + } + + if ($donor) { + if (ctype_digit($donor)) { + $query + ->where('metaTable.meta_key', DonationMetaKeys::DONOR_ID) + ->where('metaTable.meta_value', $donor); + } else { + $query + ->where('metaTable.meta_key', DonationMetaKeys::FIRST_NAME) + ->whereLike('metaTable.meta_value', $donor) + ->orWhere('metaTable.meta_key', DonationMetaKeys::LAST_NAME) + ->whereLike('metaTable.meta_value', $donor); + } + } + + if ($form) { + $query + ->where('metaTable.meta_key', DonationMetaKeys::FORM_ID) + ->where('metaTable.meta_value', $form); + } + + if ($start && $end) { + $query->whereBetween('post_date', $start, $end); + } else if ($start) { + $query->where('post_date', $start, '>='); + } else if ($end) { + $query->where('post_date', $end, '<='); + } + + return $query; + } +} diff --git a/src/Donations/Endpoints/ListDonations.php b/src/Donations/Endpoints/ListDonations.php index 86220812ad..76b533eedf 100644 --- a/src/Donations/Endpoints/ListDonations.php +++ b/src/Donations/Endpoints/ListDonations.php @@ -2,6 +2,7 @@ namespace Give\Donations\Endpoints; +use Give\Donations\Controllers\DonationsRequestController; use Give\Donations\DataTransferObjects\DonationResponseData; use WP_REST_Request; use WP_REST_Response; @@ -76,11 +77,12 @@ public function registerRoute() * * @return WP_REST_Response */ - public function handleRequest(WP_REST_Request $request) + public function handleRequest(WP_REST_Request $request): WP_REST_Response { $data = []; - $donations = give()->donations->getDonationsForRequest($request); - $donationsCount = give()->donations->getTotalDonationsCountForRequest($request); + $controller = new DonationsRequestController($request); + $donations = $controller->getDonations(); + $donationsCount = $controller->getTotalDonationsCount(); $totalPages = (int)ceil($donationsCount / $request->get_param('perPage')); foreach ($donations as $donation) { diff --git a/src/Donations/Repositories/DonationRepository.php b/src/Donations/Repositories/DonationRepository.php index a8349ff74d..287b25b9ed 100644 --- a/src/Donations/Repositories/DonationRepository.php +++ b/src/Donations/Repositories/DonationRepository.php @@ -54,13 +54,13 @@ public function __construct() /** * Get Donation By ID * - * @since 2.19.6 - * * @param int $donationId * * @return Donation|null + * @since 2.19.6 + * */ - public function getById($donationId) + public function getById(int $donationId) { return $this->prepareQuery() ->where('ID', $donationId) @@ -81,25 +81,27 @@ public function queryById($donationId) } /** - * @unreleased + * @since 2.19.6 * * @param int $subscriptionId * * @return Donation[]|null + * + * */ - public function getBySubscriptionId($subscriptionId) + public function getBySubscriptionId(int $subscriptionId) { return $this->queryBySubscriptionId($subscriptionId)->getAll(); } /** - * @since 2.19.6 - * * @param int $subscriptionId * * @return ModelQueryBuilder + * @since 2.19.6 + * */ - public function queryBySubscriptionId($subscriptionId) + public function queryBySubscriptionId(int $subscriptionId): ModelQueryBuilder { $initialDonationId = give()->subscriptions->getInitialDonationId($subscriptionId); @@ -118,13 +120,13 @@ public function queryBySubscriptionId($subscriptionId) } /** - * @since 2.19.6 - * * @param int $donorId * * @return ModelQueryBuilder + * @since 2.19.6 + * */ - public function queryByDonorId($donorId) + public function queryByDonorId(int $donorId): ModelQueryBuilder { return $this->prepareQuery() ->where('post_type', 'give_payment') @@ -141,11 +143,11 @@ public function queryByDonorId($donorId) /** * @since 2.20.0 mutate model and return void * @since 2.19.6 - * * @param Donation $donation * * @return void * @throws Exception|InvalidArgumentException + * */ public function insert(Donation $donation) { @@ -167,7 +169,7 @@ public function insert(Donation $donation) 'post_modified_gmt' => get_gmt_from_date($dateCreatedFormatted), 'post_status' => $donation->status->getValue(), 'post_type' => 'give_payment', - 'post_parent' => isset($donation->parentId) ? $donation->parentId : 0, + 'post_parent' => $donation->parentId ?? 0 ]); $donationId = DB::last_insert_id(); @@ -219,6 +221,7 @@ public function insert(Donation $donation) * * @return void * @throws Exception|InvalidArgumentException + * */ public function update(Donation $donation) { @@ -238,7 +241,7 @@ public function update(Donation $donation) 'post_modified_gmt' => get_gmt_from_date($date), 'post_status' => $donation->status->getValue(), 'post_type' => 'give_payment', - 'post_parent' => isset($donation->parentId) ? $donation->parentId : 0, + 'post_parent' => $donation->parentId ?? 0 ]); foreach ($this->getCoreDonationMetaForDatabase($donation) as $metaKey => $metaValue) { @@ -265,13 +268,13 @@ public function update(Donation $donation) /** * @since 2.20.0 consolidate meta deletion into a single query * @since 2.19.6 - * * @param Donation $donation * * @return bool * @throws Exception + * */ - public function delete(Donation $donation) + public function delete(Donation $donation): bool { DB::query('START TRANSACTION'); @@ -303,12 +306,8 @@ public function delete(Donation $donation) /** * @since 2.20.0 update amount to use new type, and add currency and exchange rate * @since 2.19.6 - * - * @param Donation $donation - * - * @return array */ - private function getCoreDonationMetaForDatabase(Donation $donation) + private function getCoreDonationMetaForDatabase(Donation $donation): array { $meta = [ DonationMetaKeys::AMOUNT => give_sanitize_amount_for_db( @@ -361,11 +360,11 @@ private function getCoreDonationMetaForDatabase(Donation $donation) * In Legacy terms, the Initial Donation acts as the parent ID for subscription renewals. * This function inserts those specific meta columns that accompany this concept. * + * @throws Exception * @since 2.19.6 * - * @throws Exception */ - public function updateLegacyDonationMetaAsInitialSubscriptionDonation($donationId) + public function updateLegacyDonationMetaAsInitialSubscriptionDonation($donationId): bool { DB::query('START TRANSACTION'); @@ -401,14 +400,14 @@ public function updateLegacyDonationMetaAsInitialSubscriptionDonation($donationI } /** - * - * @since 2.19.6 * * @param int $donationId * * @return int|null + * @since 2.19.6 + * */ - public function getSequentialId($donationId) + public function getSequentialId(int $donationId) { $query = DB::table('give_sequential_ordering')->where('payment_id', $donationId)->get(); @@ -420,13 +419,13 @@ public function getSequentialId($donationId) } /** - * @since 2.19.6 - * * @param int $id * * @return object[] + * @since 2.19.6 + * */ - public function getNotesByDonationId($id) + public function getNotesByDonationId(int $id): array { $notes = DB::table('give_comments') ->select( @@ -446,11 +445,11 @@ public function getNotesByDonationId($id) } /** - * @since 2.19.6 - * * @param Donation $donation * * @return void + * @since 2.19.6 + * */ private function validateDonation(Donation $donation) { @@ -466,11 +465,11 @@ private function validateDonation(Donation $donation) } /** + * @return DonationMode * @since 2.19.6 * - * @return DonationMode */ - private function getDefaultDonationMode() + private function getDefaultDonationMode(): DonationMode { $mode = give_is_test_mode() ? 'test' : 'live'; @@ -478,13 +477,13 @@ private function getDefaultDonationMode() } /** - * @since 2.19.6 - * * @param int $formId * * @return string + * @since 2.19.6 + * */ - public function getFormTitle($formId) + public function getFormTitle(int $formId): string { $form = DB::table('posts') ->where('id', $formId) @@ -500,7 +499,7 @@ public function getFormTitle($formId) /** * @return ModelQueryBuilder */ - public function prepareQuery() + public function prepareQuery(): ModelQueryBuilder { $builder = new ModelQueryBuilder(Donation::class); @@ -523,12 +522,8 @@ public function prepareQuery() /** * @since 2.19.6 - * - * @param $donorId - * - * @return int */ - public function getTotalDonationCountByDonorId($donorId) + public function getTotalDonationCountByDonorId(int $donorId): int { return (int)DB::table('posts') ->where('post_type', 'give_payment') @@ -543,11 +538,11 @@ public function getTotalDonationCountByDonorId($donorId) } /** - * @since 2.19.6 - * * @param $donorId * * @return array|bool|null + * @since 2.19.6 + * */ public function getAllDonationIdsByDonorId($donorId) { @@ -560,148 +555,4 @@ public function getAllDonationIdsByDonorId($donorId) 'donation_id' ); } - - /** - * @param WP_REST_Request $request - * - * @since 2.20.0 - * - * @return array - */ - public function getDonationsForRequest(WP_REST_Request $request) - { - $page = $request->get_param('page'); - $perPage = $request->get_param('perPage'); - - $query = DB::table('posts') - ->distinct() - ->select( - 'id', - ['post_date', 'createdAt'], - ['post_status', 'status'] - ) - ->attachMeta( - 'give_donationmeta', - 'id', - 'donation_id', - DonationMetaKeys::FORM_ID, - DonationMetaKeys::FORM_TITLE, - DonationMetaKeys::AMOUNT, - DonationMetaKeys::DONOR_ID, - DonationMetaKeys::FIRST_NAME, - DonationMetaKeys::LAST_NAME, - DonationMetaKeys::EMAIL, - DonationMetaKeys::GATEWAY, - DonationMetaKeys::MODE, - DonationMetaKeys::ANONYMOUS, - DonationMetaKeys::SUBSCRIPTION_INITIAL_DONATION, - DonationMetaKeys::IS_RECURRING - ) - ->where('post_type', 'give_payment'); - - $query = $this->getWhereConditionsForRequest($query, $request); - - $query->limit($perPage) - ->orderBy('id', 'DESC') - ->offset(($page - 1) * $perPage); - - $donations = $query->getAll(); - - if (!$donations) { - return []; - } - - return $donations; - } - - /** - * @param WP_REST_Request $request - * - * @since 2.20.0 - * - * @return int - */ - public function getTotalDonationsCountForRequest(WP_REST_Request $request) - { - $query = DB::table('posts') - ->where('post_type', 'give_payment'); - - $query = $this->getWhereConditionsForRequest($query, $request); - - return $query->count(); - } - - /** - * @param QueryBuilder $query - * @param WP_REST_Request $request - * - * @return QueryBuilder - * @since 2.20.0 - * - */ - private function getWhereConditionsForRequest(QueryBuilder $query, WP_REST_Request $request) - { - $search = $request->get_param('search'); - $start = $request->get_param('start'); - $end = $request->get_param('end'); - $form = $request->get_param('form'); - $donor = $request->get_param('donor'); - - if ($form || $donor || ($search && !ctype_digit($search))) { - $query->leftJoin( - 'give_donationmeta', - 'id', - 'metaTable.donation_id', - 'metaTable' - ); - } - - if ($search) { - if (ctype_digit($search)) { - $query->where('id', $search); - } else { - if (strpos($search, '@') !== false) { - $query - ->where('metaTable.meta_key', DonationMetaKeys::EMAIL) - ->whereLike('metaTable.meta_value', $search); - } else { - $query - ->where('metaTable.meta_key', DonationMetaKeys::FIRST_NAME) - ->whereLike('metaTable.meta_value', $search) - ->orWhere('metaTable.meta_key', DonationMetaKeys::LAST_NAME) - ->whereLike('metaTable.meta_value', $search); - } - } - } - - if ($donor) { - if (ctype_digit($donor)) { - $query - ->where('metaTable.meta_key', DonationMetaKeys::DONOR_ID) - ->where('metaTable.meta_value', $donor); - } else { - $query - ->where('metaTable.meta_key', DonationMetaKeys::FIRST_NAME) - ->whereLike('metaTable.meta_value', $donor) - ->orWhere('metaTable.meta_key', DonationMetaKeys::LAST_NAME) - ->whereLike('metaTable.meta_value', $donor); - } - } - - if ($form) { - $query - ->where('metaTable.meta_key', DonationMetaKeys::FORM_ID) - ->where('metaTable.meta_value', $form); - } - - if ($start && $end) { - $query->whereBetween('post_date', $start, $end); - } elseif ($start) { - $query->where('post_date', $start, '>='); - } elseif ($end) { - $query->where('post_date', $end, '<='); - } - - return $query; - } } diff --git a/src/Donors/Controllers/DonorsRequestController.php b/src/Donors/Controllers/DonorsRequestController.php new file mode 100644 index 0000000000..b161bfc9f5 --- /dev/null +++ b/src/Donors/Controllers/DonorsRequestController.php @@ -0,0 +1,130 @@ +request = $request; + } + + /** + * @unreleased + * + * @return array + */ + public function getDonors(): array + { + $page = $this->request->get_param('page'); + $perPage = $this->request->get_param('perPage'); + + $query = DB::table('give_donors') + ->select( + 'id', + ['user_id', 'userId'], + 'email', + 'name', + ['purchase_value', 'donationRevenue'], + ['purchase_count', 'donationCount'], + ['payment_ids', 'paymentIds'], + ['date_created', 'createdAt'] + ) + ->attachMeta( + 'give_donormeta', + 'id', + 'donor_id', + ['_give_donor_title_prefix', 'titlePrefix'] + ) + ->limit($perPage) + ->orderBy('id', 'DESC') + ->offset(($page - 1) * $perPage); + + $query = $this->getWhereConditions($query); + + $query->limit($perPage); + + return $query->getAll(); + } + + /** + * @unreleased + * + * @return int + */ + public function getTotalDonorsCount(): int + { + $query = DB::table('give_donors'); + $query = $this->getWhereConditions($query); + + return $query->count(); + } + + /** + * @param QueryBuilder $builder + * @unreleased + * + * @return QueryBuilder + */ + private function getWhereConditions(QueryBuilder $builder): QueryBuilder + { + $search = $this->request->get_param('search'); + $start = $this->request->get_param('start'); + $end = $this->request->get_param('end'); + $form = $this->request->get_param('form'); + + if ($search) { + if (ctype_digit($search)) { + $builder->where('id', $search); + } else { + $builder->whereLike('name', $search); + $builder->orWhereLike('email', $search); + } + } + + if ($start && $end) { + $builder->whereBetween('date_created', $start, $end); + } else if ($start) { + $builder->where('date_created', $start, '>='); + } else if ($end) { + $builder->where('date_created', $end, '<='); + } + + if ($form) { + $builder + ->whereIn('id', static function (QueryBuilder $builder) use ($form) { + $builder + ->from('give_donationmeta') + ->distinct() + ->select('meta_value') + ->where('meta_key', '_give_payment_donor_id') + ->whereIn('donation_id', static function (QueryBuilder $builder) use ($form) { + $builder + ->from('give_donationmeta') + ->select('donation_id') + ->where('meta_key', '_give_payment_form_id') + ->where('meta_value', $form); + }); + }); + } + + return $builder; + } +} diff --git a/src/Donors/Endpoints/ListDonors.php b/src/Donors/Endpoints/ListDonors.php index 868ce59986..ba5aef8065 100644 --- a/src/Donors/Endpoints/ListDonors.php +++ b/src/Donors/Endpoints/ListDonors.php @@ -2,6 +2,7 @@ namespace Give\Donors\Endpoints; +use Give\Donors\Controllers\DonorsRequestController; use Give\Donors\DataTransferObjects\DonorResponseData; use WP_REST_Request; use WP_REST_Response; @@ -75,11 +76,12 @@ public function registerRoute() * * @return WP_REST_Response */ - public function handleRequest(WP_REST_Request $request) + public function handleRequest(WP_REST_Request $request): WP_REST_Response { $data = []; - $donors = give()->donors->getDonorsForRequest($request); - $donorsCount = give()->donors->getTotalDonorsCountForRequest($request); + $controller = new DonorsRequestController($request); + $donors = $controller->getDonors(); + $donorsCount = $controller->getTotalDonorsCount(); $pageCount = (int)ceil($donorsCount / $request->get_param('perPage')); foreach ($donors as $donor) { diff --git a/src/Donors/Repositories/DonorRepository.php b/src/Donors/Repositories/DonorRepository.php index 27cbb80138..80f20401e7 100644 --- a/src/Donors/Repositories/DonorRepository.php +++ b/src/Donors/Repositories/DonorRepository.php @@ -10,10 +10,8 @@ use Give\Framework\Database\DB; use Give\Framework\Exceptions\Primitives\InvalidArgumentException; use Give\Framework\Models\ModelQueryBuilder; -use Give\Framework\QueryBuilder\QueryBuilder; use Give\Framework\Support\Facades\DateTime\Temporal; use Give\Log\Log; -use WP_REST_Request; /** * @since 2.19.6 @@ -53,7 +51,7 @@ public function queryById($donorId) * @param int $donorId * @return Donor|null */ - public function getById($donorId) + public function getById(int $donorId) { return $this->queryById($donorId)->get(); } @@ -120,7 +118,7 @@ public function insert(Donor $donor) DB::table('give_donors') ->insert([ 'date_created' => Temporal::getFormattedDateTime($dateCreated), - 'user_id' => isset($donor->userId) ? $donor->userId : 0, + 'user_id' => $donor->userId ?? 0, 'email' => $donor->email, 'name' => $donor->name ]); @@ -165,7 +163,7 @@ public function insert(Donor $donor) * @since 2.19.6 * * @param Donor $donor - * @return Donor + * @return void * @throws Exception */ public function update(Donor $donor) @@ -214,7 +212,7 @@ public function update(Donor $donor) * @return bool * @throws Exception */ - public function updateLegacyColumns($donorId, $columns) + public function updateLegacyColumns(int $donorId, array $columns): bool { DB::query('START TRANSACTION'); @@ -247,7 +245,7 @@ public function updateLegacyColumns($donorId, $columns) * * @throws Exception */ - public function delete(Donor $donor) + public function delete(Donor $donor): bool { DB::query('START TRANSACTION'); @@ -278,12 +276,12 @@ public function delete(Donor $donor) * @param Donor $donor * @return array */ - private function getCoreDonorMeta(Donor $donor) + private function getCoreDonorMeta(Donor $donor): array { return [ DonorMetaKeys::FIRST_NAME => $donor->firstName, DonorMetaKeys::LAST_NAME => $donor->lastName, - DonorMetaKeys::PREFIX => isset($donor->prefix) ? $donor->prefix : null, + DonorMetaKeys::PREFIX => $donor->prefix ?? null, ]; } @@ -306,7 +304,7 @@ private function validateDonor(Donor $donor) * @param string $email * @return Donor */ - public function getByEmail($email) + public function getByEmail(string $email) { $donorObjectByPrimaryEmail = $this->prepareQuery() ->where('email', $email) @@ -323,7 +321,7 @@ public function getByEmail($email) * @param string $email * @return Donor */ - public function getByAdditionalEmail($email) + public function getByAdditionalEmail(string $email) { $donorMetaObject = DB::table('give_donormeta') ->select(['donor_id', 'id']) @@ -341,7 +339,7 @@ public function getByAdditionalEmail($email) /** * @return ModelQueryBuilder */ - public function prepareQuery() + public function prepareQuery(): ModelQueryBuilder { $builder = new ModelQueryBuilder(Donor::class); @@ -402,7 +400,7 @@ private function updateAdditionalEmails(Donor $donor) * @param int $donorId * @return string|null */ - public function getDonorLatestDonationDate($donorId) + public function getDonorLatestDonationDate(int $donorId) { $donation = DB::table('posts') ->select('post_date') @@ -426,7 +424,7 @@ public function getDonorLatestDonationDate($donorId) * @param int $donorId * @return string|null */ - public function getDonorType($donorId) + public function getDonorType(int $donorId) { $donor = DB::table('give_donors') ->select( @@ -454,74 +452,21 @@ public function getDonorType($donorId) $recurringDonations = DB::table('posts') ->leftJoin('give_donationmeta', 'id', 'donation_id') ->whereIn('donation_id', $ids) - ->where( 'meta_key', DonationMetaKeys::IS_RECURRING) - ->where( 'meta_value', '1') + ->where('meta_key', DonationMetaKeys::IS_RECURRING) + ->where('meta_value', '1') ->count(); if ($recurringDonations) { return 'subscriber'; } - if ((int)$donor->donationCount > 1 ) { + if ((int)$donor->donationCount > 1) { return 'repeat'; } return 'single'; } - /** - * @param WP_REST_Request $request - * @since 2.20.0 - * - * @return array - */ - public function getDonorsForRequest(WP_REST_Request $request) - { - $page = $request->get_param('page'); - $perPage = $request->get_param('perPage'); - - $query = DB::table('give_donors') - ->select( - 'id', - ['user_id', 'userId'], - 'email', - 'name', - ['purchase_value', 'donationRevenue'], - ['purchase_count', 'donationCount'], - ['payment_ids', 'paymentIds'], - ['date_created', 'createdAt'] - ) - ->attachMeta( - 'give_donormeta', - 'id', - 'donor_id', - ['_give_donor_title_prefix', 'titlePrefix'] - ) - ->limit($perPage) - ->orderBy('id', 'DESC') - ->offset(($page - 1) * $perPage); - - $query = $this->getWhereConditionsForRequest($query, $request); - - $query->limit($perPage); - - return $query->getAll(); - } - - /** - * @param WP_REST_Request $request - * @since 2.20.0 - * - * @return int - */ - public function getTotalDonorsCountForRequest(WP_REST_Request $request) - { - $query = DB::table('give_donors'); - $query = $this->getWhereConditionsForRequest($query, $request); - - return $query->count(); - } - /** * @since 2.20.0 * @return int @@ -530,56 +475,4 @@ public function getDonorsCount() { return DB::table('give_donors')->count(); } - - /** - * @param QueryBuilder $builder - * @param WP_REST_Request $request - * @since 2.20.0 - * - * @return QueryBuilder - */ - private function getWhereConditionsForRequest(QueryBuilder $builder, WP_REST_Request $request) - { - $search = $request->get_param('search'); - $start = $request->get_param('start'); - $end = $request->get_param('end'); - $form = $request->get_param('form'); - - if ($search) { - if (ctype_digit($search)) { - $builder->where('id', $search); - } else { - $builder->whereLike('name', $search); - $builder->orWhereLike('email', $search); - } - } - - if ($start && $end) { - $builder->whereBetween('date_created', $start, $end); - } else if ($start) { - $builder->where('date_created', $start, '>='); - } else if ($end) { - $builder->where('date_created', $end, '<='); - } - - if ($form) { - $builder - ->whereIn('id', static function (QueryBuilder $builder) use ($form) { - $builder - ->from('give_donationmeta') - ->distinct() - ->select('meta_value') - ->where('meta_key', '_give_payment_donor_id') - ->whereIn('donation_id', static function (QueryBuilder $builder) use ($form) { - $builder - ->from('give_donationmeta') - ->select('donation_id') - ->where('meta_key', '_give_payment_form_id') - ->where('meta_value', $form); - }); - }); - } - - return $builder; - } } diff --git a/tests/unit/tests/DonationForms/Repositories/DonationFormsRepositoryTest.php b/tests/unit/tests/DonationForms/Repositories/DonationFormsRepositoryTest.php index aa8a49fdb6..e73a60e180 100644 --- a/tests/unit/tests/DonationForms/Repositories/DonationFormsRepositoryTest.php +++ b/tests/unit/tests/DonationForms/Repositories/DonationFormsRepositoryTest.php @@ -1,6 +1,7 @@ testingForms[] = Give_Helper_Form::create_simple_form(); - $this->testingForms[] = Give_Helper_Form::create_simple_form(); + + // Delete previous donation forms + $posts = DB::prefix('posts'); + DB::query("TRUNCATE TABLE $posts"); + + Give_Helper_Form::create_simple_form(); + Give_Helper_Form::create_simple_form(); } public function tearDown() { parent::tearDown(); - foreach ( $this->testingForms as $form ) - { - Give_Helper_Form::delete_form( $form->id ); - } - $this->testingForms = []; + + $posts = DB::prefix('posts'); + DB::query("TRUNCATE TABLE $posts"); } public function testListDonationForms() @@ -31,15 +35,15 @@ public function testListDonationForms() $request->set_param('perPage', 30); $request->set_param('status', 'any'); - $class = new ReflectionClass(DonationFormsRepository::class); - $getFormsForRequest = $class->getMethod('getFormsForRequest'); - $getFormsForRequest->setAccessible(true); - $forms = $getFormsForRequest->invokeArgs(new DonationFormsRepository, [$request]); + $controller = new DonationFormsRequestController($request); + $forms = $controller->getForms(); + $this->assertEquals(2, count($forms), 'Repository retrieves correct number of total forms'); } - public function testSearchRetrievesCorrectDonationForm(){ - $this->testingForms[] = Give_Helper_Form::create_simple_form( + public function testSearchRetrievesCorrectDonationForm() + { + Give_Helper_Form::create_simple_form( [ 'form' => [ @@ -54,10 +58,9 @@ public function testSearchRetrievesCorrectDonationForm(){ $request->set_param('perPage', 30); $request->set_param('status', 'any'); - $class = new ReflectionClass(DonationFormsRepository::class); - $getFormsForRequest = $class->getMethod('getFormsForRequest'); - $getFormsForRequest->setAccessible(true); - $forms = $getFormsForRequest->invokeArgs(new DonationFormsRepository, [$request]); + $controller = new DonationFormsRequestController($request); + $forms = $controller->getForms(); + $this->assertEquals(1, count($forms), 'Search retrieves a single form'); $this->assertEquals('My Simple Form', $forms[0]->title, 'Search retrieves correct form'); } From 0fe74f105de6e073b53a4a10f11fb041d0b24413 Mon Sep 17 00:00:00 2001 From: Joshua Dinh <75056371+JoshuaHungDinh@users.noreply.github.com> Date: Mon, 16 May 2022 23:14:57 -0700 Subject: [PATCH 13/53] Fix: text aligns properly on offline donations (#6417) * fix: adjust text alignment * fix: display numbered list * fix: adjust margin between elements Co-authored-by: Ravinder Kumar --- .../Templates/Classic/resources/css/_payment-details.scss | 4 ++++ src/Views/Form/Templates/Sequoia/assets/css/form.scss | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Views/Form/Templates/Classic/resources/css/_payment-details.scss b/src/Views/Form/Templates/Classic/resources/css/_payment-details.scss index 5952a45248..f503807290 100644 --- a/src/Views/Form/Templates/Classic/resources/css/_payment-details.scss +++ b/src/Views/Form/Templates/Classic/resources/css/_payment-details.scss @@ -261,6 +261,10 @@ $gatewayFontSize: 1rem; color: var(--give-primary-color); } + > #give_offline_payment_info > p { + margin: 0; + } + > .no-fields { p { margin-inline: auto; diff --git a/src/Views/Form/Templates/Sequoia/assets/css/form.scss b/src/Views/Form/Templates/Sequoia/assets/css/form.scss index 3867ff2383..36a983ddc4 100644 --- a/src/Views/Form/Templates/Sequoia/assets/css/form.scss +++ b/src/Views/Form/Templates/Sequoia/assets/css/form.scss @@ -1021,8 +1021,8 @@ p { #give_offline_payment_info { > ol { - list-style: none; padding: 0; + margin: 0 40px; > li { line-height: 1.4; From 447e4e8ee1ab199940d911af892d9748f6582167 Mon Sep 17 00:00:00 2001 From: Joshua Dinh <75056371+JoshuaHungDinh@users.noreply.github.com> Date: Wed, 18 May 2022 14:18:52 -0700 Subject: [PATCH 14/53] Fix: admin notice's correctly display beneath the header (#6421) * doc: remove additional period * feature: change admin notice position * feature: change admin notice position * fix: update element type * doc: add tag description * fix: add text as comment --- assets/src/js/admin/reports/app/index.js | 3 ++- includes/admin/views/html-admin-settings.php | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/assets/src/js/admin/reports/app/index.js b/assets/src/js/admin/reports/app/index.js index 50e7885e34..b3643eb347 100644 --- a/assets/src/js/admin/reports/app/index.js +++ b/assets/src/js/admin/reports/app/index.js @@ -45,7 +45,8 @@ const App = () => { - +
    + diff --git a/includes/admin/views/html-admin-settings.php b/includes/admin/views/html-admin-settings.php index 4620bedb30..facb4e4654 100644 --- a/includes/admin/views/html-admin-settings.php +++ b/includes/admin/views/html-admin-settings.php @@ -22,7 +22,7 @@ /** * Filter the main form tab. * - * Note: You can stop print main form if you want to.filter dynamically fire on basis of setting page slug + * Note: You can stop print main form if you want to filter dynamically fire on basis of setting page slug * For example: if you register a setting page with give-settings menu slug * then filter will be give-settings_open_form, give-settings_close_form * We are using this filter in includes/admin/tools/class-settings-data.php#L52 @@ -41,6 +41,7 @@ ) ); ?> +
    @@ -69,7 +70,15 @@
    -